之前介绍了STM32软件IIC和硬件IIC的区别,本期利用STM32上的硬件IIC实现OLED显示屏的使用。

这种0.96寸OLED可能是接触嵌入式的第一个IIC器件,大部分网上实现的方法都是利用软件IIC,但是软件IIC在不同设备之间的移植可能发生时序错误,本期我们利用硬件IIC来实现OLED屏幕的显示。

CubeMX中启用硬件I2C2,连接好SDA和SCL。

由于这块OLED的内部驱动是SSD1306,因此我们需要寻找SSD1306的驱动参考手册。



uint8_t CMD_Data[]={
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
          
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,
          
0xD8, 0x30, 0x8D, 0x14, 0xAF};      //初始化命令


void WriteCmd(void)
{
  uint8_t i = 0;
  for(i=0; i<27; i++)
  {
    HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,CMD_Data+i,1,0x100);
  }
}

//写命令
void OLED_WR_CMD(uint8_t cmd)
{
  HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
//向设备写数据
void OLED_WR_DATA(uint8_t data)
{
  HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}

这个为基础,参考驱动手册编写清空的函数。


void OLED_Clear(void)
{
  uint8_t i, n;

  // 遍历每一页(典型的SSD1306显示器有8页)
  for (i = 0; i < 8; i++)
  {
    // 设置页地址
    OLED_WR_CMD(0xb0 + i);
    // 设置较低列地址为0
    OLED_WR_CMD(0x00);
    // 设置较高列地址为0x10
    OLED_WR_CMD(0x10);

    // 遍历每一列(典型的SSD1306显示器有128列)
    for (n = 0; n < 128; n++)
    {
      // 向显示数据写入0,即关闭像素
      OLED_WR_DATA(0);
    }
  }
}

设置光标位置


void OLED_Set_Pos(uint8_t x, uint8_t y) 
{   
  OLED_WR_CMD(0xb0 + y);                   // 设置页地址
  OLED_WR_CMD(((x & 0xf0) >> 4) | 0x10);  // 设置较高列地址
  OLED_WR_CMD(x & 0x0f);                   // 设置较低列地址
}

  1. OLED_ShowNum 函数:
  • 参数:xy 表示起点坐标,num 表示要显示的数字,len 表示数字的位数,size2 表示字体大小。
  • 作用:在OLED屏幕上显示一个数字。
  • 通过循环取出数字的每一位,根据字体大小在指定位置显示。可以选择填充模式或叠加模式。
  1. OLED_ShowChar 函数:
  • 参数:xy 表示起点坐标,chr 表示要显示的字符,Char_Size 表示选择的字体大小。
  • 作用:在OLED屏幕上显示一个字符。
  • 根据选择的字体大小,选择相应的字体数组,然后在指定位置显示字符。
  1. OLED_ShowString 函数:
  • 参数:xy 表示起点坐标,*chr 表示要显示的字符串,Char_Size 表示选择的字体大小。
  • 作用:在OLED屏幕上显示一个字符串。
  • 循环遍历字符串中的每个字符,调用 OLED_ShowChar 函数逐个显示字符。在显示每个字符后,横坐标 x 增加 8(字符宽度),当横坐标 x 超过一定范围后,纵坐标 y 增加 2(字符高度),横坐标 x 归零。

//显示2个数字
//x,y :起点坐标   
//len :数字的位数
//size:字体大小
//mode:模式  0,填充模式;1,叠加模式
//num:数值(0~4294967295);         
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2)
{           
  uint8_t t,temp;
  uint8_t enshow=0;               
  for(t=0;t128-1){x=0;y=y+2;}
    if(Char_Size ==16)
      {
      OLED_Set_Pos(x,y);  
      for(i=0;i<8;i++)
      OLED_WR_DATA(F8X16[c*16+i]);
      OLED_Set_Pos(x,y+1);
      for(i=0;i<8;i++)
      OLED_WR_DATA(F8X16[c*16+i+8]);
      }
      else {  
        OLED_Set_Pos(x,y);
        for(i=0;i<6;i++)
        OLED_WR_DATA(F6x8[c][i]);
        
      }
}
 
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
  unsigned char j=0;
  while (chr[j]!='\0')
  {    OLED_ShowChar(x,y,chr[j],Char_Size);
      x+=8;
    if(x>120){x=0;y+=2;}
      j++;
  }
}

 

这里需要有字库文件用来显示字符位置。

接着我们测试一下代码


      OLED_Init();//OLED初始化
      OLED_Clear();//刷新屏幕
      OLED_ShowString(0,2,"Hello",2);//显示Hello

嘉立创PCB
全部评论 默认 最新
狗系统
2026-06-04 15:06:20 来自云南
心率血氧看个乐就行了,这玩意一点都不准
没有更多啦~