在上一篇(https://bbs.21ic.com/icview-3211342-1-1.html)中尝试点亮了WS2812,这一篇我们来试试使用WS2812显示文字和图案。 最近lvgl比较流行,我们不妨借用一下lvgl的字库。 一、字库文件分析 在lvgl的lv_font文件夹中,有若干字库文件,如lv_font_montserrat_8.c、lv_font_montserrat_10.c……,我们就借用这些字库文件来做显示。关于字体的说明似乎不多,以“lv_font_unscii_8.c”文件为例,说明如下: * Size: 8 px * Bpp: 1 * Opts: 表示这个字体高度是8px(一块8*8的ws2812即可显示),字体颜色深度为1(单色显示)。 最主要的数组有 uint8_t gylph_bitmap[] 字体的显示点阵。 lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] 字体的宽度和偏移。 以 U+21 "!"为例,在glyph_dsc中对应 {.bitmap_index = 1, .adv_w = 128, .box_w = 2, .box_h = 7, .ofs_x = 3, .ofs_y = 1} 其下一个对应的.bitmap_index = 3说明这个!包含了2个uint8_t,索引从1~2,在 gylph_bitmap中可以查找为 0xff, 0xcc, 转化二进制: 1111 1111 1100 1100 字体大小为2*7,左侧空3列,重新排列后,在8*8的板显示为: 00011000 00011000 00011000 00011000 00011000 00000000 00011000 00000000 完成如上分析后,开始动手移植字库。 二、移植 1、点亮屏幕 点亮WS2812的代码在上一篇已经完成了,这里只需要定义背景色和前景色: const uint32_t back_color=0; const uint32_t front_color=0x40; 初始化后,以背景点亮全部64个点。随便加一段代码,尝试点亮其中任意几个点,证明代码无误。接下来开始移植。 2、使用头文件 直接将lv_font_unscii_8.c文件拷贝至目标文件夹。 在字体文件中,调用头#include "../../lvgl.h"直接替换为自建的头文件,例如新建一个“lv_font_type.h”,如附件。 主要类型的说明如下: typedef int16_t lv_coord_t; //在lv_font_**.c中,使用lv_coord_t类型 typedef struct { uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width. 8 bit integer, 4 bit fractional */ uint16_t box_w; /**< Width of the glyph's bounding box*/ uint16_t box_h; /**< Height of the glyph's bounding box*/ int16_t ofs_x; /**< x offset of the bounding box*/ int16_t ofs_y; /**< y offset of the bounding box*/ uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/ } lv_font_glyph_dsc_t; //描述glyph的各属性 typedef struct { #if LV_FONT_FMT_TXT_LARGE == 0 uint32_t bitmap_index : 20; uint32_t adv_w : 12; uint8_t box_w; uint8_t box_h; int8_t ofs_x; int8_t ofs_y; } lv_font_fmt_txt_glyph_dsc_t; //描述glyph 3、读取和显示 按位读取字符可以用类似 uint8_t tmp=gylph_bitmap; if (tmp & 0x80) …… tmp=tmp<<1; 实现。 三、调试 1、在lv_font_unscii_8.c中,最主要的两个数组gylph_bitmap和glyph_dsc类型为static,无法在其它文件中调用,因此需要删除static,改为 const uint8_t gylph_bitmap[] = { …… 和 const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { …… 2、字体描述也类似,改为 lv_font_fmt_txt_dsc_t font_dsc = { …… 3、编译会出现错误,经检查发现使用extern引入其它.c文件中的数组,如果引用时不指定数组大小,不支持sizeof,如 引用命令: extern uint8_t gylph_bitmap[]; 调用sizeof: sizeof(gylph_bitmap)/sizeof(gylph_bitmap[0]) 会出现错误 error: invalid application of 'sizeof' to incomplete type 'uint8_t[] {aka unsigned char[]}' 这里我没有什么好的解决办法,暂时只有使用固定数值。 四、显示 通过尝试已成功点亮如下: 从可显示的第1个“!”到第96个“DT”,看来都能正常显示: 五、扩展 在字体文件“lv_font_montserrat_8.c”中,使用的Bpp为4,即使用4个位显示1个点。类似分析U+21 "!",可以看到,在8*8中显示为: 00000000 00000000 00000000 58000000 57000000 46000000 23000000 46000000 定义颜色4~f显示,0~3不显示,尝试运行,有的显示还是比较正常,有的就很奇怪了。比如“!”: 又比如“e”和“m”: 六、下一步 在lvgl的库中,字体文件显然不只有8*8,还有更大的比如“lv_font_montserrat_16.c”、“lv_font_simsun_16_cjk.c”和“lv_font_unscii_16.c”,下一步准备使用4块8*8的板子拼起来实现这些字体的显示。
|