本篇讲述使用u8g2图形库I2C驱动oled,设计显示界面。

一.准备工作

      本次使用ssd1306驱动OLED屏,像素分辨率128*64,I2C接口。u8g2是单色显示开源库。u8g2支持lcd和oled,支持众多驱动芯片,包含了SSD1306,具体支持驱动情况可以资源库查看到。使用要I2C2接口

1_oled接线.jpg

图1:OLED接线

二.代码准备
1.在hpm_sdk\samples\drivers\i2c\polling\master生成工程
2.u8g2资源克隆下来后,使用scrc文件里资源。删除u8x8_d_xxx.c非相关驱动源文件.这里选择 ssd1306 128x64。u8g2_d_setup.c源文件选择使用的驱动芯片初始化函数,删除其他。这里保留选择u8g2_Setup_ssd1306_i2c_128x64_noname_f。修改“u8g2_d_memory.c”文件,屏蔽掉没用到的,留下用到的。u8g2_fonts.c文件中定义了各种字库,使能宏U8G2_USE_LARGE_FONTS,使用到GB2312字体库。工程添加U8g2资源文件
2_oled工程文件添加.jpg

图2:u8g2 oled工程

3.有两种驱动方式实现,一种硬件I2C,一种软件I2C.前者有试发现官方库i2c_master_write会报错,这里就以软件I2C来实现。定义宏选择oled类型。
#define SSD1306_128x64  1
#define SSD1306_128x32  2

#define SSD1306_DEVICE  SSD1306_128x64//SSD1306_128x32//
●引脚初始化
void OLED_I2C_Init(void)
{
board_init();
board_init_gpio_pins();
gpio_set_pin_output_with_initial(SCL_GPIO_CTRL, SCL_PORT, SCL_PIN, 1);
gpio_set_pin_output_with_initial(SDA_GPIO_CTRL, SDA_PORT, SDA_PIN, 1);
}
●u8g2初始化
void u8g2_Init(u8g2_t *u8g2)
{
    #if(SSD1306_DEVICE==SSD1306_128x64)
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay);  
    #elif(SSD1306_DEVICE==SSD1306_128x32)
    u8g2_Setup_ssd1306_i2c_128x32_univision_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay);
    #endif
    u8g2_InitDisplay(u8g2);   //                                                                     
    u8g2_SetPowerSave(u8g2, 0);  //唤醒显示器
    u8g2_SetContrast(u8g2, 88);   //设置对比度  
    u8g2_ClearBuffer(u8g2);     //清除显示缓存
}
●这里u8x8_byte_sw_i2c库已实现,用户使用主要实现u8g2_gpio_and_delay如下
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    switch (msg)
    {
    case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
        //__NOP();
         board_delay_us(1);
        break;
    case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
        //for (uint16_t n = 0; n < 320; n++)
        //{
        //    //__NOP();
        //}
        board_delay_us(10);
        break;
    case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
        board_delay_ms(1);
        break;
    case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
        board_delay_us(5);
        break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
    case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
  if(arg_int == 1)  
  {
   // gpio_bits_set(SCL_PORT,SCL_PIN);//SCL=1
            gpio_write_pin(SCL_GPIO_CTRL, SCL_PORT, SCL_PIN, 1);
  }
  else if(arg_int == 0)
  {
   // gpio_bits_reset(SCL_PORT,SCL_PIN);//SCL=0
            gpio_write_pin(SCL_GPIO_CTRL, SCL_PORT, SCL_PIN, 0);
  }   
        break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
    case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
        if(arg_int == 1)  
  {
   // gpio_bits_set(SDA_PORT,SDA_PIN);  //SDA=1
            gpio_write_pin(SDA_GPIO_CTRL, SDA_PORT, SDA_PIN, 1);
  }
  else if(arg_int == 0)
  {
   // gpio_bits_reset(SDA_PORT,SDA_PIN);  //SDA=0
            gpio_write_pin(SDA_GPIO_CTRL, SDA_PORT, SDA_PIN, 0);
  }  
        break;                    // arg_int=1: Input dir with pullup high for I2C data pin
    case U8X8_MSG_GPIO_MENU_SELECT:
        u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_NEXT:
        u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_PREV:
        u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_HOME:
        u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
        break;
    default:
        u8x8_SetGPIOResult(u8x8, 1); // default return value
        break;
    }
    return 1;
}
4.下面就开始设计关于界面
●画对角线
u8g2_ClearBuffer(&u8g2);
u8g2_DrawLine(&u8g2, 0, 0, 128, 64);  
u8g2_SendBuffer(&u8g2);               
u8g2_DrawLine(&u8g2, 0, 64, 128, 0);
u8g2_SendBuffer(&u8g2);
2_对角线.jpg

●画u8g2 logo
void draw(u8g2_t *u8g2)
{
#if(SSD1306_DEVICE==SSD1306_128x64)
u8g2_SetFontMode(u8g2, 1);              /**/
u8g2_SetFontDirection(u8g2, 0);         /**/
u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /**/
u8g2_DrawStr(u8g2, 0, 20, "U");

u8g2_SetFontDirection(u8g2, 1);
u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
u8g2_DrawStr(u8g2, 21, 8, "8");

u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
u8g2_DrawStr(u8g2, 51, 30, "g");
u8g2_DrawStr(u8g2, 67, 30, "\xb2");
u8g2_DrawHLine(u8g2, 2, 35, 47);
u8g2_DrawHLine(u8g2, 3, 36, 47);
u8g2_DrawVLine(u8g2, 45, 32, 12);
u8g2_DrawVLine(u8g2, 46, 33, 12);
u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
u8g2_DrawStr(u8g2, 1, 54, "github.com/olikraus/u8g2");
}
4_U8g2.jpg

●画先楫半导体Logo .图片从官网截图,制作成100*64像素大小
//Logo
u8g2_ClearBuffer(&u8g2);  //
u8g2_DrawXBMP(&u8g2, 14, 0, 100, 64, logo_chip_factory);
u8g2_SendBuffer(&u8g2);
5_原厂Logo.jpg

●下面就是显示中文汉字这些
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312);     
u8g2_DrawUTF8(&u8g2, 0, 16, "面包板社区");
u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312);
u8g2_DrawUTF8(&u8g2, 0, 32, "先楫半导体");

u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312);
u8g2_DrawUTF8(&u8g2, 0, 48, "HPM5301开发板");

u8g2_SetFont(&u8g2, u8g2_font_ncenB10_tr);
u8g2_DrawUTF8(&u8g2, 0, 64, "Author:Cool");
6_汉字.jpg

●最后在while循环里实现渐变同心圆
while(1)
      {
          board_delay_ms(100);
          u8g2_ClearBuffer(&u8g2);//
          #if(SSD1306_DEVICE==SSD1306_128x64)
          if (++t >= 32)
                  t = 1;
          u8g2_DrawCircle(&u8g2, 64, 32, t, U8G2_DRAW_ALL);   //
          u8g2_DrawCircle(&u8g2, 32, 32, t, U8G2_DRAW_ALL);
          u8g2_DrawCircle(&u8g2, 96, 32, t, U8G2_DRAW_ALL);
          u8g2_SendBuffer(&u8g2); //  
          #elif(SSD1306_DEVICE==SSD1306_128x32)
          if (++t >= 16)
                  t = 1;
          u8g2_DrawCircle(&u8g2, 64, 16, t, U8G2_DRAW_ALL);   //
          u8g2_DrawCircle(&u8g2, 32, 16, t, U8G2_DRAW_ALL);
          u8g2_DrawCircle(&u8g2, 96, 16, t, U8G2_DRAW_ALL);
          u8g2_SendBuffer(&u8g2); //  

          #endif

      }
      相比在RT-Thread Studio用库封起来的,这里设计更加自如,且效果也很不错。这里把代码分享下见附件。整体OLED显示效果可看视频。