HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例
- 📍基于STM32F103C8T6 LL库驱动版本:
https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM
- 🎬视频演示:
WouoUI移植磁贴案例,新增确认弹窗
- 📍基于标准库驱动,STM32F103RCT6移植u8g2 硬件i2c WouoUI磁贴:
https://gitee.com/henrycrh/stm32-f103-rct6_-wouo-ui/tree/master/STM32F10x_FWlib/src
- 🎬视频演示:
[开源]STM32F103RCT6移植u8g2 > 硬件i2c > WouoUI移植
[开源]STM32F103RCT6移植u8g2 > 硬件i2c > WouoUI移植
- 🔖使用LL库和STD标准库的可以参照上面的例程测试。这里不多种说明。
✅功能部分说明
- 🌿显示部分:U8g2库驱动
- 🌿按键:采用Multi-button库驱动
- 🎞SH1106驱动显示效果:
- 📺I2C SSD1306 0.96"屏幕显示效果:
HAL库程序是基于上面的LL库移植过来的,采用的是STM32F103VET6
。保留了按键控制功能,去掉了其他没有的外设。
-
🔖AC6编译器,优化等级默认
Level 1 (o1)
。
-
🔖AC5编译器,优化等级至少要设置
Level 1 (o1)
,否则会报L6406E
错误。
-
🌿屏蔽相关报警信息
--diag_suppress=1,111,223,1295
- 🌿测试使用1.3“SH1106屏幕显示正常,0.96" ssd1306屏幕会闪屏。
- 📚移植的HAL库程序:
链接:https://pan.baidu.com/s/1Oh3ysdU8-1X0I_JJVVemkg?pwd=slro
提取码:slro
📄HAL库程序引脚说明
STM32F103VET6
按键控制
PE8 上翻页
PE7 下翻页
PB1 确认/长按返回
===================
I2C1 SCL ---- PB6
I2C1 SDA ---- PB7
🔨HAL库程序SSD1306/sh1106屏幕选择与代码调整
- ✨在oled.c中,OLED初始化
OLED_Init(void)
函数。(sh1106屏幕刷SSD1306程序也可以显示,只是边框有一部分是马赛克雪花)
//***************************** 使用下面2个
u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay); //1.3" sh1106 使用这个
// u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay); //0.96"SSD1306使用这个
//****************************** 使用上面2个
🌼U8g2库移植说明
- 🌿可以借用上面的LL库的工程,直接拷贝对应的驱动文件夹到自己所创建的工程目录下。
- 🌿其他屏幕型号,需要提前准备一个能驱动显示的工程作为模板。
- 🌿将以下3个核心函数,拷贝到能显示的模板工程中,根据驱动屏幕型号进行调整:
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);//硬件I2C
uint8_t stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr);
void OLED_Init(void);
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)//硬件I2C
{
/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
static uint8_t buffer[128];
static uint8_t buf_idx;
uint8_t *data;
switch (msg)
{
case U8X8_MSG_BYTE_INIT:
{
/* add your custom code to init i2c subsystem */
MX_I2C1_Init(); //I2C初始化
}
break;
case U8X8_MSG_BYTE_START_TRANSFER:
{
buf_idx = 0;
}
break;
case U8X8_MSG_BYTE_SEND:
{
data = (uint8_t *)arg_ptr;
while (arg_int > 0)
{
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
}
break;
case U8X8_MSG_BYTE_END_TRANSFER:
{
int ret = HAL_I2C_Master_Transmit(&hi2c1, (OLED_ADDRESS), buffer, buf_idx, 1000);
if (ret != HAL_OK)
{
return 0;
}
}
break;
case U8X8_MSG_BYTE_SET_DC:
break;
default:
return 0;
}
return 1;
}
uint8_t stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
#if 0
switch (msg)
{
// case U8X8_MSG_GPIO_AND_DELAY_INIT:
// oled_init();
// break;
case U8X8_MSG_GPIO_SPI_DATA:
if(arg_int)OLED_SDIN_Set();
else OLED_SDIN_Clr();
break;
case U8X8_MSG_GPIO_SPI_CLOCK:
if(arg_int)OLED_SCLK_Set();
else OLED_SCLK_Clr();
break;
case U8X8_MSG_GPIO_CS:
//CS????
case U8X8_MSG_GPIO_DC:
if(arg_int)OLED_DC_Set();
else OLED_DC_Clr();
break;
case U8X8_MSG_GPIO_RESET:
if(arg_int)OLED_RST_Set();
else OLED_RST_Clr();
break;
//Function which delays 100ns
case U8X8_MSG_DELAY_100NANO:
__NOP();
break;
case U8X8_MSG_DELAY_MILLI:
HAL_Delay(arg_int);
break;
default:
return 0;//A message was received which is not implemented, return 0 to indicate an error
}
return 1;
#elif 0
// printf("%s:msg = %d,arg_int = %d\r\n",__FUNCTION__,msg,arg_int);
switch (msg)
{
// case U8X8_MSG_GPIO_AND_DELAY_INIT:
// oled_init();
// break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
__NOP();
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
for (uint16_t n = 0; n < 320; n++)
{
__NOP();
}
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
HAL_Delay(1);
break;
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
// delay 5us
delay_us(5); // 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)
{
LL_GPIO_SetOutputPin(LCD_SCL_GPIO_Port, LCD_SCL_Pin);
// HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_SET);
}
else if (arg_int == 0)
{
LL_GPIO_ResetOutputPin(LCD_SCL_GPIO_Port, LCD_SCL_Pin);
// HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_RESET);
}
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
// printf("U8X8_MSG_GPIO_I2C_DATA:%d\r\n",arg_int);
if (arg_int == 1)
{
LL_GPIO_SetOutputPin(LCD_SDA_GPIO_Port, LCD_SDA_Pin);
// HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_SET);
}
else if (arg_int == 0)
{
LL_GPIO_ResetOutputPin(LCD_SDA_GPIO_Port, LCD_SDA_Pin);
// HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_RESET);
}
break; // arg_int=1: Input dir with pullup high for I2C data pin
default:
u8x8_SetGPIOResult(u8x8, 1); // default return value
break;
}
return 1;
#elif 0
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
break;
case U8X8_MSG_DELAY_MILLI:
HAL_Delay(arg_int);
break;
case U8X8_MSG_GPIO_I2C_CLOCK:
break;
case U8X8_MSG_GPIO_I2C_DATA:
break;
default:
return 0;
}
return 1; // command processed successfully.
#elif 1
switch (msg)
{
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
__NOP();
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
for (uint16_t n = 0; n < 320; n++)
{
__NOP();
}
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
HAL_Delay(1);
break;
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
// delay_us(5);
for (uint16_t n = 0; n < 160; n++)
{
__NOP();
}
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
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
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;
}
#endif
/**
* @brief OLED初始化
*/
void OLED_Init(void)
{
// u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, stm32_gpio_and_delay);
// u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, stm32_gpio_and_delay);
u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
}
📚HAL库U8g2单独驱动程序SSD1306/sh1106屏幕
- 🌿SSD1306/sh1106屏幕选择
// u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_stm32_gpio_and_delay); //1.3" sh1106 使用这个
u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_stm32_gpio_and_delay);//0.96"SSD1306使用这个
链接:https://pan.baidu.com/s/1_hQ1Op00aBoBkjhudml9pw?pwd=6z3u
提取码:6z3u