ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

U8g2 on RT-Thread:在 RT-Thread RTOS 上移植与使用 U8g2 单色屏图形库完整指南

U8g2 on RT-Thread:在 RT-Thread RTOS 上移植与使用 U8g2 单色屏图形库完整指南 嵌入式嵌入式GUI驱动开发【免费下载链接】u8g2U8glib library for monochrome displays, version 2项目地址https://gitcode.com/gh_mirrors/u8/u8g2点击查看免费下载U8g2 是面向单色显示屏的通用图形库U8glib 第二版本指南围绕其官方 RT-Thread 移植层讲解如何在 RT-Thread 实时操作系统中完成 U8g2 的接入、配置、编译与示例运行。读完本文你将掌握从 RT-Thread Studio / ENV 工具链起步、按需裁剪 U8g2 功能、通过软件/硬件 I2C、软件/硬件 SPI 及 8080 并行接口驱动 OLED/LCD并理解移植层源码中 GPIO、延时与总线字节函数的底层实现原理。RT-Thread 平台概览U8g2 的宿主 RTOSRT-Thread 是一款开源的、中立且以社区为基础的实时操作系统RTOS提供Standard标准版和Nano 版两种形态。对于资源受限的微控制器MCU系统Nano 版仅需约3 KB Flash 与 1.2 KB RAM并可通过易用的工具进行裁剪定制对于资源充裕的物联网设备RT-Thread 可通过在线软件包管理工具配合系统配置工具实现直观、快速的模块化裁剪无缝导入丰富的软件包从而支持类似 Android 的图形界面、触摸滑动效果、智能语音交互等复杂功能。官方 READMEsys/rt-thread/README.md罗列了 RT-Thread 的关键特性为资源受限设备设计最小内核仅需 1.2 KB RAM 与 3 KB Flash提供多种标准接口如 POSIX、CMSIS、C 应用环境拥有丰富的组件和快速成长的软件包生态代码风格优雅易于使用、阅读与掌握高可扩展性具备高质量的可扩展软件架构、松耦合、模块化易于裁剪与扩展支持高性能应用支持 GCC、Keil、IAR 等主流编译工具支持广泛的架构与芯片。将 U8g2 移植到 RT-Thread 后图形库运行在 RT-Thread 的线程调度之上其中毫秒级延时直接调用rt_thread_mdelay挂起当前线程既保证了时序又让出了 CPU这正是 RTOS 环境与裸机 Arduino 环境的最大差异之一。快速开始两种官方推荐的开发路径官方为不同偏好的开发者提供了两条快速上手路径二者均围绕同一套移植源码sys/rt-thread/port 目录展开路径一RT-Thread StudioWindows 图形化 IDE偏好 GUI 的开发者可直接使用 RT-Thread Studio在其软件包管理界面中导入 U8g2 官方软件包构建组依赖PKG_USING_U8G2_OFFICIAL见 sys/rt-thread/SConscript然后通过图形化配置勾选显示接口与示例。官方为这条路径提供了配套的视频教程。路径二RT-Thread ENV 工具Ubuntu 终端偏好终端的开发者可使用 RT-Thread ENV 工具在工程目录执行menuconfig配置软件包与功能开关用scons编译最后将固件烧录到板卡后在 MSHFinSH 命令行中运行导出的示例命令。官方为此路径提供了终端录屏教程。无论哪条路径最终都会落到两个核心选择上是否启用 C 封装U8G2_USE_CPP以及采用哪种显示接口软件/硬件 I2C、软件/硬件 SPI、8080 并行。移植层源码解析GPIO、延时与总线字节函数RT-Thread 移植的核心全部集中在 sys/rt-thread/port/u8g2_port.c 与 sys/rt-thread/port/u8g2_port.h 中。U8g2 的架构要求移植者提供两类回调字节传输函数u8x8_byte_*和 GPIO/延时函数u8x8_gpio_and_delay_*移植层按此实现了三个关键函数u8x8_gpio_and_delay_rtthreadGPIO 与延时桥接该函数将 U8g2 的 GPIO 消息与延时消息翻译为 RT-Thread 的 PIN 设备接口u8g2_port.c延时处理U8X8_MSG_DELAY_MILLI调用rt_thread_mdelay(arg_int)实现毫秒级延时让出 CPU纳秒/百纳秒级延时用nop指令近似U8X8_MSG_DELAY_10MICRO与U8X8_MSG_DELAY_I2C则通过循环执行nop实现初始化U8X8_MSG_GPIO_AND_DELAY_INIT一次性将 SPI时钟/数据/复位/DC/CS、I2CSDA/SCL、8080 并行D0~D7/E以及菜单按键引脚U8X8_PIN_MENU_*上拉输入全部按需配置引脚操作所有写引脚操作都经过u8g2_port_pin_write内部先判断pin ! U8X8_PIN_NONE再调用rt_pin_write因此未连接的引脚如U8X8_PIN_NONE会被安全跳过读引脚如菜单按键走rt_pin_read。u8x8_byte_rtthread_hw_i2c硬件 I2C 字节传输在U8G2_USE_HW_I2C宏开启时编译u8g2_port.c。其实现要点在U8X8_MSG_BYTE_INIT中通过rt_i2c_bus_device_find(U8G2_I2C_DEVICE_NAME)查找 I2C 总线设备U8X8_MSG_BYTE_SEND将数据暂存进 32 字节静态缓冲U8g2 在 START 与 END 之间最多发送 32 字节U8X8_MSG_BYTE_END_TRANSFER组装struct rt_i2c_msg地址取u8x8_GetI2CAddress(u8x8)1即 7 位地址调用rt_i2c_transfer发送失败时最多重试MAX_RETRY3次。u8x8_byte_rtthread_4wire_hw_spi硬件 SPI 字节传输在U8G2_USE_HW_SPI宏开启时编译u8g2_port.c。其实现要点U8X8_MSG_BYTE_INIT调用rt_hw_spi_config将设备挂载到U8G2_SPI_BUS_NAME指定的总线默认spi1设备名为U8G2_SPI_DEVICE_NAME默认spi10并按u8x8-display_info-spi_mode映射为 RT-Thread 的RT_SPI_MODE_0~3max_hz取自display_info-sck_clock_hz值得注意的是片选信号由 GPIO 直接控制U8X8_MSG_BYTE_START_TRANSFER/END_TRANSFER中手动拉低/拉高 CS而rt_spi_transfer_message中cs_take/cs_release均为 0SPI 总线通过rt_spi_take_bus/rt_spi_release_bus互斥访问每个显示控制器的 SPI 模式、时钟频率、片选使能电平chip_enable_level/chip_disable_level及片选前后等待时间post_chip_enable_wait_ns/pre_chip_disable_wait_ns都来自 U8g2 的display_info保证了跨控制器驱动的通用性。可配置宏一览sys/rt-thread/port/u8g2_port.h 定义了以下开关与默认值宏默认值含义U8G2_USE_HW_SPI未定义需自行开启启用硬件 SPI 字节函数U8G2_USE_HW_I2C未定义需自行开启启用硬件 I2C 字节函数U8G2_SPI_BUS_NAMEspi1挂载 SPI 设备的总线名U8G2_SPI_DEVICE_NAMEspi10挂载后的 SPI 设备名U8G2_I2C_DEVICE_NAMEi2c2查找的 I2C 总线设备名未开启上述任一硬件宏时可选用 U8g2 自带的软件接口u8x8_byte_sw_i2c、u8x8_byte_4wire_sw_spi它们通过 GPIO 位操作模拟时序仅依赖u8x8_gpio_and_delay_rtthread无需额外的总线驱动。构建系统与功能裁剪SConscript 依赖选项RT-Thread 使用 SConscript 描述组件的构建。移植层的 SConscript 固定编译port/u8g2_port.c与根目录../../csrc/*.c即 U8g2 全部 C 源码当开启U8G2_USE_CPP时额外编译port/*.cppC 封装即U8g2lib.h提供的类接口。示例源码则通过一系列GetDepend选项按需加入全部选项按依赖宏分组如下基础示例C 接口U8G2_USE_CPP关闭时生效| 依赖宏 | 对应源码 | |---|---| |U8G2_USING_SW_I2C_SSD1306| examples/ssd1306_12864_sw_i2c_example.c | |U8G2_USING_HW_I2C_SSD1306| examples/ssd1306_12864_hw_i2c_example.c | |U8G2_USING_SW_SPI_SSD1306| examples/ssd1306_12864_4wire_sw_spi_example.c | |U8G2_USING_HW_SPI_SSD1306| examples/ssd1306_12864_4wire_hw_spi_example.c | |U8G2_USING_8080_ST7920| examples/st7920_12864_8080_example.c |C 接口U8G2_USE_CPP开启时除上述基础示例的.cpp版本如 examples/ssd1306_12864_hw_i2c_example.cpp外还有三大类可选示例Frame Buffer全帧缓冲U8G2_USING_FRAME_EXAMPLE_*系列对应 examples/full_buffer 下的 FPS、FontUsage、GraphicsTest、HelloWorld、IconMenu、PrintUTF8、SelectionList、U8g2Logo、UpdateArea、Weather 等Page Buffer页缓冲U8G2_USING_PAGE_EXAMPLE_*系列对应 examples/page_buffer 下 27 个示例含 Chinese、Japanese、Korean、Devanagari 等多语言示例U8x8 文本模式U8G2_USING_U8x8_EXAMPLE_*系列对应 examples/u8x8游戏示例U8G2_USING_GAME_EXAMPLE_SPACE_TRASH/TREX对应 examples/games。构建时根据依赖宏裁剪源码既保证了“用到什么编什么”也避免了不需要的示例挤占 Flash——这与 README 中强调的“模块化、易裁剪”理念完全一致。实战示例一C 接口驱动 SSD1306四种接口对比C 接口示例以u8g2_t结构体 设置函数为骨架全部导出为 FinSH 命令MSH_CMD_EXPORT烧录后可在控制台输入命令名直接运行。以硬件 SPI 为例ssd1306_12864_4wire_hw_spi_example.c#include rthw.h #include rtthread.h #include rtdevice.h #include u8g2_port.h #define OLED_SPI_PIN_RES 2 // PA2 #define OLED_SPI_PIN_DC 1 // PA1 #define OLED_SPI_PIN_CS 0 // PA0 static void u8g2_ssd1306_12864_4wire_hw_spi_example(int argc, char *argv[]) { u8g2_t u8g2; // 初始化显示控制器 旋转方向 字节函数 GPIO/延时函数 u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_rtthread_4wire_hw_spi, u8x8_gpio_and_delay_rtthread); u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_CS, OLED_SPI_PIN_CS); u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_DC, OLED_SPI_PIN_DC); u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_RESET, OLED_SPI_PIN_RES); u8g2_InitDisplay(u8g2); u8g2_SetPowerSave(u8g2, 0); // 全帧缓冲绘制流程清空 → 设字体 → 画字符串 → 送显 u8g2_ClearBuffer(u8g2); u8g2_SetFont(u8g2, u8g2_font_ncenB08_tr); u8g2_DrawStr(u8g2, 1, 18, U8g2 on RT-Thread); u8g2_SendBuffer(u8g2); // 绘制 Unicode 符号雪人 ☃U2603 u8g2_SetFont(u8g2, u8g2_font_unifont_t_symbols); u8g2_DrawGlyph(u8g2, 112, 56, 0x2603); u8g2_SendBuffer(u8g2); } MSH_CMD_EXPORT(u8g2_ssd1306_12864_4wire_hw_spi_example, hardware 4 wire spi ssd1306 sample);四种接口的关键差异仅在设置函数与引脚绑定上接口设置函数字节函数需绑定的引脚硬件 SPIu8g2_Setup_ssd1306_128x64_noname_fu8x8_byte_rtthread_4wire_hw_spiCS、DC、RESET时钟/数据由 SPI 总线接管软件 SPI同上u8x8_byte_4wire_sw_spiSPI_CLOCK、SPI_DATA、CS、DC、RESET硬件 I2Cu8g2_Setup_ssd1306_i2c_128x64_noname_fu8x8_byte_rtthread_hw_i2c无需绑引脚总线名由U8G2_I2C_DEVICE_NAME指定软件 I2C同上u8x8_byte_sw_i2cI2C_CLOCK、I2C_DATA软件 I2C 示例ssd1306_12864_sw_i2c_example.c以OLED_I2C_PIN_SCL 22 /* PB6 */、OLED_I2C_PIN_SDA 23 /* PB7 */绑定引脚硬件 I2C 示例则无需任何u8x8_SetPin调用因为总线设备由rt_i2c_bus_device_find按名字查找。此外 st7920_12864_8080_example.c 展示了 8 位 8080 并行接口通过辅助函数u8x8_SetPin_8Bit_8080一次性绑定 D0~D7、EN、CS、DC、RST 共 12 个引脚使用u8g2_Setup_st7920_p_128x64_f与u8x8_byte_8bit_8080mode。实战示例二C 接口与三种渲染模式开启U8G2_USE_CPP后可使用 sys/rt-thread/port/U8g2lib.h 提供的类接口。C 示例的写法与 Arduino 完全一致例如硬件 I2Cssd1306_12864_hw_i2c_example.cpp#include rthw.h #include rtthread.h #include rtdevice.h #include U8g2lib.h // 构造器命名规则控制器_分辨率_变体_缓冲模式_接口 static U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset*/ U8X8_PIN_NONE); static void u8g2_ssd1306_12864_hw_i2c_example(int argc, char *argv[]) { u8g2.begin(); u8g2.clearBuffer(); // 清空内部缓冲 u8g2.setFont(u8g2_font_6x13_tr); // 选择合适的字体 u8g2.drawStr(1, 18, U8g2 on RT-Thread); // 写入内部缓冲 u8g2.sendBuffer(); // 缓冲送显 u8g2.setFont(u8g2_font_unifont_t_symbols); u8g2.drawGlyph(112, 56, 0x2603); u8g2.sendBuffer(); } MSH_CMD_EXPORT(u8g2_ssd1306_12864_hw_i2c_example, i2c ssd1306 sample);C 构造器命名包含FFrame Buffer、1/2Page Buffer或8x8U8x8 文本模式等标识对应 U8g2 的三种渲染模式examples/full_buffer/HelloWorld.cpp 文件头注释对此有明确说明Frame Buffer全帧缓冲clearBuffer()/sendBuffer()成对使用绘制快但需要整屏 RAM如 128×64 需要 1024 字节RAM 受限的板卡可能无法使用Page Buffer页缓冲firstPage()/nextPage()循环绘制RAM 占用小几乎所有板卡都能运行参考 examples/page_buffer/HelloWorld_pb.cppU8x8 文本模式零 RAM 占用直接与显示控制器通信仅支持 8×8 文本无图形能力参考 examples/u8x8 下的示例。选择原则RAM 充足、追求帧率选 Frame BufferRAM 紧张选 Page Buffer只需显示文本选 U8x8。此外U8g2lib.h中的构造器注释还提示大分辨率屏如 SSD1322 256×64、ST75256 256×128需要开启U8G2_16BIT320×240 以上的控制器则需要额外的U8G2_32BIT支持。运行与验证完成配置与编译后将固件烧录到目标板卡打开串口终端进入 RT-Thread FinSH 控制台输入help查看所有导出的 MSH 命令应能看到u8g2_ssd1306_12864_4wire_hw_spi_example、u8g2_ssd1306_12864_hw_i2c_example、u8g2_full_buffer_hello_world等输入对应命令即可在屏幕上看到 U8g2 on RT-Thread 字样与 ☃ 符号若屏幕无显示按以下顺序排查确认U8G2_SPI_BUS_NAME/U8G2_I2C_DEVICE_NAME与实际总线名一致可通过list_device命令查看确认引脚编号与板卡原理图一致示例注释提示可参考板级驱动如drv_gpio.c的引脚定义确认已按接口开启U8G2_USE_HW_SPI或U8G2_USE_HW_I2C宏确认显示控制器型号、分辨率与构造器/设置函数匹配。小结U8g2 的 RT-Thread 移植层在 sys/rt-thread/port 目录中提供了一个完整、可裁剪的接入方案u8x8_gpio_and_delay_rtthread打通了 GPIO 与延时u8x8_byte_rtthread_hw_i2c与u8x8_byte_rtthread_4wire_hw_spi分别桥接 RT-Thread 的 I2C/SPI 设备框架软件模拟接口则让无总线驱动的板卡也能直接驱动屏幕SConscript 通过一组U8G2_USING_*依赖宏把 C/C 接口与数十个示例做成按需编译的模块。配合 RT-Thread Studio 或 ENV 工具链开发者可以在几分钟内从零点亮一块 SSD1306 显示屏并在此基础上进一步探索 FPS 测试、多语言渲染、菜单控件等更复杂的图形应用。赞分享嵌入式嵌入式GUI驱动开发【免费下载链接】u8g2U8glib library for monochrome displays, version 2项目地址https://gitcode.com/gh_mirrors/u8/u8g2点击查看免费下载相关推荐RT-Thread on Raspberry Pi PicoRP2040 BSP 移植实战指南RT Thread on Raspberry Pi PicoRP2040 BSP 移植实战指南 本篇技术指南以 RT Thread 仓库中 bsp/raspb操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 在 GD32305R-START 开发板上的 BSP 移植与使用指南RT Thread 在 GD32305R START 开发板上的 BSP 移植与使用指南 导读 GD32305R START 是兆易创新GigaDevice操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 在 NUCLEO-L476RG 开发板上的 BSP 移植与使用指南RT Thread 在 NUCLEO L476RG 开发板上的 BSP 移植与使用指南 NUCLEO L476RG 是 ST 官方推出的基于 STM32L476操作系统嵌入式物联网嵌入式OSRTOS上一篇LTX-2实战案例用IC-LoRA实现视频风格迁移的完整流程下一篇开源项目 Pingo 使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进