1. U8g2库自定义字体生成与使用指南
在嵌入式开发中,OLED显示屏的文字显示是一个常见需求。U8g2库作为一款强大的图形库,虽然自带丰富的字体资源,但在实际项目中,我们经常需要自定义字体来满足特定设计需求。本文将详细介绍如何为U8g2库生成和使用自定义字体,包括ASCII仿数码管字体和汉字字体的完整制作流程。
1.1 U8g2字体系统概述
U8g2库内置了超过200种字体,涵盖了从6x10像素到30x50像素的各种尺寸。这些字体定义在u8g2.h头文件中,可以通过简单的API调用进行设置和使用。然而,当我们需要特殊风格的字体(如仿数码管效果)或显示中文时,内置字体往往无法满足需求。
U8g2的字体系统基于位图字体原理,每个字符都以像素矩阵的形式存储。这种设计虽然占用存储空间较大,但在小尺寸OLED上能保证最佳的显示效果。字体文件以C数组形式存在,可以直接嵌入到固件中。
提示:U8g2支持三种文本绘制函数:
- DrawStr():用于ASCII字符
- DrawGlyph():用于图标
- DrawUTF8():用于Unicode字符(如中文)
2. ASCII仿数码管字体制作
2.1 工具准备与字体选择
制作仿数码管字体需要以下工具:
- FontForge(开源字体编辑软件)
- U8g2自带的bdfconv转换工具
- 数码管风格字体文件(.ttf)
推荐获取数码管字体的资源网站:
- Dafont(https://www.dafont.com/seven-segment.font)
- FontStruct(https://fontstruct.com/gallery/set/32/lcd-segment)
选择字体时需考虑OLED屏幕分辨率。对于常见的128x64 SSD1306,建议选择15-20像素高度的字体。
2.2 字体编辑与导出
在FontForge中打开下载的.ttf字体文件后,需要执行以下关键步骤:
-
设置像素尺寸:
- 进入"Element > Font Info"菜单
- 在"General"选项卡中设置合适的Em Size(如256)
- 在"OS/2"选项卡中调整Win Ascent/Win Descent值
-
调整字符间距:
- 数码管字体通常需要减少字符间距
- 使用"Metrics > Set Width"调整每个字符的宽度
-
导出BDF文件:
- 选择"File > Generate Fonts"
- 格式选择"BDF"
- 勾选"Bitmap Only"选项
- 设置合适的像素大小(如15x30)
2.3 字体转换与集成
使用U8g2提供的bdfconv工具将BDF文件转换为C数组:
bash复制./bdfconv.exe -v -f 1 -m "33-125" SevenSegmentRegular-15.bdf -n SevenSegmentRegular_tn16 -o SevenSegmentRegular_tn16.c
参数说明:
-v: verbose模式-f 1: 字体格式1(U8g2专用格式)-m "33-125": 只包含ASCII可打印字符-n: 字体名称-o: 输出文件名
生成的.c文件需要:
- 添加到u8g2_fonts.c文件中
- 在u8g2.h中声明外部引用:
c复制extern const uint8_t SevenSegmentRegular_tn16[1220] U8G2_FONT_SECTION("SevenSegmentRegular_tn16");
2.4 数码管字体使用示例
c复制void Display_SEG() {
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2,SevenSegmentRegular_tn16);
u8g2_DrawStr(&u8g2,0, 16,"12:32-59.{-}");
u8g2_DrawStr(&u8g2,0, 32,"ABCDEFGHIJK");
u8g2_DrawStr(&u8g2,0, 48,"MLNOPRSTUVW");
u8g2_DrawStr(&u8g2,0, 64,"XYZ[\\+/(|)]");
u8g2_SendBuffer(&u8g2);
HAL_Delay(1000);
}
注意事项:
- 数码管字体通常只包含数字和部分符号,字母显示可能不理想
- 转换时务必指定正确的字符范围,避免生成不必要的字体数据
- 小尺寸OLED上建议使用15px以下的字体,否则可能显示不全
3. 汉字字体生成与使用
3.1 汉字字体生成工具
推荐使用开源工具"Easy-u8g2-font-generate-tools":
- 原项目地址:https://gitee.com/createskyblue/Easy-u8g2-font-generate-tools
- 修改版地址:https://gitee.com/perseverance51/Easy-u8g2-font-generate-tools
该工具基于Python开发,可以将.ttf字体文件转换为U8g2兼容的C数组格式,支持任意Unicode字符。
3.2 汉字字体生成步骤
-
准备字体文件:
- 选择适合的中文字体(如思源黑体、文泉驿等)
- 注意字体版权问题,商业项目需使用免费商用字体
-
配置字符集:
- 在工具的config.json中指定需要生成的汉字
- 可以批量指定常用汉字(GB2312约6763字)
- 对于特定诗词,只需包含诗中用到的汉字
-
运行转换工具:
bash复制
python main.py -f font.ttf -s 16 -o myFont_16.c参数说明:
-f: 输入字体文件-s: 字体大小(像素高度)-o: 输出文件名
3.3 汉字字体集成与使用
生成的字体数组需要:
- 添加到项目源文件中
- 在u8g2.h中声明:
c复制extern const uint8_t myFont_16[1870] U8G2_FONT_SECTION("myFont_16");
使用示例:
c复制void Display_CN() {
static uint8_t i=0;
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2,myFont_16);
if(++i<6) {
u8g2_DrawUTF8(&u8g2,0, 15,"远上寒山石径斜");
u8g2_DrawUTF8(&u8g2,0, 30,"白云深处有人家");
u8g2_DrawUTF8(&u8g2,0, 45,"停车坐爱枫林晚");
u8g2_DrawUTF8(&u8g2,0, 60,"霜叶红于二月花");
} else {
if(i>12) i=0;
u8g2_DrawUTF8(&u8g2,0, 15,"碧玉妆成一树高");
u8g2_DrawUTF8(&u8g2,0, 30,"万条垂下绿丝绦");
u8g2_DrawUTF8(&u8g2,0, 45,"不知细叶谁裁出");
u8g2_DrawUTF8(&u8g2,0, 60,"二月春风似剪刀");
}
u8g2_SendBuffer(&u8g2);
HAL_Delay(1000);
}
4. 常见问题与优化技巧
4.1 字体大小与内存优化
-
字体大小选择:
- 128x64 OLED:推荐12-16px字体
- 64x48 OLED:推荐8-10px字体
- 测试不同大小在目标屏幕上的实际显示效果
-
内存优化技巧:
- 只包含必要的字符(ASCII 33-126或特定汉字)
- 使用
-b 1参数减少位深度(单色位图) - 分段加载字体,不使用时从内存中释放
4.2 显示效果优化
-
抗锯齿处理:
- 在FontForge中启用抗锯齿渲染
- 适当调整字符间距和行距
- 对于小尺寸字体,禁用抗锯齿可能更清晰
-
多语言支持:
- 混合显示ASCII和汉字时,需要切换字体
- 可以制作包含ASCII和常用汉字的复合字体
- 考虑使用U8g2的扩展字体特性
4.3 性能优化
-
缓冲区管理:
- 使用合适的缓冲区大小(
u8g2_Setup_系列函数) - 对于复杂界面,考虑分页渲染
- 减少
SendBuffer调用次数
- 使用合适的缓冲区大小(
-
字体缓存:
- 高频使用的字符可以预渲染到位图
- 实现简单的字体缓存机制
- 对于静态内容,考虑直接使用位图
5. 实际项目经验分享
在STM32F103上使用U8g2驱动SSD1306 OLED时,自定义字体的应用需要注意以下几点:
-
存储空间管理:
- 一个16px的中文字体(约3000字)可能占用100KB+ Flash
- 考虑使用外部Flash或压缩字体数据
- 启用编译器的优化选项(-Os)
-
渲染性能:
- 汉字渲染比ASCII慢3-5倍
- 复杂界面需要考虑帧率问题
- 适当使用
u8g2.setFontPosTop()优化文本定位
-
多字体混合:
- 标题使用大号字体,正文使用小号字体
- 中英文混排时需要处理字体切换
- 实现统一的文本绘制接口
个人经验:在实际项目中,我通常会建立一个字体管理系统,统一管理所有自定义字体资源,并提供简单的API来切换字体。对于中文显示,建议预先统计所有需要用到的汉字,只生成这些字符的字体数据,可以显著减少固件体积。
通过本文介绍的方法,你应该能够为U8g2库创建各种风格的自定义字体,并在嵌入式项目中实现专业的文本显示效果。无论是复古的数码管风格,还是优美的中文字体,都能为你的项目增添独特的视觉效果。
