HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例
-
📍硬件I2C DMA驱动参考:
https://blog.csdn.net/weixin_45065888/article/details/118225993
-
📌github上的相关项目:
https://github.com/taburyak/STM32_OLED_SSD1306_HAL_DMA
-
🔖本工程基于
STM32F103VCT6
,驱动程序独立,可以移植到任意STM32型号上使用。
📑字体大小说明
- 🌿该驱动程序ASCII字符集类型大小包含:6X8、8X16,12X6 三种。其中6X8和8X16共用一个API函数调用,形参不同。
//针对F6x8、F8X16字体
void OLED_show_char2(uint8_t row, uint8_t col, uint8_t chr, uint8_t size)
{uint8_t x ;uint8_t y;if(size == 8){x = col * 6;y = row * 8;}else {x = col * 8;y = row * 16; }uint8_t temp, t, t1;uint8_t y0 = y;chr = chr - ' ';if(size == 16) {for(t = 0; t < 8; t++) {temp = F8X16[chr*16+t];for(t1 = 0; t1 < 8; t1++) {if(temp & 0x01)OLED_draw_point(x, y, PEN_WRITE);elseOLED_draw_point(x, y, PEN_CLEAR);temp >>= 1;y++;if((y - y0) == 8) {y = y0;x++;break;}}}for(t = 0; t < 8; t++) {temp = F8X16[chr*16+t+8];for(t1 = 0; t1 < 8; t1++) {if(temp & 0x01)OLED_draw_point(x-8, y+8, PEN_WRITE);elseOLED_draw_point(x-8, y+8, PEN_CLEAR);temp >>= 1;y++;if((y - y0) == 8) {y = y0;x++;break;}}} } else {for(t = 0; t < 6; t++) {temp = F6x8[chr][t];for(t1 = 0; t1 < 8; t1++) {if(temp & 0x01)OLED_draw_point(x, y, PEN_WRITE);elseOLED_draw_point(x, y, PEN_CLEAR);temp >>= 1;y++;if((y - y0) == 8) {y = y0;x++;break;}}}}
}
//6X12字体
void OLED_show_char(uint8_t row, uint8_t col, uint8_t chr)
{uint8_t x = col * 6;uint8_t y = row * 12;uint8_t temp, t, t1;uint8_t y0 = y;chr = chr - ' ';for(t = 0; t < 12; t++) {temp = asc2_1206[chr][t];for(t1 = 0; t1 < 8; t1++) {if(temp & 0x80)OLED_draw_point(x, y, PEN_WRITE);elseOLED_draw_point(x, y, PEN_CLEAR);temp <<= 1;y++;if((y - y0) == 12) {y = y0;x++;break;}}}
}
🛠 0.96" SSD1306和1.3" SH1106切换,代码调整
void OLED_set_pos(uint8_t x, uint8_t y)
{OLED_CMDbuf[y][0] = 0x00;OLED_CMDbuf[y][1] = 0xb0 + y;OLED_CMDbuf[y][2] = 0x10;OLED_CMDbuf[y][3] = 0x00; //ssd1306:0x00;sh1106:0x02}
🔨STM32CubeMX配置
-
🌿开启硬件硬件I2C:
-
🌿勾选I2C DMA 发送数据(TX):
- 🌿中断(NVIC)列表勾选
I2C1 event interrupt
,优先级配置,根据个人使用环境配置。
📝测试代码
int main(void)
{/* USER CODE BEGIN 1 */
// float num = 3.14;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_I2C1_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */OLED_init(); //OLED初始化OLED_operate_gram(PEN_CLEAR);//清缓存/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */OLED_operate_gram(PEN_CLEAR);//清缓存OLED_showString(0, 2, (uint8_t*)"China Loong",16);OLED_show_string(2, 3, (uint8_t*)"perseverance");OLED_refresh_gram();//全局刷新HAL_Delay(1500);OLED_operate_gram(PEN_CLEAR);//清缓存OLED_show_string(3, 3, (uint8_t*)"Hello World");OLED_show_string(4, 3, (uint8_t*)"DISPLAY China");OLED_refresh_gram();//全局刷新HAL_Delay(1500);}/* USER CODE END 3 */
}
📚测试例程
链接:https://pan.baidu.com/s/1jkwfS7BmxVZHrDrhvrBWJw?pwd=h6s3
提取码:h6s3
📗基于Github项目例程
- 📍项目地址:
https://github.com/taburyak/STM32_OLED_SSD1306_HAL_DMA
- 🔖 该项目提供了3种ASCII字符集字体:7x10、11x18、16x26。驱动显示提供了硬件I2C加可选DMA传输方式。屏幕类型执行128X64、128X32类型。
- ✨该项目需要自行提前通过STM32CubeMX配置好项目,然后将驱动文件拷贝到工程中。
🛠配置方法
- 🌿STM32CubeMX配置基本工程,如果需要开启DMA需要添加对应的选项。
- 🌿I2C相关配置参数,
ssd1306_defines.h
:
#define SCREEN_TYPE 1 //SSD1306_12864:0 ; SH1106_13264:1
//#define USE_DMA // uncomment if used I2C DMA mode
#define STM32_I2C_PORT hi2c1 // I2C port as defined in main generated by CubeMx
#define SSD1306_ADDRESS 0x3C // I2C address display
#define SSD1306_128X64 // OR #define SSD1306_128X32
- 📄驱动显示示例:
ssd1306_Init();ssd1306_FlipScreenVertically(); //垂直翻转显示 内容旋转180 ssd1306_Clear();ssd1306_SetCursor(0, 0); //显示位置ssd1306_SetColor(White); //设置显示字符颜色ssd1306_WriteString((char*)"Hello World", Font_7x10); //显示字符串 字体类型ssd1306_UpdateScreen();
- 🔧SSD1306/SH1106补充定义:
- 在
ssd1306_defines.h
添加:
#define SCREEN_TYPE 1 //SSD1306_12864:0 ; SH1106_13264:1
- 🔨在
ssd1306.c
文件中调整:
//
// Get a width and height screen size
//
static uint16_t width(void)
{
#if(SCREEN_TYPE)return (SSD1306_WIDTH + 2); //sh1106: +2
#elsereturn SSD1306_WIDTH; //SSD1306#endif
};//
// Position the cursor
//
void ssd1306_SetCursor(uint8_t x, uint8_t y)
{
#if(SCREEN_TYPE)SSD1306.CurrentX = x|0x02; //sh1106: x|0x02
#elseSSD1306.CurrentX = x; //ssd1306: x
#endif SSD1306.CurrentY = y;
}
📓移植到stm32f103驱动工程:
链接:https://pan.baidu.com/s/1pJemQzj9RdLDVsKdlp55OA?pwd=5e5l
提取码:5e5l
🔖此文章仅作为个人学习探索知识的总结,不作为他人或引用者的理论依据,由于学识所限,难免会出现错误或纰漏,欢迎大家指正。