简介
相信大家或多或少的都用过SSD1306的OLED屏幕,也用它来做过很多的效果。那么在本文中讲介绍如何在ESP-IDF的环境下快速的移植U8G2库。来实现漂亮的动画。
1- 首先访问U8G2的Github页面,并且找到wiki
最下面有一个
点击并且进入
2- 找到ESPIDF的平台,并且点击进入

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

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

就是说,首先我们需要在IDF的项目中创建一个components的文件夹,用于管理外部组件(u8g2)然后把U8g2的代码clone进这个文件夹。剩余的4,5,6 步骤不需要做,因为已经自带了。
5- 下载hal文件 (即整合了ESP32和U8G2的 hardware abstract layer)并且放到了项目中, 由于我这个OLED屏幕是I2C的,所以我删除了所有的SPI的屏幕代码和Hal文件。

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)); // 控制动画速度
}
}效果如下所示

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