芯片型号:ESP32-S2-MINI-1 开发环境:VS Code + ESP-IDF插件
- 从官方下载u8g2源码:u8g2
- 复制
csrc 文件夹到工程目录下 - 将不必要的外设驱动(
u8x8_d_xxx.c )删除,只保留需要使用的驱动(u8g2_d_memory.c 和u8g2_d_setup.c 要保留),下面以ssd1306 为例,保留u8x8_d_ssd1306_128x64_noname.c 文件 - 删除后,将c/h文件独立放在两个文件夹下:
u8g2
├─inc
│ mui.h
│ mui_u8g2.h
│ u8g2.h
│ u8x8.h
│
└─src
mui.c
mui_u8g2.c
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_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
- 将
u8g2 文件夹放在components 组件下 - 修改
components 组件的CMakeLists.txt
file(GLOB_RECURSE SOURCES u8g2/src/*.c)
idf_component_register(SRCS ${SOURCES}
INCLUDE_DIRS "u8g2/inc")
- 删除
u8g2_d_setup.c 中不必要的内容,只保留u8g2_Setup_ssd1306_128x64_noname_f 函数
#include "u8g2.h"
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_m_16_8_f 函数
#include "u8g2.h"
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
}
- 在
main 组件中新建oled.c 和oled.h oled.h 包含如下头文件
#ifndef __OLED_H_
#define __OLED_H_
#include "u8g2.h"
#include "u8x8.h"
void oled_init(void);
#endif
oled.c 编写u8g2的GPIO和延时回调函数,下面以软件模拟spi为例
#define OLED_SCK (36U)
#define OLED_SDA (35U)
#define OLED_RST (34U)
#define OLED_DC (33U)
u8g2_t u8g2;
static void oled_gpio_init(void)
{
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << OLED_SCK) | (1ULL << OLED_SDA) | (1ULL << OLED_RST) | (1ULL << OLED_DC),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_ENABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
}
uint8_t gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
oled_gpio_init();
break;
case U8X8_MSG_GPIO_SPI_DATA:
gpio_set_level(OLED_SDA, arg_int);
break;
case U8X8_MSG_GPIO_SPI_CLOCK:
gpio_set_level(OLED_SCK, arg_int);
break;
case U8X8_MSG_GPIO_CS:
break;
case U8X8_MSG_GPIO_DC:
gpio_set_level(OLED_DC, arg_int);
break;
case U8X8_MSG_GPIO_RESET:
gpio_set_level(OLED_RST, arg_int);
break;
case U8X8_MSG_DELAY_MILLI:
vTaskDelay(arg_int / portTICK_PERIOD_MS);
break;
default:
return 0;
}
return 1;
}
- 然后调用
u8g2_Setup_ssd1306_128x64_noname_f 函数初始化u8g2
u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, gpio_and_delay_cb);
旋转/镜像 | 描述 |
---|
U8G2_R0 | 无旋转,横向 | U8G2_R1 | 90度顺时针旋转 | U8G2_R2 | 顺时针旋转 180 度 | U8G2_R3 | 270度顺时针旋转 | U8G2_MIRROR | 无旋转、横向、显示内容镜像(v2.6.x) |
其中u8x8_byte_4wire_sw_spi 是u8g2帮我们编写好的软件模拟spi驱动代码,此外,还自带以下几种传输字节的方式:
字节程序 | 描述 |
---|
u8x8_byte_4wire_sw_spi | 标准 8 位 SPI 通信,带“四针”(SCK、MOSI、DC、CS) | u8x8_byte_3wire_sw_spi | 9 位“三针”通信(SCK、MOSI、CS) | u8x8_byte_8bit_6800mode | 并行接口,6800格式 | u8x8_byte_8bit_8080mode | 并行接口,8080格式 | u8x8_byte_sw_i2c | 两线制,I2C 通信 | u8x8_byte_ks0108 | KS0108控制器专用接口 |
函数内部宏的含义为:
信息 | 描述 |
---|
U8X8_MSG_BYTE_INIT | 在显示的初始化阶段发送一次。 | U8X8_MSG_BYTE_SET_DC | 设置数据/命令引脚的电平。arg_int 包含预期的输出水平。用于u8x8_gpio_SetDC(u8x8, arg_int) 向 GPIO 过程发送消息。 | U8X8_MSG_BYTE_START_TRANSFER | 在此处设置片选线。 u8x8->display_info->chip_enable_level 包含预期水平。用于u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level) 调用 GPIO 过程。 | U8X8_MSG_BYTE_SEND | 发送一个或多个字节,位于arg_ptr ,arg_int 包含字节数。 | U8X8_MSG_BYTE_END_TRANSFER | 取消选择设备。从这里使用 CS 级别:u8x8->display_info->chip_disable_level . |
硬件通信需要自己实现,文末会给出参考链接。
void oled_init(void)
{
u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, gpio_and_delay_cb);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
u8g2_ClearBuffer(&u8g2);
}
u8g2_SetFont(&u8g2, u8g2_font_6x12_mr);
u8g2_DrawStr(&u8g2, 0, 30, "hello world");
u8g2_SendBuffer(&u8g2);
参考:
- 移植到新的 MCU 平台
- ESP32 U8G2 library support
- 移植u8g2单色图形库驱动OLED
- YouTube教程
|