STM32F103基于HAL库移植U8g2库驱动I2C SSD1306 Oled

文章详细介绍了如何在STM32F103上基于HAL库移植U8g2图形库,以驱动I2C接口的SSD1306OLED屏幕。关键步骤包括选择性保留和修改库文件,配置STM32CubeMX的I2C设置,以及编写特定的硬件延迟和I2C传输函数。提供的代码示例涵盖了I2C通信的初始化和显示初始化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.cu8g2_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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值