ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

LCD/OLED取模工具全面解析:字符与图片转点阵的实战指南

2026/9/7 7:26:18 拓冰建站 浏览量
LCD/OLED取模工具全面解析:字符与图片转点阵的实战指南 简介面向 LCD 与 OLED 屏开发的字符/图像取模工具适合嵌入式系统、物联网设备开发者使用可将字符或位图快速转换为显示屏所需的二进制点阵数据免去手工计算像素的低效过程。工具支持字符取模与图像取模两大功能前者可将 ASCII 等编码字符生成自定义字模便于定制字体后者能将 BMP 等位图转换为单色或灰度格式适配常见屏幕的有限色彩能力。压缩包以 RAR 格式封装大小仅 501KB内附 C 语言源码与 CHM 中文帮助文档方便开发者直接借鉴集成也可通过图文步骤熟悉取模流程。资源已有 1147 人学习下载对希望提升屏幕开发效率、统一多设备字符与图像处理流程的开发者来说是一份轻量而实用的辅助工具。1. 取模工具到底在解决什么问题从“屏上没字”到“屏上有字”的最后一公里做LCD或OLED显示开发的人大概率都经历过这个阶段屏幕好不容易点亮了背光也亮了结果想在上面显示一个“Hello”或者一个电压数值却不知道字符是怎么“画”上去的。我最早接触OLED时也是这样用的还是SSD1306驱动的0.96寸屏寄存器配置好了整屏也能清成全黑但一查手册才发现驱动IC根本不认识ASCII码它只认“哪几个像素点该亮、哪几个不该亮”。换句话说你想显示一个字母“A”必须先把“A”拆成一个由0和1组成的点阵数据表告诉屏幕第几行第几列要亮屏幕才能把这个字母呈现出来。这个“把字符或图像拆成点阵数据”的过程就叫取模而干这件事的工具就是开发圈子里常说的取模工具。它的本质非常简单输入一个字符或一张图片输出一个C语言数组数组中每个字节的每一位对应屏幕上的一个像素点。1代表这个像素点亮0代表不亮。你在代码里把这个数组写到显存里屏幕上就能看到对应的字形或画面。那为什么不直接在代码里手写点阵数据因为手写一张16x16的汉字图几十个字节的0和1写错一位显示出来就是一团乱码而且效率极低。取模工具的价值就是把这个过程自动化——你把字打进去、图片拖进去它帮你生成排布规整、带注视的数组文件你只需要复制粘贴进工程即可。这类工具解决的另一个隐藏问题是不同显示屏驱动IC之间的“数据组织方式差异”。同样是显示一个汉字横向取模、纵向取模、字节高位在前还是低位在前生成的数组内容完全不同。如果驱动代码里写的是纵向取模的显示逻辑你却贴了横向取模的数据结果就是字形翻转、笔画错乱。取模工具里那些看似不起眼的参数选项实际上决定了数据能否和你的屏幕驱动代码正确匹配。这一点后面我详细展开也是本文最值得看的部分。2. 取模参数不是随便选的横向取模、纵向取模与字节序背后的显示原理很多新手拿到取模工具看到界面上“横向取模”“纵向取模”“字节正序”“字节反序”“阴码”“阳码”这些选项就发懵。我先说结论这些参数没有绝对的对错只有匹配不匹配的问题。关键看两个东西——你的驱动IC是什么、你的画点函数是怎么写的。2.1 横向取模与纵向取模的本质横向取模也叫水平取模指在点阵图上按从左到右的方向每8个像素点凑成一个字节8个点凑满后换到下一行继续。假如你要取一个8x8的字符横向取模的结果就是8个字节每个字节代表一行中8个像素的状态。这种方式符合人眼从左往右阅读的习惯调试时对照代码很容易看出哪个字节对应哪一行。纵向取模则相反按从上到下的方向先把同一列里连续的8个像素点凑成一个字节8个点取满后再换到下一列。这种方式和SSD1306这类OLED驱动IC的页寻址模式天然契合。SSD1306把屏幕划分为8页每页包含8行像素数据在页内是按列方向连续扫描的。因此很多OLED驱动库默认就按纵向取模来准备字模数据写显存时直接把数组按页、按列刷进去效率最高。我给一个具体例子用8x8的字符“A”演示横向取模的样子// 8x8 字符 A横向取模阳码1 表示点亮 const unsigned char font_A[] { 0x18, // 00011000 0x24, // 00100100 0x42, // 01000010 0x42, // 01000010 0x7E, // 01111110 0x42, // 01000010 0x42, // 01000010 0x00 // 00000000 };如果是纵向取模同一个“A”的数据排列方式就会完全变个样因为每列8个点被压缩成一个字节列与列之间的字节顺序成了主导。很多OLED例程里用的5x7或6x8英文字模看着像乱码实际上就是纵向取模后的正常结果。2.2 高位在前与低位在前的坑取模工具里的“字节正序/反序”严格说叫“位序”决定的是一个字节内部哪一位对应像素的最左端或最上端。假设一个字节8位分别是D7-D0高位在前表示D7对应第一个像素低位在前表示D0对应第一个像素。这个参数如果选错最典型的现象就是字符横向被镜像了或者纵向被颠倒了。比如你从网上找了一个字模库贴在OLED上显示发现字母“b”显示出来像“d”或者汉字上下颠倒大概率就是位序不匹配。SSD1306的数据手册里明确写了它的数据移位顺序实际开发中最稳妥的办法不是死记手册而是先用一个已知的简单字符做测试比如数字“0”或字母“A”根据显示效果反推工具端应该选哪种位序。2.3 阴码和阳码到底要不要纠结阴码和阳码的定义在不同工具里不太一致但核心就一件事1代表亮还是0代表亮。阳码一般指笔画处为1、背景为0阴码则相反笔画处为0、背景为1。在OLED这类自发光屏上我强烈建议用阳码也就是1代表点亮因为0越多意味着不亮的像素越多OLED的黑底效果更纯粹耗电也更低。而在LCD配白色背光的场景里如果屏本身是白底黑字风格反而可能用阴码更合适。这个没有标准答案以最终视觉效果为准。3. 字符取模实操ASCII、汉字与自定义图形符号的参数配置3.1 英文字符取模尺寸和基线先想清楚英文取模相对简单常见的有5x7、6x8、8x8、8x16几种。5x7的字模省空间一屏能显示更多内容但字符笔画细小尺寸下可读性一般8x16的字模在128x64的OLED上正好是8列x2页显示信息密度适中是很多仪表界面的首选。我的建议是如果项目以数值显示为主就用8x16大字号扫一眼就能看清如果项目需要显示较多文字信息用6x8相对紧凑。取模时注意字符之间的间距问题——很多6x8字模实际只用了左边6列右边留2列做空隙如果你把宽度参数调成6显示时字符会挤在一起这种情况下宁可取8列宽。3.2 汉字取模编码表和数组结构要配对汉字取模和英文最大的区别在于字库管理。16x16汉字点阵是嵌入式界最经典的配置每个汉字占32字节。取模工具里通常有“GB2312内码”输入框你直接输入汉字工具会查出区位码并生成对应的点阵数据。我在实际项目中踩过一个坑用PCtoLCD2002取了一批16x16汉字生成的是横向取模数据但驱动里用的显示函数是按纵向方式刷显存的结果所有汉字都出现了左右笔画断裂的怪像。后来在工具里把取模方式改成“纵向取模”重新生成数据问题立刻消失。所以汉字取模时第一件事不是关心汉字本身而是先确认驱动代码的刷屏逻辑是什么方向的。3.3 自定义图形符号取模最容易被低估的一类电池电量图标、WiFi信号图标、箭头、温度计符号这些不能用字符输入法直接打出来的图形恰恰是取模工具最出彩的地方。做法有两种第一种是在取模工具自带的点阵编辑区里手动画适合简单图形第二种是先用画图工具做一个BMP图片再导入取模工具适合复杂图形。我建议图标素材单独用一个数组文件保存命名清晰比如battery_icon_4格、battery_icon_3格方便后续切换显示。图标的取模参数和汉字保持一致这样驱动代码只需要一个通用的“画位图”函数不用为图标单独写一套显示逻辑。3.4 我常用的字符取模参数参考参数项推荐取值备注取模方式纵向取模SSD1306 OLED首选位序高位在前以实际显示效果为准码制阳码1点亮0熄灭每行显示数16针对16x16汉字数据输出格式C数组带const修饰字模宽度按需选择8、12、16、24、324. 图片取模没那么简单从位深、缩放比例到反色的连续坑字符取模的输入是一个“字”而图片取模的输入是一张“图”。图片取模比字符取模复杂是因为图片有灰度、有颜色、有分辨率而单色OLED或单色LCD只有一个“亮”和“不亮”的二元状态。你必须在取模前先把图片处理成屏幕能接受的形式。4.1 位深选择1bit、4bit还是8bit1bit意味着每个像素只占1位0或1适合显示图标、边框、简单的波形图。4bit灰度能显示16级亮度适合显示有一定层次感的图片但代价是显存占用成倍增加。8bit灰度有256级效果最细腻但一屏128x64的数据量已经达到8KB对单片机RAM和刷新率都是考验。如果你用的是128x64的OLED我的建议是默认用1bit。一是硬件本身没有灰度支持强行做多级灰度需要靠PWM调亮暗刷新率会大打折扣二是单色图像在OLED上做“反色”显示黑白对比强烈实际效果往往比灰蒙蒙的半色调更好看。4.2 反色处理OLED显示图片的核心技巧OLED自发光特性决定了点亮的像素越多屏幕越亮功耗越高。一张白底黑线的图直接取模显示会看到大面积亮光刺眼不说还加速像素老化。正确的做法是在取模工具里勾选“反色”把白底变成黑底让笔画部分点亮背景保持熄灭。这样屏幕看起来是“黑底发光字”既有OLED的质感又省电。在Img2Lcd这类工具里反色功能通常是一个复选框叫“反色”或“颜色反转”。我每次转换图片前都会确认一遍因为漏勾反色的图上屏效果基本没法看。4.3 缩放和裁剪比取模本身更影响最终效果很多新手直接导入一张800x600的照片然后问为什么生成的数组一大堆、屏幕显示却花成一团。真正常用的流程是先预处理图片。先用图片编辑工具把图片裁剪成屏幕分辨率比例一致的尺寸再缩放到目标宽高比如128x64最后转成灰度图。这一步我在项目里通常用画图工具就能完成打开图片调整尺寸另存为单色BMP。有了这张干净的预处理图再交给取模工具生成的数据基本一次就能用。4.4 一次完整的图片取模流程以Img2Lcd为例我习惯这套参数输入128x64、单色位图输出灰度单色1bit最大宽度和高度128、64扫描方式水平扫描输出数据类型C数组反色勾选包含头文件按需勾选转换完成后生成的数组直接用即可。需要注意某些取模工具生成的数组默认带static关键字如果你在函数外面定义全局字模数组记得去掉static或改成const避免链接作用域出错。5. 取模数据的工程化用法从零散数组到可维护的字库与素材管理字符取模一次可能只生成几十个字节但一个完整的项目做下来ASCII字模、汉字字模、图标素材会积累出几百甚至上千个数组。如果不做工程化管理代码很快就会变成一锅粥。5.1 按功能拆分文件别把字模和业务逻辑混在一起我的习惯是在工程里建一个font目录下面分三个文件font_ascii.c保存英文和数字字模font_hz.c保存汉字字模font_icons.c保存图标素材。每个文件配一个同名头文件头文件里只暴露数组的声明不暴露具体数据。这样做好处很明显业务代码里只管调用OLED_ShowString()、OLED_ShowChinese()这类函数完全不用关心字模数据是怎么存的。后续要换字体、加字符只需要改font_ascii.c和font_hz.c业务代码一行都不用动。5.2 const修饰字模数组RAM和Flash的博弈单片机上的RAM通常很宝贵STM32F103C8T6只有20KB RAM而Flash却有64KB。字模数据是只读的必须用const声明存放在Flash区而不是默认的RAM区。很多新手写代码时不加const导致一个小小字模库就占掉几KB RAM程序跑起来后堆栈空间被挤压表现为莫名死机、变量被改写。这个问题排查起来非常隐蔽所以我在所有字模数组定义处都加了const并且用编译器的map文件检查数据段大小。5.3 不要一次性导入整个汉字库有些工具可以一键生成整个GB2312字库的字模看起来很方便但生成的数组体积巨大动辄几百KB。对于128x64的小屏一屏最多显示几十个汉字你根本用不到这么多字模。我建议的做法是先把项目中可能出现的菜单文案、状态提示整理一份清单只对这些汉字取模把字模数量控制在几十个以内。如果后期增加了新功能再补充取模把新数据追加到font_hz.c末尾。这样既省Flash又便于维护。5.4 给字模数组建立索引表当汉字数量多起来后一个个搜索数组名再调用会很痛苦。我通常建一个结构体数组把汉字的GB2312编码和对应字模指针关联起来typedef struct { uint16_t code; const uint8_t *font_data; } FONT_HZ_INDEX; const FONT_HZ_INDEX font_hz_index[] { {0xC4E3, font_hz_你}, {0xBAC3, font_hz_好}, {0xCAC0, font_hz_世}, {0xBDE7, font_hz_界}, };显示汉字时先查索引表找到对应编码的字模指针再传给驱动函数。这样新增汉字只需要加一条索引记录代码可读性也高得多。6. 一组实测参数参考与排查乱码的经验清单6.1 我在STM32SSD1306项目里的参数组合给各位一组我实测过的组合直接可用的那种主控STM32F103C8T6屏幕0.96寸OLEDSSD1306128x64通信硬件SPI取模工具PCtoLCD2002取模方式纵向取模位序高位在前码制阳码字符集ASCII 8x16、汉字16x16这套组合下字符和汉字显示都正常没有镜像、颠倒问题。如果你用I2C接口取模参数也是一样的因为数据组织方式由驱动IC决定不因通信接口变化而变化。6.2 乱码排查的几条路径如果上屏后字符是乱的按下面顺序排查第一看方向。字符镜像错乱通常是位序反了把“高位在前”改成“低位在前”或者反过来再试一次。第二看排列。笔画断裂、左右分离多半是横向取模和纵向取模不匹配改取模方式即可。第三看亮度。背景大面积发光说明明暗逻辑反了切换阴码阳码。第四看位移。字符整体偏移或显示到错误位置检查驱动函数的页地址和列地址计算逻辑有时候不是字模问题而是坐标计算越界。6.3 最后再提醒几个小事取模工具生成的注释里通常带着原字符或原图信息保留这些注释对后续维护很有帮助不要为了省空间删掉。字模数组定义时建议把code和font_data都加上const限定避免意外写入Flash导致异常。如果你需要同时支持多款屏幕最好把取模参数记录在代码注释里换屏时能快速定位问题。我在不同项目里反复切换过OLED和LCD最大的体会是取模本身不难难的是搞懂“驱动代码期待什么格式的数据”。每次开始一个新屏幕的驱动开发我都先用一个8x8的“A”做测试确认取模参数无误后再批量生成字模和图片数据。这个习惯帮我省下了大量排查时间也推荐你试试。本文还有配套的精品资源点击获取