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);
else
OLED_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);
else
OLED_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);
else
OLED_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);
else
OLED_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
#else
return 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
#else
SSD1306.CurrentX = x; //ssd1306: x
#endif
SSD1306.CurrentY = y;
}
📓移植到stm32f103驱动工程:
链接:https://pan.baidu.com/s/1pJemQzj9RdLDVsKdlp55OA?pwd=5e5l
提取码:5e5l
🔖此文章仅作为个人学习探索知识的总结,不作为他人或引用者的理论依据,由于学识所限,难免会出现错误或纰漏,欢迎大家指正。