起因

在 emWin 里直接 GUI_DispString 一段中文,屏幕上出来的是问号或空白。根因在渲染链路:显示一个字符 = 拿它的编码去当前字体里查字模,查不到就没得画——emWin 自带字体(GUI_Font13B 这类)只有 ASCII 范围的字模,汉字根本不在里面。所以显示中文必须做两件事:造一个包含所需汉字的字体;保证源码里字符串的字节编码和字库的码表对得上。这里以加入中文字体为例,说明如何建立字库,调用,并显示字体。

需求

  • 界面显示指定中文文字(示例:微软雅黑 24 号)
  • 字库只包含用到的字,不把整个汉字集烧进 Flash
  • 做好的字库能反复续做(以后加字不用从头来)

技术实现原理

字体 = 码表 + 字模,Flash 决定只能选字

一个 emWin 字体文件本质是“字符编码 → 点阵数据”的查找表。全部汉字做进字库要几 MB,MCU 的 Flash 放不起,所以流程是反过来的:先把所有字禁用(Disable all),再只启用用到的字(Toggle / Enable range)。Edit 菜单的 Save pattern file 把“启用清单”存成文件,下次 Read pattern file 读回来接着加字——这就是字库能续做的机制。

编码必须两头一致

字模按编码索引,索引查不查得到取决于两端编码是否一致:一端是 FontCvtST 生成字库时用的编码,另一端是 C 源码里字符串的实际字节。U2C.exe 这一步的作用就是把 UTF-8 文本转成 C 字符串(逐字节转义形式),保证写进 Keil 工程的字节序列与字库码表对齐——“字库里明明有这个字,屏幕却出方块”多半是这两端编码不一致造成的。

保存的 C 文件名必须用英文

FontCvt 生成的 C 文件里,对外导出的字体变量名由文件名派生(GUI_Fontxxxxx)。文件名用中文,派生出的标识符就是乱码, extern 声明与链接都会出问题,所以务必改成英文文件名。

1. 字体库的建立

1. 字体库的建立

打开macs文件中的emwinSoftware文件夹,打开FontCvtST.exe文件

选择Standard 点击OK

这里以微软雅黑为例,字号24,24字号表示一个英文字符宽12像素长24像素,而中文字符长宽都是24像素。

字体界面,默认所有字是启用的状态,左侧数字是字的字符标准编码

因为我们不建立有所有字体的字库(太大),因此先禁用所有的字体,Edit—Disable all character

右键点击选择Toggle character 即可切换启用/禁用字体,启用字体会以白色显示

如果是中文,可以通过工具转换成标准编码,然后使用Edit—Enable range of character进行切换

如果下次还要继续编辑,则需要保存启用字体列表,Edit——Save pattern file ,在下次要接着编辑时候点击Readpattern file读取。

编辑完成后保存文件,文件名务必改成英文否则内部函数名称会出错乱码

使用Sublime text 打开保存的文件后可以看到字库

在keil项目中添加这一个文件,在需要调用这一个字库的文件位置添加extern GUI_CONST_STORAGE GUI_FONT GUI_Fontxxxxx;

【Xxxxx是字库文件的名称】

2.keil调用并显示文字

先设置文字模式为背景透明 GUI_SetTextMode(GUI_TM_TRANS);

下图演示了几种文字绘制模式。

设置文字的颜色位白色 GUI_SetColor(0xFFFFFF)

之后设置字体 GUI_SetFont(&GUI_Fontxxxxx);

在指定位置显示文字,在这之前我们需要先将文字转换成可以被emwin识别的字符串

打开emwinSoftware文件夹中的软件U2C.exe

选择文件,文件内填写我们需要的文字,保存时候选择UTF-8编码

保存后文件,复制字符到keil中

存储为静态字符类型

之后即可进行调用,方法示例GUI_DispStringAt(&chstr[0], x, y);

代码说明

  • GUI_SetTextMode(GUI_TM_TRANS):文字背景透明。默认模式下每个字符连背景矩形一起画,会盖住底下内容,透明模式只画笔画;
  • GUI_SetColor(0xFFFFFF)GUI_SetFont(&GUI_Fontxxxxx):设置接下来的绘制颜色与字体——两个都是“状态机”式 API,设置后一直生效到下次修改;
  • 字符串定义成静态数组(U2C 转出的转义形式)后,GUI_DispStringAt(&chstr[0], x, y) 在指定位置逐字查字模画出来。

踩坑记录与注意事项

  • 显示问号/方块:先确认当前字体(GUI_SetFont)里有没有这个字的字模,再确认字符串字节编码与字库码表一致——一个查“有没有”,一个查“对不对”;
  • 加了新字不生效:字库 C 文件重新生成后要确认 Keil 工程里替换的是同一个文件、extern 的变量名没变,否则链接到的还是旧字库;
  • 文件名用中文导致标识符乱码:FontCvt 派生的变量名来自文件名,C 文件名务必英文;
  • 字号 24 ≠ 高 24 宽 24 的汉字格:24 号字英文字符宽约 12 像素、汉字 24×24,排版留间距时按这个算,中英混排别用等宽估算;
  • pattern file 别忘存:不加 Save/Read pattern file 的习惯,下次加字就得从全禁用状态重新点,工作量翻倍;
  • 多字号就要多字库:一个字体文件只有一个字号,界面里多种字号需要分别生成多个字库文件、分别 GUI_SetFont 切换。