这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 功率监测与控制系统DIY-03 实现OLED屏幕显示信息

共2条 1/1 1 跳转至

功率监测与控制系统DIY-03 实现OLED屏幕显示信息

助工
2025-06-23 11:48:36     打赏


1. 任务目标

2. OLED 介绍

3. STM32 I2C配置

    3.1 选用 I2C1

    3.2   STM32CubeMX 工程配置

    3.3 PB8 配置为SCL

    3.4 PB9 配置为 SDA

4. PCtoLCD 汉字取模软件

5. 流程图

6. 关键代码

    6.1 主函数

    6.2 I2C 初始化

    6.3 OLED 接口函数

        6.3.1   Oled_Write_Data() 实现

        6.3.2   Oled_Write_Cmd() 实现

    6.4 OLED   API

        6.4.1   OLED_Init() 初始化

        6.4.2   OLED_Fill() 刷屏

        6.4.3   OLED_ShowStr()

        6.4.4   OLED_ShowCN()

7. 实操演示


1. 任务目标

 

实现OLED屏幕显示信息

 

2. OLED 介绍

 

此款 OLED Seeed Studio 出品的 Grove 接口的 0.96英寸 OLED 显示屏,驱动IC SSD1315.

OLED Display 0.96''  SSSD1315 V1.1 分辨率 128x64

供电为 3.3V 或者 5V,通信接口为 I2C


image.png


考虑到电流表 INA219 也是 I2C 通信接口,在STM32开发板上使用同一组I2C硬件,OLEDINA219配置不同的器件地址,就可以一个I2C控制器驱动两个I2C器件。

 

此开发板有 Arduino 接口,恰好把 Seeed Base Shield 扩展板接上。


image.png



 

3. STM32 I2C配置

 

3.1 选用 I2C1

信号

STM32F411 管脚

丝印

SCL

PB8

CN10.3 或者 Arduino.D15

SDA

PB9

CN10.5 或者 Arduino.D14


image.png



Nucleo-F411RE 管脚分配

参考两个文档

        UM1724.pdf》,查看其中的 6.12 ST morpho connector 管脚和 6.10 Extension connections Figure19. NUCLEO-F411RE

        mb1136-default-c04_schematic.pdfPage5Extension connectors

 

3.2 STM32CubeMX 工程配置

 

        Connecity 中选择 I2C1

        在右侧使能 i2c

        配置 I2C 参数为 Standard Mode, 速率 100KHz,地址为7比特,主要的从器件地址为 0x78


image.png


 

3.3 PB8 配置为SCL


image.png



 

3.4 PB9 配置为 SDA


image.png



 

4. PCtoLCD 汉字取模软件

此次任务在OLED上展示中文字符如下:

 

电子产品世界

得捷

你好

功率检测

系统控制

电压电流

 

所有取模的文字:

电子产品世界得捷你好功率监测系统控制电压流

 

PCtoLCD2002 软件配置如下:

        点阵格式:阴码

        取模方式:列行式

        取模走向:逆向(低位在前)

        自定义格式:C51格式,且行前缀、行后缀都为空。


image.png

image.png

 

在输入框输入文字后点击生成字模,拷贝到工程中即可。


5. 流程图


image.png

6. 关键代码

 

6.1 主函数

 

        HAL库初始化

        时钟初始化

        硬件初始化,如GPIOTIMUARTI2C

        OLED初始化,清屏

        显示界面,界面切换,死循环



int main(void)
{
    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_USART2_UART_Init();
    MX_TIM1_Init();
    MX_I2C1_Init();

    /* USER CODE BEGIN 2 */

    printf("\r\n");
    printf("\t\t EEPW_2025_DIY1_Task2_OLED \r\n");
    printf("\t\t Build: %s %s \r\n", __DATE__, __TIME__);
    printf("\r\n");

    HAL_TIM_Base_Start_IT(&htim1);

    OLED_Init();

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
        screen_00_welcome();
        HAL_Delay(1000 * 3);
        screen_01_welcome();
        HAL_Delay(1000 * 3);
        screen_02_diy_power_monitor();
        HAL_Delay(1000 * 5);
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        // HAL_Delay(2000);
    }
    /* USER CODE END 3 */
}


6.2 I2C 初始化

 

这里的初始化代码是 STM32CubeMX 生成的,初始化参数来自界面配置的参数。

 

        函数 MX_I2C1_Init() 先保存 I2C 参数到 hi2c1 结构体上,调用 HAL_I2C_Init() 初始化硬件

        函数 HAL_I2C_MspInit() HAL_I2C_Init() 函数调用,初始化 I2C1 管脚,配置为复用功能


void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 240;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PB8     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = OLED_SCL_Pin|OLED_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }
}


6.3 OLED 接口函数

 

OLED 接口层,主要实现两个函数,其他的 OLED API都是依赖这两个函数

        Oled_Write_Data() 发送数据到 OLED IC

        Oled_Write_Cmd() 发送命令到 OLED IC


6.3.1 Oled_Write_Data() 实现

 

这里直接调用 HAL API OLED 发送数据


void Oled_Write_Data(uint8_t data)
{
    HAL_I2C_Mem_Write(&HI2CX, OLED_ID, OLED_WR_DATA, I2C_MEMADD_SIZE_8BIT, &data, 1, 0x100);
}


6.3.2 Oled_Write_Cmd() 实现

 

这里直接调用 HAL API OLED 发送命令


void Oled_Write_Cmd(uint8_t cmd)
{
    HAL_I2C_Mem_Write(&HI2CX, OLED_ID, OLED_WR_CMD, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 0x100);
}


6.4 OLED API

 

这里仅列举几个常用的 API 实现。

 

6.4.1 OLED_Init() 初始化

 

OLED 上电后需要发送命令配置参数


void OLED_Init(void)
{
    /* 设置显示打开/关闭
     * AE--->显示打开
     * AF--->显示关闭(休眠模式)
     */
    Oled_Write_Cmd(0xAE);

    /* ================== 基本命令表 ===================*/
    /* 设置对比度
     * 0~255:数值越大 亮度越亮
     */
    Oled_Write_Cmd(0x81);
    Oled_Write_Cmd(0xFF);

    /* 使能全屏显示
     * A4--->恢复到RAM内容显示
     * A5--->忽略RAM内容显示
     */
    Oled_Write_Cmd(0xA4);

    /* 设置显示模式
     * A6--->正常显示:0灭1亮
     * A7--->逆显示:1灭0亮
     */
    Oled_Write_Cmd(0xA6);

    /* ================== 滚动命令表 ===================*/
    /* 滚动使能/失能
     * 2E--->失能
     * 2F--->使能
     */
    Oled_Write_Cmd(0x2E);

    /* 七字节命令: 连续水平滚动设置 */

    /* 左/右水平滚动设置
     * 26--->右水平滚动
     * 27--->左水平滚动
     */
    Oled_Write_Cmd(0x26);
    /* 虚拟字节 */
    Oled_Write_Cmd(0x00);
    /* 设置滚动起始页地址 */
    Oled_Write_Cmd(0x00);
    /* 设置滚动间隔 */
    Oled_Write_Cmd(0x03);
    /* 设置滚动结束地址 */
    Oled_Write_Cmd(0x07);
    /* 虚拟字节 */
    Oled_Write_Cmd(0x00);
    Oled_Write_Cmd(0xFF);

    /* =============== 寻址设置命令表 ==================*/

    /* 双字节命令:寄存器寻址模式 */
    Oled_Write_Cmd(0x20);

    /* 10:页寻址模式
     * 01:垂直寻址模式
     * 00:水平寻址模式
     */
    Oled_Write_Cmd(0x10);
    /* 单字节命令:设置页寻址的起始页地址 */
    Oled_Write_Cmd(0xB0);
    /* 单字节命令:设置页寻址的起始列地址低位 */
    Oled_Write_Cmd(0x00);
    /* 单字节命令:设置页寻址的起始列地址高位 */
    Oled_Write_Cmd(0x10);

    /*=============== 硬件配置命令表 ==================*/

    /* 设置显示开始线
     * 0x40~0x7F对应0~63
     */
    Oled_Write_Cmd(0x40);

    /* 设置列重映射
     * A0:addressX--->segX
     * A1:addressX--->seg(127-X)
     */
    Oled_Write_Cmd(0xA1);

    /* 设置多路复用比 */
    Oled_Write_Cmd(0xA8);
    Oled_Write_Cmd(0x3F);

    /* 设置COM输出扫描方向
     * C0:COM0--->COM63(从上往下扫描)
     * C8:COM63--->COM0(从下往上扫描)
     */
    Oled_Write_Cmd(0xC8);

    /* 双字节命令:设置COM显示偏移量 */
    Oled_Write_Cmd(0xD3);
    Oled_Write_Cmd(0x00); /* COM不偏移 */

    /* 双字节命令:配置COM重映射 */
    Oled_Write_Cmd(0xDA);
    Oled_Write_Cmd(0x12);

    /* 双字节命令:设置预充期 */
    Oled_Write_Cmd(0xD9);
    Oled_Write_Cmd(0x22); /* 阶段一2个无效DCLK时钟/阶段二2个无效DCLK时钟 */

    /* 设置VCOMH取消选择电平
     * 00:0.65xVcc
     * 20:0.77xVcc
     * 30:0.83xVcc
     */
    Oled_Write_Cmd(0xDB);
    Oled_Write_Cmd(0x20);

    /* 双字节命令:设置电荷泵 */
    Oled_Write_Cmd(0x8d);
    Oled_Write_Cmd(0x14);

    Oled_Write_Cmd(0xAF);
}


6.4.2 OLED_Fill() 刷屏

 

m 表示page 地址,数值0~7n 表示列地址,数值 0~127

填充的数据 fill_data,设置为0,则屏幕为黑色;设置为1,则屏幕白色;设置为其他值,屏幕显示条纹。



void OLED_Fill(uint8_t fill_data) // 全屏填充
{
    unsigned char m, n;
    for (m = 0; m < 8; m++) {
        Oled_Write_Cmd(0xb0 + m); // page0-page1
        Oled_Write_Cmd(0x00);     // low column start address
        Oled_Write_Cmd(0x10);     // high column start address
        for (n = 0; n < 128; n++) {
            Oled_Write_Data(fill_data);
        }
    }
}


6.4.3 OLED_ShowStr()

 

这里支持两种字体大小,分别是 6x8 8x16 大小。


/**
 * @brief 显示 ASCII 字符,有 6x8 和 8x16 字体大小可以选择
 *
 * @param x 起始点坐标 x [0, 127]
 * @param y 起始点坐标 y [0, 7]
 * @param ch 要显示的字符串
 * @param textsize 1 表示字体大小 6x8; 2 表示字体大小 8x16
 */
void OLED_ShowStr(uint16_t x, uint16_t y, uint8_t ch[], ascii_font_e font)
{
    uint8_t c = 0, i = 0, j = 0;
    switch (font) {
        case ASCII_FONT_6X8: {
            while (ch[j] != '\0') {
                c = ch[j] - 32;
                if (x > 126) {
                    x = 0;
                    y++;
                }
                OLED_SetPos(x, y);
                for (i = 0; i < 6; i++)
                    Oled_Write_Data(FONT_ASCII_6x8[c][i]);
                x += 6;
                j++;
            }
            break;
        }

        case ASCII_FONT_8X16: {
            while (ch[j] != '\0') {
                c = ch[j] - 32;
                if (x > 120) {
                    x = 0;
                    y++;
                }
                OLED_SetPos(x, y);
                for (i = 0; i < 8; i++)
                    Oled_Write_Data(FONT_ASCII_8x16[c * 16 + i]);
                OLED_SetPos(x, y + 1);
                for (i = 0; i < 8; i++)
                    Oled_Write_Data(FONT_ASCII_8x16[c * 16 + i + 8]);
                x += 8;
                j++;
            }
            break;
        }

        default:
            break;
    }
}


6.4.4 OLED_ShowCN()

 

这里只支持一种中文字体大小,16x16


/**
 * @brief 显示 oled_codetab.h 中的汉字,16x16 点阵
 *
 * @param x 起始坐标 x [0, 127]
 * @param y 起始坐标 y [0, 7]
 * @param n 汉字在 16x16 点阵中的索引,下标从0开始
 */
void OLED_ShowCN(uint16_t x, uint16_t y, uint16_t index)
{
    unsigned char wm = 0;
    unsigned int adder = 32 * index;

    OLED_SetPos(x, y);
    for (wm = 0; wm < 16; wm++) {
        Oled_Write_Data(FONT_CN_16x16[adder]);
        adder += 1;
    }
    OLED_SetPos(x, y + 1);
    for (wm = 0; wm < 16; wm++) {
        Oled_Write_Data(FONT_CN_16x16[adder]);
        adder += 1;
    }
}


7. 实操演示

 

显示中文欢迎界面


image.png

 

显示英文欢迎界面


image.png

显示功率检测界面,其中的电压、电流和功率数值是预设值,并非实际测量的。


image.png


VID_20250614_161146 00_00_00-00_00_30.gif





关键词: OLED    

专家
2025-06-25 08:46:03     打赏
2楼

谢谢分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]