STM32F103基于HAL库移植U8g2库驱动I2C SSD1306 Oled
- 📌
U8g2
库的 GitHub 地址为:https://github.com/olikraus/u8g2
- 📍相关参考文章《stm32移植U8G2图像库指南》
- 《U8G2库移植到STM32平台上》
- 🔰屏幕类型说明:U8g2库仅支持单色屏幕的驱动显示,不支持彩屏,例如ST7735之类的。
- ⚡需要拷贝的原文件夹:
u8g2\u8g2\csrc
- 🌿需要保留的文件名列表如下:
u8g2.h
u8g2_bitmap.c
u8g2_box.c
u8g2_buffer.c
u8g2_button.c
u8g2_circle.c
u8g2_cleardisplay.c
u8g2_d_memory.c
u8g2_d_setup.c
u8g2_font.c
u8g2_fonts.c
u8g2_hvline.c
u8g2_input_value.c
u8g2_intersection.c
u8g2_kerning.c
u8g2_line.c
u8g2_ll_hvline.c
u8g2_message.c
u8g2_polygon.c
u8g2_selection_list.c
u8g2_setup.c
u8log.c
u8log_u8g2.c
u8log_u8x8.c
u8x8.h
u8x8_8x8.c
u8x8_byte.c
u8x8_cad.c
u8x8_capture.c
u8x8_debounce.c
u8x8_display.c
u8x8_d_ssd1306_128x64_noname.c
u8x8_fonts.c
u8x8_gpio.c
u8x8_input_value.c
u8x8_message.c
u8x8_selection_list.c
u8x8_setup.c
u8x8_string.c
u8x8_u16toa.c
u8x8_u8toa.c
- 🔖移除的前缀带
u8x8_d_xxxxxx
的文件,只保留u8x8_d_ssd1306_128x64_noname.c
,例外移除下面这4个文件:
🛠设置显示屏幕接口源文件以及修改显示缓存源文件
- 🌿
u8g2_d_memory.c
与u8g2_d_setup.c
这两个文件。
– ✨针对 u8g2_d_setup.c
文件修改说明:
🚩选择性保留对应接口的构造函数,其他可以都注释,这里这么做主要是为了节省内存空间,将没有使用到的构造函数注释掉,以免在后面编译工程的时候,包内存空间不够用的问题,如果你的芯片内存空间够大,不影响编译通过,可以保留多个构造函数下来。
- 🔖函数的最后一个英文字母
f
代表的是内存。就是一次传输多少字节的数据。f
为1024个字节,2
为256个字节,1
为128个字节
/* ssd1306 f 使用I2C驱动*/
void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
uint8_t tile_buf_height;
uint8_t *buf;
u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
buf = u8g2_m_16_8_f(&tile_buf_height);
u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}
- 🔖如果是使用SPI接口的那么就使用下面这个:
/* ssd1306 f 使用SPI接口驱动*/
void u8g2_Setup_ssd1306_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
uint8_t tile_buf_height;
uint8_t *buf;
u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_001, byte_cb, gpio_and_delay_cb);
buf = u8g2_m_16_8_f(&tile_buf_height);
u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}
- ✨针对
u8g2_d_memory.c
文件修改说明:
- 🚩将
u8g2_d_memory.c
文件内的函数实现都注释掉,选择性启用上面u8g2_d_setup.c
文件中保留下来的函数被调用的函数:u8g2_m_16_8_f(&tile_buf_height);
。
uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
#ifdef U8G2_USE_DYNAMIC_ALLOC
*page_cnt = 8;
return 0;
#else
static uint8_t buf[1024];
*page_cnt = 8;
return buf;
#endif
}
STM32CUBEMX配置I2C
- 🌿根据使用需求配置一个I2C
🔨Keil配置
- 🌿添加源文件。(将上面筛选后的文件夹拷贝到工程目录下,然后将源文件添加到工程当作来。)
- 🌿添加头文件路径。
oled.c和oled.h的文件
- 🌿
oled .c
文件
#include "oled.h"
#include "i2c.h"
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* 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(); //I2C1初始化
// MX_I2C2_Init(); //I2C2初始化
}
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:
{
if (HAL_I2C_Master_Transmit(&hi2c1, (OLED_ADDRESS), buffer, buf_idx, 1000) != HAL_OK)
return 0;
}
break;
case U8X8_MSG_BYTE_SET_DC:
break;
default:
return 0;
}
return 1;
}
void delay_us(uint32_t time)
{
uint32_t i = 8 * time;
while (i--)
;
}
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();
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);
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
arg_int ? HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
// if(arg_int == 1) // arg_int=1: Input dir with pullup high for I2C clock pin
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
// else
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, 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
arg_int ? HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
// if(arg_int == 1) // arg_int=1: Input dir with pullup high for I2C data pin
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
// else if(arg_int == 0)
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
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;
}
void u8g2Init(u8g2_t *u8g2)
{
u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay); // ssd1306 I2C初始化 u8g2 结构体
//u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8x8_gpio_and_delay); // SSD1306 SPI u8g2 结构体
u8g2_InitDisplay(u8g2); // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
u8g2_SetPowerSave(u8g2, 0); // 打开显示器
u8g2_ClearBuffer(u8g2);
}
- 🌿oled.h文件
#ifndef __oled_H
#define __oled_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "u8g2.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#define u8 unsigned char // unsigned char
#define MAX_LEN 128 //
#define OLED_ADDRESS 0x78 // oled模块从机地址
#define OLED_CMD 0x00 // 写命令
#define OLED_DATA 0x40 // 写数据
/* USER CODE BEGIN Prototypes */
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
void u8g2Init(u8g2_t *u8g2);
#ifdef __cplusplus
}
#endif
#endif /*__ i2c_H */
/* USER CODE END Prototypes */
📚工程源码
链接: https://pan.baidu.com/s/1O3InLV7iueFrK9SOmVd6-A
提取码: v369
- 🌿(2024-2-17 更新)HAL库程序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