HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例


  • 📍WouoUI原项目地址:https://github.com/RQNG/WouoUI
  • 📍基于STM32F103C8T6 LL库驱动版本:https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM
  • 🌿串口控制WouoUIPage版本:https://github.com/Sheep118/WouoUI-PageVersion
  • 🎬视频演示:

WouoUI移植磁贴案例,新增确认弹窗


  • 📍基于标准库驱动,STM32F103RCT6移植u8g2 硬件i2c WouoUI磁贴:https://gitee.com/henrycrh/stm32-f103-rct6_-wouo-ui/tree/master/STM32F10x_FWlib/src
  • 🎬视频演示:

[开源]STM32F103RCT6移植u8g2 > 硬件i2c > WouoUI移植

  • 🔖使用LL库和STD标准库的可以参照上面的例程测试。这里不多作说明。
  • 🔖串口控制WouoUIPage版本,该开源项目原作者,提供了较为详细的项目介绍和API接口使用说明,这里不做过多说明,该项目耦合度低,移植方便。原项目stm32 demo默认使用的是标准库SPI,这里会提供一个,移植到使用HAL库的I2C DMA方式的工程。
✅功能部分说明
  • 🌿显示部分: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
  • 🌿测试使用1.3“SH1106屏幕显示正常,0.96" ssd1306屏幕会闪屏。
  • 📚移植的HAL库程序:
链接:https://pan.baidu.com/s/1Oh3ysdU8-1X0I_JJVVemkg?pwd=slro 
提取码:slro

   
   
  • 1
  • 2
📄HAL库程序引脚说明
STM32F103VET6
按键控制
PE8 上翻页
PE7 下翻页
PB1  确认/长按返回
===================
	  I2C1   SCL ---- PB6
	  I2C1   SDA ---- PB7

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
🔨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个

   
   
  • 1
  • 2
  • 3
  • 4
🌼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);

   
   
  • 1
  • 2
  • 3
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;
<span class="token keyword">switch</span> <span class="token punctuation">(</span>msg<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
	<span class="token keyword">case</span> U8X8_MSG_BYTE_INIT<span class="token operator">:</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token comment">/* add your custom code to init i2c subsystem */</span>
		<span class="token function">MX_I2C1_Init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//I2C初始化</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
	<span class="token keyword">case</span> U8X8_MSG_BYTE_START_TRANSFER<span class="token operator">:</span>
	<span class="token punctuation">{<!-- --></span>
		buf_idx <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
	<span class="token keyword">case</span> U8X8_MSG_BYTE_SEND<span class="token operator">:</span>
	<span class="token punctuation">{<!-- --></span>
		data <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span>arg_ptr<span class="token punctuation">;</span>
		<span class="token keyword">while</span> <span class="token punctuation">(</span>arg_int <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
		<span class="token punctuation">{<!-- --></span>
			buffer<span class="token punctuation">[</span>buf_idx<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator">*</span>data<span class="token punctuation">;</span>
			data<span class="token operator">++</span><span class="token punctuation">;</span>
			arg_int<span class="token operator">--</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
	<span class="token keyword">case</span> U8X8_MSG_BYTE_END_TRANSFER<span class="token operator">:</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token keyword">int</span> ret <span class="token operator">=</span> <span class="token function">HAL_I2C_Master_Transmit</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>hi2c1<span class="token punctuation">,</span> <span class="token punctuation">(</span>OLED_ADDRESS<span class="token punctuation">)</span><span class="token punctuation">,</span> buffer<span class="token punctuation">,</span> buf_idx<span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>ret <span class="token operator">!=</span> HAL_OK<span class="token punctuation">)</span>
		<span class="token punctuation">{<!-- --></span>
			<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
	<span class="token keyword">case</span> U8X8_MSG_BYTE_SET_DC<span class="token operator">:</span>
			<span class="token keyword">break</span><span class="token punctuation">;</span>
	<span class="token keyword">default</span><span class="token operator">:</span>
			<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>

}

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

<span class="token keyword">case</span> U8X8_MSG_GPIO_I2C_CLOCK<span class="token operator">:</span> <span class="token comment">// arg_int=0: Output low at I2C clock pin</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>arg_int <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token function">LL_GPIO_SetOutputPin</span><span class="token punctuation">(</span>LCD_SCL_GPIO_Port<span class="token punctuation">,</span> LCD_SCL_Pin<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">//        HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_SET);</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>arg_int <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token function">LL_GPIO_ResetOutputPin</span><span class="token punctuation">(</span>LCD_SCL_GPIO_Port<span class="token punctuation">,</span> LCD_SCL_Pin<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">//        HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_RESET);</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>					 <span class="token comment">// arg_int=1: Input dir with pullup high for I2C clock pin</span>
<span class="token keyword">case</span> U8X8_MSG_GPIO_I2C_DATA<span class="token operator">:</span> <span class="token comment">// arg_int=0: Output low at I2C data pin</span>
	<span class="token comment">//  printf("U8X8_MSG_GPIO_I2C_DATA:%d\r\n",arg_int);</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>arg_int <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token function">LL_GPIO_SetOutputPin</span><span class="token punctuation">(</span>LCD_SDA_GPIO_Port<span class="token punctuation">,</span> LCD_SDA_Pin<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">//        HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_SET);</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>arg_int <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		<span class="token function">LL_GPIO_ResetOutputPin</span><span class="token punctuation">(</span>LCD_SDA_GPIO_Port<span class="token punctuation">,</span> LCD_SDA_Pin<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">//        HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_RESET);</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token comment">// arg_int=1: Input dir with pullup high for I2C data pin</span>

<span class="token keyword">default</span><span class="token operator">:</span>
	<span class="token function">u8x8_SetGPIOResult</span><span class="token punctuation">(</span>u8x8<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// default return value</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>

#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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
📚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使用这个

 
 
  • 1
  • 2
链接:https://pan.baidu.com/s/1_hQ1Op00aBoBkjhudml9pw?pwd=6z3u 
提取码:6z3u

 
 
  • 1
  • 2
📚串口控制WouoUIPage STM32 HAL库I2C DMA方式工程版本
  • 🔖基于STM32F103,兼容SSD1306/sh1106。在oled.h中修改对应宏,决定选择屏幕类型
#define SH1106_OLED    0
#define SSD1306_OLED    1
#define  SCREEN_TYPE   SH1106_OLED    //SSD1306:0 ; SH1106:1

 
 
  • 1
  • 2
  • 3
  • 🔖测试方法:推荐使用带快捷键配置串口发送指令的串口调试助手,例如SSCOM、正点原子串口调试助手
    在这里插入图片描述
    在这里插入图片描述
链接:https://pan.baidu.com/s/1gh1-SFdA_IzaArTd_w4LWQ?pwd=hr3k 
提取码:hr3k

 
 
  • 1
  • 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值