3. 字模提取技术:从像素到字节的魔法
做嵌入式GUI,绕不开一个字——「点」。说白了,屏幕上的每个汉字、每个字母,最终都是一堆点的亮灭组合。而字模提取,就是把我们看得懂的字符,翻译成单片机吃得下的二进制数据。
我记得刚入行那会儿,为了在12864上显示一个「嵌」字,硬是手算了一下午的点阵数据。后来才发现,有工具能帮我干这活。今天我就把字模提取这点事,掰开了跟你聊聊。
3.1 常用字模提取软件:PCtoLCD2002 与它的朋友们
市面上字模提取软件不少,但我用得最多的,还是 PCtoLCD2002。这软件体积小、功能全,而且免费。你想想看,一个不到2MB的工具,能搞定几乎所有常见字体的取模工作,多省心。
除了它,还有几个值得一提的:
| 软件名称 | 特点 | 适用场景 |
|---|---|---|
| PCtoLCD2002 | 支持多种取模方式、字体丰富、界面直观 | 通用嵌入式GUI开发 |
| FontForge | 开源、支持字体编辑与导出 | 需要自定义字体的场景 |
| BDF2C | 命令行工具、适合批量处理 | 自动化构建流程 |
| 自写脚本 | 完全可控、可定制 | 特殊格式需求 |
我个人习惯用 PCtoLCD2002 做原型验证,等确定方案后,再用脚本批量生成正式数据。这样既快又稳。
3.2 手动提取字模步骤:一步步来
工具虽好,但原理得懂。我曾经在调试一个OLED驱动时,发现显示出来的字全是镜像的。排查了半天,原来是取模方向搞反了。所以,手动走一遍流程,能帮你理解工具背后在干什么。
手动提取字模,大致分这几步:
- 确定点阵尺寸——比如16×16、24×24、32×32。尺寸越大,字越精细,但占用的存储也越多。
- 绘制字符网格——在纸上或软件里画一个点阵网格,把字符填进去。有笔画的格子涂黑,没笔画的留白。
- 确定取模方向——这是关键。横向取模还是纵向取模?从上到下还是从左到右?方向错了,显示就乱套。
- 逐行/逐列读取数据——按你选的方向,把每个字节的8个bit拼起来。涂黑的格子为1,留白的为0。
- 生成十六进制数组——把二进制数据转成0x??的形式,方便在C代码里使用。
3.3 字模数据格式:横向取模 vs 纵向取模
这是新手最容易踩坑的地方。我见过太多人,取模方向选错了,折腾半天显示不出来。说白了,横向取模和纵向取模,就是数据排列顺序不同。
横向取模(行扫描)
按行从左到右扫描,每8个点组成一个字节。如果一行超过8个点,就拆成多个字节。这种方式适合大多数LCD驱动芯片,比如SSD1306、ST7735。
举个例子,一个8×8的「A」字,横向取模的结果可能是:
// 横向取模:从左到右,从上到下
// 行0: 00111100 -> 0x3C
// 行1: 01100110 -> 0x66
// 行2: 01100110 -> 0x66
// 行3: 01111110 -> 0x7E
// 行4: 01100110 -> 0x66
// 行5: 01100110 -> 0x66
// 行6: 01100110 -> 0x66
// 行7: 00000000 -> 0x00
uint8_t font_A_horizontal[8] = {
0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00
};
纵向取模(列扫描)
按列从上到下扫描,每8个点组成一个字节。如果一列超过8个点,就拆成多个字节。这种方式在某些老式驱动或特殊屏上会用到。
同样的「A」字,纵向取模的结果是:
// 纵向取模:从上到下,从左到右
// 列0: 00111100 -> 0x3C
// 列1: 01000010 -> 0x42
// 列2: 01000010 -> 0x42
// 列3: 01000010 -> 0x42
// 列4: 00111100 -> 0x3C
// 列5: 00000000 -> 0x00
// 列6: 00000000 -> 0x00
// 列7: 00000000 -> 0x00
uint8_t font_A_vertical[8] = {
0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00
};
3.4 取模方向与字节序:细节决定成败
除了横向/纵向,还有两个细节容易被忽略:
- 高位在前 vs 低位在前——比如0x3C,二进制是00111100。如果高位在前,最左边的点对应bit7;低位在前,最左边的点对应bit0。这个顺序错了,字会左右镜像。
- 字节顺序——对于16×16以上的字,一行或一列会拆成多个字节。这些字节在数组里的排列顺序,也决定了显示效果。
我建议你在项目初期,就定好一套统一的取模规范。比如:横向取模、高位在前、字节顺序从左到右。然后所有字模都按这个规范生成,省得后面出问题。
3.5 知识体系总览
下面这张图,把字模提取的核心逻辑串起来了。你可以把它当作一个快速参考。
3.6 避坑指南:我踩过的那些坑
做字模提取这么多年,我总结了几条血泪教训:
- 取模方向一定要跟驱动芯片匹配。 我曾经在SSD1306上用了纵向取模的数据,结果显示出来的字全是乱的。查了半天,才发现驱动默认是横向取模。
- 注意字节内的位序。 有些工具默认高位在前,有些默认低位在前。如果你发现字是镜像的,先检查这个。
- 大尺寸字模要分段测试。 32×32以上的字,数据量大了容易出错。我习惯先测8×8,再测16×16,最后上大尺寸。这样出问题了能快速定位。
- 工具生成的数据,最好人工校验一遍。 尤其是第一个字和最后一个字,容易出边界问题。
一句话总结: 字模提取不难,但细节多。选对工具、定好规范、多做校验,就能少走弯路。