这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » [ESP-IDF]在IDF的环境下快速移植集成U8G2

共1条 1/1 1 跳转至

[ESP-IDF]在IDF的环境下快速移植集成U8G2

工程师
2025-11-17 16:41:48     打赏

简介

相信大家或多或少的都用过SSD1306的OLED屏幕,也用它来做过很多的效果。那么在本文中讲介绍如何在ESP-IDF的环境下快速的移植U8G2库。来实现漂亮的动画。


1- 首先访问U8G2的Github页面,并且找到wiki

image.png最下面有一个

点击并且进入


2- 找到ESPIDF的平台,并且点击进入

image.png

3- 访问ESP-32的HAL文件库

image.png

4- 这里给大伙翻译一下具体的操作步骤。英文文档如下所示

image.png


就是说,首先我们需要在IDF的项目中创建一个components的文件夹,用于管理外部组件(u8g2)然后把U8g2的代码clone进这个文件夹。剩余的4,5,6 步骤不需要做,因为已经自带了。

5- 下载hal文件 (即整合了ESP32和U8G2的 hardware abstract layer)并且放到了项目中, 由于我这个OLED屏幕是I2C的,所以我删除了所有的SPI的屏幕代码和Hal文件。

image.png

6- 删除u8g2_esp32_hal.c 中的Switch case 中的 U8X8_MSG_BYTE_INIT 中对I2C初始化的代码,保持如下所示

case U8X8_MSG_BYTE_INIT:
{
if (u8g2_esp32_hal.sda == U8G2_ESP32_HAL_UNDEFINED ||
u8g2_esp32_hal.scl == U8G2_ESP32_HAL_UNDEFINED)
{
break;
}

ESP_LOGI(TAG, "I2C pins set (sda=%d, scl=%d). Assuming I2C driver initialized by app.",
u8g2_esp32_hal.sda, u8g2_esp32_hal.scl);
break;
}

这里一定要删除,否则的话初始化的时候会报时钟错误。


7 - 在对应的HAL 驱动中写下我们自己的I2C初始化

/*
 * u8g2_esp32_hal.h
 *
 *  Created on: Feb 12, 2017
 *      Author: kolban
 */

#ifndef U8G2_ESP32_HAL_H_
#define U8G2_ESP32_HAL_H_
#include "u8g2.h"

#include "driver/gpio.h"
#include "driver/i2c.h"

#define U8G2_ESP32_HAL_UNDEFINED (-1)

#define I2C_MASTER_NUM I2C_NUM_0 // 使用 I2C0
#define I2C_MASTER_SDA_IO 40
#define I2C_MASTER_SCL_IO 41
#define I2C_MASTER_FREQ_HZ 800000 // 400kHz
#define I2C_MASTER_TX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_DISABLE 0

#ifndef ACK_CHECK_EN
#define ACK_CHECK_EN 0x1 //  I2C master will check ack from slave
#endif
#ifndef ACK_CHECK_DIS
#define ACK_CHECK_DIS 0x0 //  I2C master will not check ack from slave
#endif

typedef struct
{
gpio_num_t clk;
gpio_num_t mosi;
gpio_num_t sda; // data for I²C
gpio_num_t scl; // clock for I²C
gpio_num_t cs;
gpio_num_t reset;
gpio_num_t dc;
} u8g2_esp32_hal_t;

#define U8G2_ESP32_HAL_DEFAULT {U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED}

void i2c_master_init(void);
void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param);
uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
#endif /* U8G2_ESP32_HAL_H_ */

然后在U8G2调用之初先调用

i2c_master_init

来初始化I2C。 这样便可以集成完毕。

8 - 在GPT的帮助下让他帮我写了一个雪花的动画。进行测试(原本的Demo效果是显示作者名称)

#include <driver/gpio.h>
#include <driver/i2c.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <u8g2.h>
#include "u8g2_esp32_hal.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define MAX_SNOW 100

typedef struct
{
int x;
int y;
} Snowflake;

static const char *TAG = "snow";

void app_main(void *ignore)
{
i2c_master_init();

u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
u8g2_esp32_hal.sda = I2C_MASTER_SDA_IO;
u8g2_esp32_hal.scl = I2C_MASTER_SCL_IO;
u8g2_esp32_hal_init(u8g2_esp32_hal);

u8g2_t u8g2;
u8g2_Setup_ssd1306_i2c_128x32_univision_f(
&u8g2,
U8G2_R0,
u8g2_esp32_i2c_byte_cb,
u8g2_esp32_gpio_and_delay_cb);

u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);

ESP_LOGI(TAG, "Snowflake animation start!");

srand(time(NULL));

// 初始化雪花
Snowflake snow[MAX_SNOW];
for (int i = 0; i < MAX_SNOW; i++)
{
snow[i].x = rand() % SCREEN_WIDTH;
snow[i].y = rand() % SCREEN_HEIGHT;
}

// FPS 计算
int frames = 0;
int fps = 0;
TickType_t last_tick = xTaskGetTickCount();

while (1)
{
u8g2_ClearBuffer(&u8g2);

// 更新雪花位置
for (int i = 0; i < MAX_SNOW; i++)
{
snow[i].y += 1; // 雪花下落速度
if (snow[i].y >= SCREEN_HEIGHT)
{
snow[i].y = 0;
snow[i].x = rand() % SCREEN_WIDTH;
}
u8g2_DrawPixel(&u8g2, snow[i].x, snow[i].y);
}

// 显示 FPS
frames++;
TickType_t now = xTaskGetTickCount();
if (now - last_tick >= 1000 / portTICK_PERIOD_MS)
{
fps = frames;
frames = 0;
last_tick = now;
}
char fps_str[16];
sprintf(fps_str, "FPS:%d", fps);
u8g2_SetFont(&u8g2, u8g2_font_5x7_tr);
u8g2_DrawStr(&u8g2, 0, 7, fps_str);

u8g2_SendBuffer(&u8g2);
vTaskDelay(pdMS_TO_TICKS(1)); // 控制动画速度
}
}


效果如下所示

27f84d073b3a03ad71fc3c7636195430.jpg

总结

本文详细介绍了如何在ESP-IDF的环境下移植U8G2,并且显示动画效果。实际上当前动画的帧率和CPU的速度无关、因为CPU的速度已经足够快的。 它只和代码中RTOS的delay和I2C的传输速度有关。 如果屏幕采用的是SPI的通讯方式的话,这个速率可以更快!




关键词: ESP-IDF     U8G2    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]