作者学习自以下博客,经过验证,并重新整理了步骤。
https://www.cnblogs.com/deng1821333144/p/15307883.html#_label2
如有需要,请访问原文章进行查看。



一、TFT_eSPI基础配置

本篇内容以TFT_eSPI库中制作中文字库为重点,不再讲解该库使用环境的搭建,网上讲解的很多,可以自行搜索学习。
请确保自己的TFT_eSPI库已正确完成基础配置(如例程测试成功)后,再尝试本文方法。

截止2022年8月16日
Arduino 1.8.19
TFT_eSPI 2.4.72
该方法测试无误

二、字库制作

1. 找到官方工具

首先,先找到自己安装的TFT_eSPI库所在目录,一般处于Arduino安装目录或是自定义工作空间的libraries文件夹下。
TFT_eSPI目录
在其中的Tools文件夹中,有官方提供的字库制作工具。
tools文件夹
按路径进入Tools\Create_Smooth_Font\Create_font文件夹
目录下有两个文件夹与一个.pde文件
create_font
data:文件夹,存放待转换的原始字体文件(ttf后缀)
FontFiles:文件夹,存放制作出的字库文件(vlw后缀)
Create_font.pde:文件,制作字库所用的代码程序

这里的.pde文件需要使用专门的IDE进行运行,安装如下:

进入官网 https://processing.org/
选择Download,下载对应电脑版本的软件即可。
免费软件(捐赠可忽略)processing

这里讲一下linux下的安装
下载后会得到一个.tgz压缩文件(具体版本号可能存在差异)在这里插入图片描述
将其解压后放到常用于存放程序的目录下
使用终端进入该软件目录,执行install脚本

bash install.sh

在这里插入图片描述
随后桌面上会出现程序图标,运行效果如下:
在这里插入图片描述
如果图标无法正常显示,按提示进行信任操作即可。

2. 准备字体文件

准备好字体文件。
Windows环境下,在系统盘的Windows\Fonts目录下可以找到本机使用的字体文件,可以选想用的字体复制出来。或者可以在网上找字体网站下载字体。ttf格式和otf格式均可。
将字体文件放进前文提到的data文件夹中。
create_font
如本次使用的字体是华光准圆[HGY3_CNKI.ttf]
字体

3. 稍改一下代码

① 设定字体文件

使用Processing IDE打开Create_font.pde文件,修改其130、132、133行(可能随版本改变行数发生变化)。
fontName >>> 字体的名字 (如本次使用的HGY3_CNKI)
fontType >>>字体的格式 (如本次使用的是ttf)
改文件名

② 确定字体的转换大小

fontSize>>> 使用的ttf中的字体大小
displayFontSize>>>转换后用于显示的字体大小
请根据自己使用的tft屏幕大小来确定字库使用的字体大小。
建议两者采用相同的数值,对于汉字建议不低于12像素,否则会模糊。
字体大小

③ 确定字体的转换范围

由于汉字的特殊性,其字体文件往往体积较大,将全部中文字符集转换并使用会对微处理器带来不小的内存负担。因此使用时往往挑选需要使用的部分汉字和符号制作字库,以减小内存消耗。
转换采用的Unicode编码来标识字符。
需要设置和更改的为这两个数组。
第一部分unicodeBlocks数组,设置的unicode范围字符。

在这里插入图片描述
在下面几行的开头删除//以包括该unicode块,还可以通过编辑范围的开始和结束值来确定。可以包括多行。

例如我这里,解注释了第行
0x0021, 0x007E,
这个Unicode块包含了常见的符号与所有的大小写英文字母。

第二部分specificUnicoed数组,设置的单个unicode字符。
在这里插入图片描述
英文与部分符号因为其字符种类较少,且编码联系,可使用Unicode块的方式增加在unicodeBlocks中。
而中文字一般都是独立的,不是按编码顺序,一般中文的字符在specificUnicoed这里添加。

首先要确定添加中文字符的Unicode值,可以使用在线转换工具,并将\u前缀改为0x前缀,并用,分隔。
可以试试这个:http://www.jsons.cn/unicode/

例如:
转换“我才是马邦德”六个字
转换unicode
转换结果如下:\u6211\u624d\u662f\u9a6c\u90a6\u5fb7
进一步,用,0x替换\u。字符少可以手动替换,字符多用查找/替换功能即可。
结果如下:
替换字符头

之后,将转换好的结果放入specificUnicoed数组中,如下:

unicode在processing中如果有需要补充的字符,在这部分之后继续增加即可。一些常用的符号已被程序的作者写好了,直接解注释即可使用。

重点强调:转换的字符与顺序无关,如本例程中使用我才是马邦德六个字符制作中文字库。所建立的是六个汉字unicode与屏幕显示之间的映射关系。与这一句子的顺序无关。使用字库可以单独显示任一字符,或显示字符多次,也可以显示德邦马我我我我我是这样任意语序的句子。

④ 生成vlw文件

修改完毕后,点击左上角的开始按钮,运行程序。
开始运行
正常运行结果会出现一个提示框,显示所有被制作为字库的字符。
如下图所示:
字符集展示

其中,前面的字符都是由unicodeBlocks数组中解注释的那行提供Unicode;后面的“我才是马邦德“则是由我们后续手动添加在specificUnicoed数组中实现的。

若不能成功运行可以查看**常见错误**部分。

同时,在FontFiles文件夹中,可以找到生成的.vlw格式的中间文件。该文件不能直接作为字库使用,需要进一步操作。

字库中间文件

4. 生成字库文件

① vlw文件转为hex数组

关于vlw我了解的也不多,大概可以理解为是一种二进制编码文件。想要使用要把它转化为十六进制的编码

可以使用在线转换工具:
https://tomeko.net/online_tools/file_to_hex.php?lang=zh

按参考文掌的作者说法可以使用bin2hex程序进行转换,但我未进行过尝试。故本文使用在线转换进行讲解。

前文链接页面打开如下:
可以点击左侧的按钮选择文件上传,也可以直接拖动.vlw文件到红框所示的位置即可实现上传。
bin2hex
上传文件成功后会自动加载,并在output区显示转换结果。可以点击下方的Copy output to clipboard一键复制转换结果。
bin2hex

② 创建字库头文件

最后一步了!!
新建一个空白.h文件,名称建议使用全英文标识的“字体”+”字号来表示“。

例如本文转换的 华光准圆 字体,大小为20。
字体文件名则为zhunyuan_20.h

打开空白.h文件,讲上一步骤结尾所复制的全部转码结果粘贴。
转码结果

!!!下一步:加上字库文件头和文件尾!!!
中间的绿色的0x00等一堆,是我们刚才复制出来的一批转码结果。
在开头和结尾分别添加如下

#include <pgmspace.h>
const uint8_t  zhunyuan_20[] PROGMEM = {
0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0B, 0x00,
0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
.				.				.
.				.				.
.				.				.
.				.				.
0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
};

开头添加
#include <pgmspace.h>
const uint8_t zhunyuan_20[] PROGMEM = {

其中zhunyuan_20是自拟的字库名,请各位根据自己使用字库更改。建议与文件命名保持一致。

结尾添加

};
用来表示结束,懂c语言的应该不用解释吧

最后保存,搞定!
因为中文字体数量原因,一般制作字库会只针对于单个项目使用。因此建议将做好的.h字库头文件放在项目文件夹中,与ino工程文件同一级。
放在工程目录下
使用时,在程序中使用#include "你的字体.h"添加自定义字体。
引入自定义字体

三、演示效果

演示板卡:RP2040 GAMEKIT --by eetree
处理器:RP2040
屏幕:TFT ST7789 240*240 SPI

用Arduino编写验证程序(请确保TFT_eSPI已经配置正确):

#include <TFT_eSPI.h> 
#include <zhunyuan_20.h>           //加载自定义字体

TFT_eSPI tft;

void setup() {
    tft.begin();                  //初始化TFT屏幕
    tft.fillScreen(TFT_BLACK);    //刷屏底色为黑色
    tft.setTextColor(TFT_YELLOW); //设置字体颜色
    tft.loadFont(zhunyuan_20);     //设定我们制作的华光准圆的字体
    tft.setCursor(70, 100);       //设置光标位置
    tft.println("马邦德是我");     //打印文字
    tft.setCursor(60, 125);       //设置光标位置
    tft.println("我才是马邦德");   //打印文字
    tft.unloadFont();             //释放字库,节省RAM
}

void loop() {

}

运行效果如下:
运行效果

四、常见错误

1. A null Pfont was passed to textFont()

这代表这Processing IDE在运行时没找到你设定被转换的字体文件。
请再次检查data文件夹中是否存放了待转换字体文件,且与程序130行处所填写的文件名相同。

若还不行请注意一下后缀的大小写问题。Processing IDE区分大小写而多数文件后缀名不区分大小写。因此有些字体文件的后缀可能为.TTF,因此 Processing IDE检测.ttf文件便无法检测到。
若出现这种情况,建议把字体文件的后缀改为小写即可。

2. 字体.h: No such file or directory

在Arduino中使用include函数调用字体时发生。
如果你确定你的.h头文件写好了。那一定是保存的目录或是引用方式有误。
若保存在Arduino的libraries文件夹下,include函数需要使用尖括号<字体.h>来进行调用。
若保存在项目目录下,include函数需要使用引号"字体.h"来进行调用。
也有可能是存在相对调用路径的问题,请认真检查校对。


声明

该文章是自己学习摸索过程中得出的一些结论,内容不一定百分之百正确,描述语言也不一定专业,若有错误请大佬评论区指正,谢谢!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐