RT thread使用u8g2点亮oled显示屏

张开发
2026/6/9 10:33:36 15 分钟阅读
RT thread使用u8g2点亮oled显示屏
本案例使用u8g2的软件包stm32f4070.96寸oled显示屏at24c04。rtthread版本4.1.1增加软件包u8g2该软件包可以直接支持SSD1306的0.96寸的oled显示屏修改配置打开RT THread settings 配置u8g2软件包配置项开关 / 填写值核心说明U8G2 总开关✅ 开启启用 u8g2 软件包使用硬件 SPI❌ 关闭我们用 I2C 接口不需要 SPI使用硬件 I2C✅ 必须开启核心名字有误导性真实含义是「启用 RT-Thread 标准 I2C 设备接口」哪怕你用的是软件模拟 I2C也必须开这个↳ i2c device name填入i2c1和你board.h里注册的 I2C 设备名完全一致和 AT24C04 共用同一个 I2C 总线Use C❌ 关闭我们用 C 语言开发不需要 C 支持U8G2 Examples❌ 里面所有示例全部关闭避免示例代码和你自己写的main.c/oled.c编译冲突我们自己写不用它的示例Version保持latest不用修改用最新稳定版即可为什么用软件 I2C还要开使用硬件 I2c这个开关的名字有极强的误导性本质它不是控制 “用不用硬件 I2C 外设”而是控制 u8g2 要不要对接RT-Thread 标准的 I2C 设备驱动框架。只要你在 RT-Thread 里注册了名为i2c1的 I2C 设备不管这个设备是硬件外设实现的还是软件 GPIO 模拟的就必须开这个开关。开启后u8g2 才会生成你oled.c里用到的u8x8_byte_rtthread_hw_i2c、u8x8_gpio_and_delay_rtthread适配函数否则会报「函数未定义」的编译错误。打开软件模拟iic\配置board.h打开软件iic填入pb8与9的对应引脚右键main.c选择属性文本编码该成utf-8用于显示中文oled.c#include oled.h #include u8g2.h #include u8g2_port.h #include stdio.h // 全局 u8g2 句柄内部维护外部无法直接调用 static u8g2_t u8g2; /** * brief 初始化 OLED 屏幕 * note 配置: SSD1306 128x64, 软件I2C, 设备名 i2c1 */ void oled_init(void) { // 1. 初始化 u8g2 核心 // 关键使用 u8g2 软件包提供的 RT-Thread 硬件I2C适配函数 // 注意这里的 hw_i2c 指的是 RT-Thread 标准 I2C 设备接口不是 STM32 硬件外设 u8g2_Setup_ssd1306_i2c_128x64_noname_f( u8g2, U8G2_R0, // 屏幕旋转方向 (0/90/180/270) u8x8_byte_rtthread_hw_i2c, // RT-Thread I2C 字节传输函数 u8x8_gpio_and_delay_rtthread // RT-Thread 延时函数 ); // 2. 初始化显示硬件 u8g2_InitDisplay(u8g2); // 3. 开启显示 (退出省电模式) u8g2_SetPowerSave(u8g2, 0); // 4. 清空显存 u8g2_ClearBuffer(u8g2); // 5. 默认设置英文字体 u8g2_SetFont(u8g2, u8g2_font_ncenB10_tr); } /** * brief 清空屏幕显存 * note 调用后需要调用 oled_update() 才会生效 */ void oled_clear(void) { u8g2_ClearBuffer(u8g2); } /** * brief 刷新屏幕把显存内容一次性显示出来 */ void oled_update(void) { u8g2_SendBuffer(u8g2); } /** * brief 显示英文字符/字符串 * param x: 像素横坐标 (0~127) * param y: 像素纵坐标 (0~63, 注意是像素不是行号) * param str: 要显示的字符串 */ void oled_show_str(uint8_t x, uint8_t y, const char *str) { // 切换到英文字体 u8g2_SetFont(u8g2, u8g2_font_ncenB10_tr); // 绘制字符串 u8g2_DrawStr(u8g2, x, y, str); } /** * brief 显示中文字符串 (UTF-8编码) * param x: 像素横坐标 * param y: 像素纵坐标 * param str: 要显示的中文字符串 (UTF-8) * note 调用此函数的 .c 文件必须是 UTF-8 编码 */ void oled_show_chinese(uint8_t x, uint8_t y, const char *str) { // 切换到完整版中文字体 (包含所有汉字如哈哈) u8g2_SetFont(u8g2, u8g2_font_wqy12_t_chinese3); // 关键必须用 DrawUTF8 显示中文 u8g2_DrawUTF8(u8g2, x, y, str); } /** * brief 显示整数数字 * param x: 像素横坐标 * param y: 像素纵坐标 * param num: 要显示的整数 (支持负数) */ void oled_show_num(uint8_t x, uint8_t y, int32_t num) { char buf[32] {0}; // 格式化数字为字符串 rt_snprintf(buf, sizeof(buf), %d, num); // 调用英文字符显示函数 oled_show_str(x, y, buf); } /** * brief 画一个点 * param x: 横坐标 y: 纵坐标 */ void oled_draw_pixel(uint8_t x, uint8_t y) { u8g2_DrawPixel(u8g2, x, y); } /** * brief 画一条直线 * param x1,y1: 起点坐标 * param x2,y2: 终点坐标 */ void oled_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { u8g2_DrawLine(u8g2, x1, y1, x2, y2); } /** * brief 画一个空心矩形框 * param x: 左上角横坐标 * param y: 左上角纵坐标 * param w: 宽度 * param h: 高度 */ void oled_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h) { u8g2_DrawFrame(u8g2, x, y, w, h); } /** * brief 画一个实心填充矩形 * param x: 左上角横坐标 * param y: 左上角纵坐标 * param w: 宽度 * param h: 高度 */ void oled_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h) { u8g2_DrawBox(u8g2, x, y, w, h); } /** * brief 画空心圆 * param x,y: 圆心坐标 * param r: 圆的半径 */ void oled_draw_circle(uint8_t x, uint8_t y, uint8_t r) { u8g2_DrawCircle(u8g2, x, y, r, U8G2_DRAW_ALL); // U8G2_DRAW_ALL 表示画整个圆 } /** * brief 画空心三角形 * param x1,y1/x2,y2/x3,y3: 三角形三个顶点的坐标 */ void oled_draw_triangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t x3, uint8_t y3) { u8g2_DrawTriangle(u8g2, x1, y1, x2, y2, x3, y3); }代码详细讲解u8g2_Setup_ssd1306_i2c_128x64_noname_f( u8g2, // 把我们的“遥控器”传进去 U8G2_R0, // 屏幕不旋转 u8x8_byte_rtthread_hw_i2c, // 【关键】告诉u8g2“你通过RT-Thread的I2C设备接口去发数据” u8x8_gpio_and_delay_rtthread // 告诉u8g2“你用RT-Thread的延时函数” );oled.h#ifndef __OLED_H__ #define __OLED_H__ #include rtthread.h #include stdint.h // 滚动方向枚举定义 typedef enum { OLED_SCROLL_LEFT 0, // 屏幕内容向左滚动 OLED_SCROLL_RIGHT 1 // 屏幕内容向右滚动 } oled_scroll_dir_t; /** * brief OLED初始化函数必须第一个调用 */ void oled_init(void); /** * brief 清空OLED显存仅清空内存不刷新屏幕 */ void oled_clear(void); /** * brief 刷新显存到OLED屏幕所有绘制后必须调用 */ void oled_update(void); /** * brief 显示英文字符串 * param x: 横坐标(0~127) y: 纵坐标(0~63) str: 英文文本 */ void oled_show_str(uint8_t x, uint8_t y, const char *str); /** * brief 显示UTF-8编码中文字符串 * param x: 横坐标 y: 纵坐标 str: 中文文本 */ void oled_show_chinese(uint8_t x, uint8_t y, const char *str); /** * brief 显示整数数字 * param x: 横坐标 y: 纵坐标 num: 整数值 */ void oled_show_num(uint8_t x, uint8_t y, int32_t num); /** * brief 在指定坐标画一个点 * param x: 横坐标 y: 纵坐标 */ void oled_draw_pixel(uint8_t x, uint8_t y); /** * brief 画一条直线 * param x1,y1: 起点坐标 x2,y2: 终点坐标 */ void oled_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); /** * brief 画空心矩形 * param x,y: 左上角坐标 w:宽度 h:高度 */ void oled_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h); /** * brief 画实心矩形 * param x,y: 左上角坐标 w:宽度 h:高度 */ void oled_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h); /** * brief 画空心圆 * param x,y: 圆心坐标 r: 半径 */ void oled_draw_circle(uint8_t x, uint8_t y, uint8_t r); /** * brief 画空心三角形 * param x1,y1/x2,y2/x3,y3: 三个顶点坐标 */ void oled_draw_triangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t x3, uint8_t y3); #endifu8g2_InitDisplay(u8g2);作用u8g2 通过 I2C 给 SSD1306 发送一串初始化命令比如设置分辨率、开启电荷泵等让屏幕从 “休眠” 状态醒过来。u8g2_SetPowerSave(u8g2, 0);作用退出省电模式让屏幕亮起来。u8g2_ClearBuffer(u8g2);核心概念显存Bufferu8g2 不会画一个点就立刻刷新屏幕那样太慢了。它先在内存里开辟一块 “草稿纸”显存你所有的绘制操作写字、画线都是先画在这张草稿纸上。等你全部画完了再一次性把草稿纸的内容发到屏幕上。u8g2_SetFont(u8g2, u8g2_font_ncenB10_tr);作用选一支笔默认选一支写英文字母的笔。void oled_clear(void) { u8g2_ClearBuffer(u8g2); // 只是擦干净了内存里的草稿纸 }注意调用这个函数后屏幕不会立刻变干净因为你只擦了草稿纸还没贴到屏幕上。void oled_update(void) { u8g2_SendBuffer(u8g2); // 【关键】把草稿纸的内容一次性通过I2C发送到屏幕 }作用把内存里的 “草稿纸”显存通过 I2C 全部发送给 SSD1306屏幕才会真正显示内容。新手学习u8g2只需要知道4个步骤1. oled_init() → 初始化屏幕拿到“遥控器” 2. oled_clear() → 擦干净“草稿纸” 3. oled_show_xxx() → 在“草稿纸”上画内容所有 Draw 函数都是画在内存里 4. oled_update() → 【关键】把“草稿纸”一次性贴到屏幕上main.c#include rtthread.h #include oled.h int main(void) { rt_kprintf( OLED 测试程序 \n); // 1. 初始化 OLED oled_init(); // 2. 清屏 oled_clear(); // 3. 测试显示英文 oled_show_str(0, 15, Hello RT-Thread!); // 4. 测试显示中文 // 注意这个 main.c 必须是 UTF-8 编码 oled_show_chinese(0, 35, 单片机); // 5. 测试显示数字 oled_show_str(0, 55, Year: ); oled_show_num(40, 55, 2026); // 6. 画个框装饰 oled_draw_rect(0, 0, 128, 64); // 7. 【关键】刷新屏幕所有内容才会显示出来 oled_update(); rt_kprintf(1测试显示完成\n); rt_thread_mdelay(2000); oled_clear(); oled_draw_circle(70, 32, 20); // 在屏幕中心画一个半径20的圆 oled_draw_triangle(10, 50, 30, 10, 50, 50); // 画一个三角形 oled_update(); while (1) { rt_thread_mdelay(1000); } return RT_EOK; }

更多文章