HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例

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型号上使用。

在这里插入图片描述

📑字体大小说明

✨ 由于不同大小的字符集取模方式不一样,导致字体和API调用函数不能共用一套实现。

  • 🌿该驱动程序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

📓其他代码移植

  • 🌿使用波特律动I2C代码驱动代码基础上,修改为DMA方式。
  • 📍波特律动I2C驱动代码:https://led.baud-dance.com/
  • 📌在线取模地址:https://led.baud-dance.com/

⛳需要注意的事项:

  • 👉中文内容显示,需要将编译器的编码格式设置为:UTF-8.否则中文内容不会显示,或乱码。
    在这里插入图片描述
  • 🔨取模方式:列行式 阳码
    在这里插入图片描述
📚驱动源码:
链接:https://pan.baidu.com/s/1N8CNKIm05QynAkCP2auBzw?pwd=x6q4 
提取码:x6q4

🔖此文章仅作为个人学习探索知识的总结,不作为他人或引用者的理论依据,由于学识所限,难免会出现错误或纰漏,欢迎大家指正。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值