news 2026/5/8 17:06:51

STM32F103C8T6上玩转U8G2库:手把手教你驱动0.96寸OLED显示中文和动画

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103C8T6上玩转U8G2库:手把手教你驱动0.96寸OLED显示中文和动画

STM32F103C8T6上玩转U8G2库:手把手教你驱动0.96寸OLED显示中文和动画

在嵌入式开发中,OLED显示屏因其高对比度、低功耗和快速响应等特性,成为许多项目的首选显示方案。而U8G2库作为一款功能强大的图形库,能够为这些小型显示屏带来丰富的图形和文本显示能力。本文将深入探讨如何在STM32F103C8T6这款经典的Cortex-M3微控制器上,通过U8G2库实现0.96寸OLED屏的中文显示和动画效果。

1. 环境准备与基础配置

在开始之前,我们需要确保开发环境已经准备就绪。对于STM32F103C8T6这款芯片,Keil MDK或者STM32CubeIDE都是不错的选择。这里我们以Keil MDK为例,介绍必要的配置步骤。

首先,创建一个新的工程,选择STM32F103C8T6作为目标设备。在工程设置中,有几个关键点需要注意:

  • 确保勾选C99 Mode选项,这是U8G2库正常运行的前提
  • 设置合适的优化等级,通常选择-O2可以获得较好的性能与代码大小的平衡
  • 在Include Paths中添加U8G2库的路径

接下来是硬件连接部分。0.96寸OLED屏通常采用I2C接口,接线方式如下:

OLED引脚STM32引脚功能
GNDGND地线
VCC3.3V电源
SCLPB8时钟线
SDAPB9数据线

2. U8G2库的裁剪与优化

U8G2库功能强大但体积较大,直接使用可能会导致编译错误或占用过多Flash空间。因此,我们需要对库进行适当的裁剪。

首先从GitHub获取U8G2源码:

git clone https://github.com/olikraus/u8g2.git

在csrc目录中,我们只需要保留以下几个关键文件:

  • u8x8_d_ssd1306_128x64_noname.c (OLED驱动)
  • u8g2_d_setup.c (保留i2c相关函数)
  • u8g2_d_memory.c (保留u8g2_m_16_8_f函数)

对于中文显示,还需要特别注意字库的处理。U8G2提供了多种中文字体,但全量包含会导致编译失败。推荐只保留需要的字体,例如:

// 在u8g2_fonts.c中只保留以下字体 const uint8_t u8g2_font_wqy16_t_chinese2[] U8G2_FONT_SECTION("u8g2_font_wqy16_t_chinese2");

3. I2C接口驱动实现

U8G2库需要开发者提供底层的GPIO和延时函数。下面是一个完整的I2C接口实现示例:

#include "u8g2.h" #include "stm32f10x.h" #define OLED_I2C_SCL_PIN GPIO_Pin_8 #define OLED_I2C_SCL_PORT GPIOB #define OLED_I2C_SDA_PIN GPIO_Pin_9 #define OLED_I2C_SDA_PORT GPIOB void Delay_us(uint32_t us) { // 实现微秒级延时函数 us *= 72 / 5; while(us--) { __NOP(); } } void Delay_ms(uint32_t ms) { while(ms--) { Delay_us(1000); } } uint8_t u8g2_gpio_and_delay_stm32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_DELAY_MILLI: Delay_ms(arg_int); break; case U8X8_MSG_GPIO_I2C_CLOCK: if(arg_int) GPIO_SetBits(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN); else GPIO_ResetBits(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN); break; case U8X8_MSG_GPIO_I2C_DATA: if(arg_int) GPIO_SetBits(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN); else GPIO_ResetBits(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN); break; default: return 0; } return 1; }

4. 中文显示与动画效果实现

4.1 中文显示基础

要在OLED上显示中文,首先需要选择合适的字体。U8G2提供了多种中文字体,如u8g2_font_wqy16_t_chinese2。使用前需要确保:

  1. 字体已包含在工程中
  2. 源代码文件保存为UTF-8编码
  3. Keil中设置了正确的编译选项

基本的中文显示代码如下:

void ShowChinese(u8g2_t *u8g2) { u8g2_ClearBuffer(u8g2); u8g2_SetFont(u8g2, u8g2_font_wqy16_t_chinese2); u8g2_DrawUTF8(u8g2, 0, 16, "嵌入式开发"); u8g2_DrawUTF8(u8g2, 0, 32, "中文显示测试"); u8g2_SendBuffer(u8g2); }

4.2 文字动画效果

U8G2库支持多种文字动画效果,下面实现一个简单的文字滚动效果:

void ScrollText(u8g2_t *u8g2, const char *text) { int width = u8g2_GetUTF8Width(u8g2, text); for(int x = 128; x > -width; x--) { u8g2_ClearBuffer(u8g2); u8g2_SetFont(u8g2, u8g2_font_wqy16_t_chinese2); u8g2_DrawUTF8(u8g2, x, 32, text); u8g2_SendBuffer(u8g2); Delay_ms(30); } }

4.3 图形动画实现

除了文字,我们还可以创建简单的图形动画。下面是一个跳动的小球示例:

void BouncingBall(u8g2_t *u8g2) { int x = 64, y = 32; int dx = 2, dy = 2; while(1) { u8g2_ClearBuffer(u8g2); u8g2_DrawDisc(u8g2, x, y, 5, U8G2_DRAW_ALL); u8g2_SendBuffer(u8g2); x += dx; y += dy; if(x <= 5 || x >= 123) dx = -dx; if(y <= 5 || y >= 59) dy = -dy; Delay_ms(20); } }

5. 性能优化与常见问题解决

5.1 显示刷新优化

OLED的刷新速度直接影响动画的流畅度。以下是几个优化建议:

  1. 局部刷新:只更新变化的部分,而不是整个屏幕
  2. 双缓冲:使用U8G2的双缓冲功能减少闪烁
  3. 简化图形:减少复杂图形的使用

5.2 常见问题及解决方案

问题1:中文显示乱码

  • 确保源代码文件保存为UTF-8编码
  • 在Keil的Misc Controls中添加:--no-multibyte-chars
  • 检查是否包含了正确的中文字体

问题2:编译时Flash空间不足

  • 裁剪不需要的字体和功能
  • 提高优化等级
  • 使用更小的字体

问题3:动画卡顿

  • 减少每帧的绘制内容
  • 优化延时函数精度
  • 检查I2C时钟速度是否设置合理

6. 高级应用示例

6.1 多页面菜单系统

利用U8G2可以构建简单的菜单界面。下面是一个基础实现框架:

typedef struct { const char *title; void (*action)(u8g2_t*); } MenuItem; void ShowMenu(u8g2_t *u8g2, MenuItem *items, int count, int selected) { u8g2_ClearBuffer(u8g2); u8g2_SetFont(u8g2, u8g2_font_wqy16_t_chinese2); for(int i = 0; i < count; i++) { if(i == selected) { u8g2_DrawBox(u8g2, 0, i*16, 128, 16); u8g2_SetDrawColor(u8g2, 0); } u8g2_DrawUTF8(u8g2, 10, i*16 + 13, items[i].title); if(i == selected) { u8g2_SetDrawColor(u8g2, 1); } } u8g2_SendBuffer(u8g2); }

6.2 实时数据可视化

对于需要显示传感器数据的应用,可以创建简单的图表:

void DrawGraph(u8g2_t *u8g2, int *data, int count) { u8g2_ClearBuffer(u8g2); // 绘制坐标轴 u8g2_DrawHLine(u8g2, 10, 60, 100); u8g2_DrawVLine(u8g2, 10, 10, 50); // 绘制数据点 for(int i = 0; i < count-1; i++) { int y1 = 60 - data[i]/2; int y2 = 60 - data[i+1]/2; u8g2_DrawLine(u8g2, 15+i*5, y1, 15+(i+1)*5, y2); } u8g2_SendBuffer(u8g2); }

在实际项目中,我发现合理使用U8G2的绘图函数可以大大提升用户体验。例如,通过组合基本图形创建自定义图标,或者利用帧动画原理实现复杂的界面过渡效果。对于资源有限的STM32F103C8T6,关键在于找到功能丰富性和性能消耗之间的平衡点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 17:06:40

蜂窝网络绿色转型:从芯片到架构的能效革新与实战指南

1. 项目概述&#xff1a;当可持续性成为蜂窝网络基础设施的硬指标最近和几位在运营商负责网络规划的老同事聊天&#xff0c;话题总绕不开两个字&#xff1a;电费。这听起来可能有点意外&#xff0c;但对他们而言&#xff0c;这已经是比频谱资源、用户增长更迫在眉睫的运营压力。…

作者头像 李华
网站建设 2026/5/8 17:06:38

OpenPilot:开源自动驾驶系统如何重新定义智能驾驶体验

OpenPilot&#xff1a;开源自动驾驶系统如何重新定义智能驾驶体验 【免费下载链接】openpilot openpilot is an operating system for robotics. Currently, it upgrades the driver assistance system on 300 supported cars. 项目地址: https://gitcode.com/GitHub_Trendin…

作者头像 李华
网站建设 2026/5/8 17:05:59

无线电力网络:从设备供电到环境基础设施的物联网范式变革

1. 无线电网&#xff1a;当电力成为环境基础设施还记得十几年前&#xff0c;办公室里到处都是网线吗&#xff1f;桌子底下、墙角边&#xff0c;各种颜色的线缆像藤蔓一样缠绕&#xff0c;新添一台电脑就得拉一根线&#xff0c;规划网络布局是件头疼事。后来Wi-Fi普及了&#xf…

作者头像 李华
网站建设 2026/5/8 17:05:55

VMware Tools安装问题解决

&#x1f50d; 错误原因解析这个弹窗说明&#xff1a;VMware Workstation 新版本&#xff08;17.x 及以后&#xff09;不再默认内置部分客户机系统的 VMware Tools 镜像&#xff0c;尤其是部分旧版 Linux 系统&#xff0c;需要你手动下载并安装。&#x1f6e0;️ 解决方法&…

作者头像 李华
网站建设 2026/5/8 17:05:46

《AR眼镜如何成为外科医生的“第三只眼“:5大临床应用场景》

《AR眼镜如何成为外科医生的"第三只眼"&#xff1a;5大临床应用场景》AR手术导航系统&#xff08;如适配安宝特M400工业AR眼镜的医疗解决方案&#xff09;核心价值在于打通术前规划数据与术中实操的“手眼协同断点”&#xff0c;让医生无需脱离术野即可获取多维度关键…

作者头像 李华
网站建设 2026/5/8 17:04:31

智能车竞赛AI模型组|3D自动裁判系统视频文稿

简 介&#xff1a; &#xff1a;全国大学生智能汽车竞赛推出人工智能模型组3D自动裁判系统&#xff0c;由百度提供技术支持。该系统通过3D可视化界面实时还原赛场全貌&#xff0c;自动判定碰撞、打卡等赛事事件&#xff0c;实现数据留痕和判罚透明化。系统面向高校免费开放&…

作者头像 李华