一.准备工作
本次使用ssd1306驱动OLED屏,像素分辨率128*64,I2C接口。u8g2是单色显示开源库。u8g2支持lcd和oled,支持众多驱动芯片,包含了SSD1306,具体支持驱动情况可以资源库查看到。使用要I2C2接口
图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: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);
●画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");
}
●画先楫半导体Logo .图片从官网截图,制作成100*64像素大小
//Logo
u8g2_ClearBuffer(&u8g2); //
u8g2_DrawXBMP(&u8g2, 14, 0, 100, 64, logo_chip_factory);
u8g2_SendBuffer(&u8g2);
●下面就是显示中文汉字这些
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");
●最后在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显示效果可看视频。