U8G2库移植到STM32平台上

本文详细介绍了如何将U8G2图形库移植到STM32F407VET6微控制器上,用于驱动IIC接口的SSD1306 OLED屏幕。首先从GitHub下载U8G2库,然后选择所需的驱动程序,删除不必要的部分。接着将源码复制到CubeIDE工程中,并编写底层的I2C传输和延时函数。最后,创建并初始化u8g2结构体,实现显示功能。通过这个教程,读者可以了解到STM32与OLED屏幕的硬件接口和软件配置过程。

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

U8G2库简介

U8g2是嵌入式设备的单色图形库,一句话简单明了。主要应用于嵌入式设备,包括我们常见的单片机;

建议先看这篇博客的介绍,写的比较好u8g2库的使用
这篇博客介绍了对于u8g2的使用,但是是针对arduino平台的,但是使用方法在stm32平台上也是大同小异。

U8G2库的下载及硬件平台

U8G2库是一个开源的github项目,通过github可以直接下载 。下载地址

此次使用的mcu是stm32f407vet6,屏幕是IIC接口的oled12864屏幕,屏幕驱动芯片是ssd1306.,使用的是cubeide进行开发。

移植到stm32

首先我们需要建立一份工程,关于工程的建立,再这里就不在赘述了,记住要初始化一个IIC,不然就没有办法驱动屏幕了。

打卡我们下载的u8g2源码,可以看到里面有许多文件夹。其他的文件夹里面都是一些说明文档,可以不用关注,注意我用红框标注的,csrc文件夹,这里面存放的都是我们所需要的源码。
u8g2源码
打开csrc文件夹,可以看到里面有许多.c文件。注意到有许多U8x8_d_*****类型的c文件,这是针对不同的驱动芯片所写的驱动程序,我们只需要选择我们需要的就行了,其他的在移植到自己的工程的时候,可以把删除。我们此次使用的是ssd1306,因此在移植的时候,只保留ssd1306相关的驱动程序就可以了(图中画红线的部分)。

**注意:移植的时候,把不同的驱动芯片的c文件删除即可,不要删除其他的
在这里插入图片描述

然后将csrc文件夹下面的文件都复制到cubeide的工程中,建立好的工程如下图。
cubeide

到这一步就距离成功仅有一步之遥了,接下来编写我们需要的底层函数。

编写一个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(); //I2C初始化
    }
    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
        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
        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); // 初始化 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 */

主函数

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "u8g2.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  u8g2_t u8g2; // a structure which will contain all the data for one display
  u8g2Init(&u8g2);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  //u8g2_DrawCircle(&u8g2, 64, 32, 30, U8G2_DRAW_ALL);
	   u8g2_SendBuffer(&u8g2);
	   u8g2_DrawBox(&u8g2,0,0,20,20);
	   u8g2_DrawBox(&u8g2,20,20,20,20);
	   u8g2_SendBuffer(&u8g2);
	   u8g2_DrawFrame(&u8g2,10,40,20,20);
	   u8g2_SendBuffer(&u8g2);
	   u8g2_SetFont(&u8g2,u8g2_font_DigitalDiscoThin_tf);
	   u8g2_DrawStr(&u8g2,30,10,"free");
	   u8g2_SendBuffer(&u8g2);


	   HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

按照以上进行移植,就可以使用U8G2库了。

成品效果图

在这里插入图片描述

在这里插入图片描述
到这里 u8g2就顺利的移植到 stm32平台上了,
欢迎观看,
有什么问题留言给我哦。

### 将U8g2移植STM32微控制器的方法 #### 准备工作 为了成功将U8g2移植STM32平台,需完成如下准备工作: - **获取必要的资源** - 下载并安装最新版本的STM32CubeMX工具用于创建项目框架。 - 获取目标开发板对应的固件包以及驱动程序。 - 访问[U8g2官方网站](https://github.com/olikraus/u8g2),下载适用于嵌入式系统的U8g2图形源码。 - **环境搭建** - 使用STM32CubeMX配置硬件I2C接口参数,并生成初始化代码。 - 导出工程至Keil MDK或其他IDE环境中编译调试[^1]。 #### 移植过程详解 ##### 配置U8g2支持硬件I2C通信协议 对于采用SSD1306型号OLED屏的情况,在`main.c`文件内定义全局变量实例化结构体对象`u8g2_t u8g2;`。接着调用特定于设备类型的设置函数来指定显示器尺寸、旋转方向等属性;这里选用的是带有F型字体表的128x64分辨率非命名款式的单色屏幕作为例子说明: ```c // 初始化U8G2与硬件连接方式 u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c); ``` 注意上述语句中的第三个参数应替换为实际使用的传输模式——即此处指明利用硬件级联接口进行数据交换操作[u8x8_byte_hw_i2c]()而非软件模拟SPI或SW I2C形式[^2]。 ##### 完成基本显示功能测试 编写简单的循环逻辑绘制圆形图案验证是否能够正常渲染图像内容: ```c while (true) { // 清除缓冲区 u8g2_ClearBuffer(&u8g2); // 更新圆半径大小 if (++t >= 32) t = 1; // 绘制三个不同位置的小球效果 u8g2_DrawCircle(&u8g2, 64, 32, t, U8G2_DRAW_ALL); u8g2_DrawCircle(&u8g2, 32, 32, t, U8G2_DRAW_ALL); u8g2_DrawCircle(&u8g2, 96, 32, t, U8G2_DRAW_ALL); // 刷新物理帧缓存同步更新画面 u8g2_SendBuffer(&u8g2); } ``` 此段代码片段展示了如何通过改变`t`值控制动态变化的视觉呈现效果,同时确保每次迭代都执行刷新命令使新绘图生效[^3]。 #### 常见问题解答 当遇到无法正确显示字符或者图形时可以尝试以下几个方面排查原因: - 检查连线无误尤其是SCL/SDA信号线接触良好; - 确认供电电压范围满足器件规格书要求; - 调整I2C总线速率匹配官方推荐数值; - 查看是否有其他外设干扰导致冲突现象发生。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值