第53章 STM32H7的LTDC应用之汉字小字库和全字库制作
本章教程为大家讲解汉字小字库和全字库的制作方式,实际项目中用到的地方比较多。
53.1 初学者重要提示
53.2 使用MakeDot小软件生成C文件格式小字库方法
53.3 使用MakeDot小软件生成C文件格式全字库方法
53.4 C文件格式汉字使用方法
53.5 汉字显示方法解析
53.6 LCD驱动移植和使用
53.7 实验例程设计框架
53.8 实验例程说明(MDK)
53.9 实验例程说明(IAR)
5.10 总结
53.1 初学者重要提示
学习本章节前,务必优先学习第52章,需要对点阵字体字符编码有个认识。
LTDC驱动设计和相关问题在第51章有详细说明。
本章节为大家讲解的小字库和全字库方法,简单易用,是直接以C文件格式存储到内部Flash的。支持12点阵,16点阵,24点阵和32点阵的ASCII以及GB2312编码汉字显示。
53.2 使用MakeDot小软件生成C文件格式小字库方法
生成方法比较简单,这里做个介绍:
53.2.1 第1步,准备好显示的字符
比如要显示如下字符,采用16点阵格式:
安富莱电子,www.armfly.com
故人西辞黄鹤楼,烟花三月下扬州。
孤帆远影碧空尽,唯见长江天际流。
53.2.2 第2步,复制要显示的字符到MakeDot小软件
选择16点阵,并将要显示的字符复制到输入窗口:
点击生成数组按钮后的效果如下:
53.2.3 第3步,复制生成的数组到工程中
在输出窗口鼠标右击,选择“全选”,然后再次鼠标右击选择复制。
这样就可以粘贴到工程的hz.c文件里面:
将点阵数据放在相应的文件里面时要注意加上两个0XFF。hz.c文件的内容如下:
/*FLASH中内嵌小字库,只包括本程序用到的汉字点阵
每行点阵数据,头2字节是汉子的内码,后面是16点阵汉子的字模数据。*/#ifdef USE_SMALL_FONT
unsignedchar const g_Hz16[] ={0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//。// 0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xA3,0xAC, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//,// 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0xB0,0xB2, 0x02,0x00,0x01,0x00,0x3F,0xFC,0x20,0x04,0x42,0x08,0x02,0x00,0x02,0x00,0xFF,0xFE,//安// 0x04,0x20,0x08,0x20,0x18,0x40,0x06,0x40,0x01,0x80,0x02,0x60,0x0C,0x10,0x70,0x08,/*中间部分省略未写*/
0xD7,0xD3, 0x00,0x00,0x7F,0xF8,0x00,0x10,0x00,0x20,0x00,0x40,0x01,0x80,0x01,0x00,0xFF,0xFE,//子// 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,/*最后一行必须用0xFF,0xFF结束,这是字库数组结束标志*/
0xFF,0xFF};#elseunsignedchar const g_Hz16[] = {0xFF, 0xFF};#endif
添加完毕点阵数据后,在font.h文件里面使能使用小字库:
#define USE_SMALL_FONT /* 定义此行表示使用小字库, 这个宏只在bsp_tft+lcd.c中使用 */
至此就完成了小字库的汉字添加,用户就可以在使用16点阵时显示第1步中转换的字符了。
53.3 使用MakeDot小软件生成C文件格式全字库方法
生成方法比较简单,这里做个介绍:
53.3.1 第1步,准备好GB2312字符集
GB2312字符集已经在MakeDot小软件里面存好,点击汉字编码按钮可以看到:
53.3.2 第2步,复制GB2312全部字符到MakeDot小软件
复制MakeDot小软件中GB2312所有字符到“输入窗口区”(在GB2312字符显示区,鼠标右击选择全选,之后就可以复制了),
点击生成数组按钮后的效果如下:
53.3.3 第3步,复制生成的数组到工程中
在输出窗口鼠标右击,选择“全选”,然后再次鼠标右击选择复制。
这样就可以粘贴到工程的hz.c文件里面:
将点阵数据放在相应的文件里面时要注意加上两个0XFF。hz.c文件的内容如下:
/*FLASH中内嵌小字库,只包括本程序用到的汉字点阵
每行点阵数据,头2字节是汉子的内码,后面是16点阵汉子的字模数据。*/#ifdef USE_SMALL_FONT
unsignedchar const g_Hz16[] ={0xA1,0xA1, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xA2, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//、// 0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x0C,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//。// 0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00,/*中间部分省略未写*/
0xF7,0xFB, 0x20,0x0E,0xCE,0xF0,0x82,0x22,0xEE,0x92,0x82,0x44,0x82,0x20,0xFE,0x44,0x00,0xF8,//鼷// 0x92,0x10,0x92,0x24,0xDA,0xFE,0x92,0x10,0xDA,0xFE,0x92,0x28,0x93,0x44,0xD9,0x82,0xF7,0xFC, 0x10,0x20,0x3E,0x20,0x22,0x20,0x3E,0x20,0x22,0xF8,0x3E,0x28,0x00,0x28,0x7F,0x28,//鼽// 0x49,0x28,0x7F,0x28,0x49,0x28,0x7F,0x2A,0x00,0x2A,0xFF,0xCA,0x22,0x46,0x42,0x80,0xF7,0xFD, 0x10,0x00,0x3E,0x00,0x22,0x7C,0x3E,0x10,0x22,0x10,0x3E,0x10,0x00,0x10,0x7F,0x10,//鼾// 0x49,0xFE,0x7F,0x10,0x49,0x10,0x7F,0x10,0x00,0x10,0xFF,0x90,0x22,0x10,0x42,0x10,0xF7,0xFE, 0x10,0x10,0x3E,0x10,0x22,0xFE,0x3E,0x38,0x22,0x54,0x3E,0x92,0x00,0x00,0x7F,0x7C,//齄// 0x49,0x44,0x7F,0x7C,0x49,0x44,0x7F,0x7C,0x00,0x44,0xFF,0x80,0x22,0xFE,0x42,0x00,/*最后一行必须用0xFF,0xFF结束,这是字库数组结束标志*/
0xFF,0xFF};#elseunsignedchar const g_Hz16[] = {0xFF, 0xFF};#endif
添加完毕点阵数据后,在font.h文件里面使能宏定义:
#define USE_SMALL_FONT /*这个宏只在bsp_tft+lcd.c中使用 */
至此就完成了全字库的汉字添加,用户就可以使用16点阵的汉字了。
53.4 C文件格式汉字使用方法
汉字的显示方法比较简单。
定义一个FONT_T类型变量:
FONT_T tFont12; /*定义一个12点阵字体结构体变量,用于设置字体参数*/FONT_T tFont16;/*定义一个16点阵字体结构体变量,用于设置字体参数*/FONT_T tFont24;/*定义一个24点阵字体结构体变量,用于设置字体参数*/
FONT_T的原始定义如下:
typedef struct{
FONT_CODE_E FontCode;/*字体代码 FONT_CODE_E*/uint16_t FrontColor;/*字体颜色*/uint16_t BackColor;/*文字背景颜色,透明*/uint16_t Space;/*文字间距,单位 = 像素*/}FONT_T;
初始化变量tFont:
设置12,16和24点阵。
/*设置字体属性*/tFont.FontCode= FC_ST_12; /*字体选择宋体12点阵,高12 x宽11)*/tFont.FrontColor= CL_WHITE; /*字体颜色设置为白色*/tFont.BackColor= CL_MASK; /*文字背景颜色,透明*/tFont.Space= 0; /*字符水平间距, 单位 = 像素*/tFont.FontCode= FC_ST_16; /*字体选择宋体16点阵,高16 x宽15)*/tFont.FrontColor= CL_WHITE; /*字体颜色设置为白色*/tFont.BackColor= CL_MASK; /*文字背景颜色,透明*/tFont.Space= 0; /*字符水平间距, 单位 = 像素*/tFont.FontCode= FC_ST_24; /*字体选择宋体24点阵,高24 x宽23)*/tFont.FrontColor= CL_WHITE; /*字体颜色设置为白色*/tFont.BackColor= CL_MASK; /*文字背景颜色,透明*/tFont.Space= 0; /*字符水平间距, 单位 = 像素*/
调用函数LCD_DispStr显示字符:
下面显示了12,16和24点阵字符。
LCD_DispStr(5, 3, "故人西辞黄鹤楼,烟花三月下扬州。www.armfly.com", &tFont12);
LCD_DispStr(5, 20, "孤帆远影碧空尽,唯见长江天际流。www.armfly.com", &tFont12);
LCD_DispStr(5, 38, "故人西辞黄鹤楼,烟花三月下扬州。", &tFont16);
LCD_DispStr(5, 68, "孤帆远影碧空尽,唯见长江天际流。", &tFont16);
LCD_DispStr(5, 98, "故人西辞黄鹤楼烟花三月下扬州", &tFont24);
LCD_DispStr(5, 128, "孤帆远影碧空尽唯见长江天际流", &tFont24);
53.5 汉字显示方法解析
下面将汉字的显示流程做个说明,几个函数的调用关系如下:
LCD_DispStr ----> LCD_DispStrEx ----->_LCD_ReadAsciiDot
_LCD_ReadHZDot
53.5.1 函数LCD_DispStr
中英文显示都是调用的如下函数实现:
/**********************************************************************************************************
* 函 数 名: LCD_DispStr
* 功能说明: 在LCD指定坐标(左上角)显示一个字符串
* 形 参:
* _usX : X坐标
* _usY : Y坐标
* _ptr : 字符串指针
* _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数
* 返 回 值: 无
**********************************************************************************************************/
void LCD_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont)
{
LCD_DispStrEx(_usX, _usY, _ptr, _tFont,0, 0);
}
这个函数的注释已经比较详细,这里就不再赘述了。而这个函数是通过调用LCD_DispStrEx实现。
53.5.2 函数LCD_DispStrEx
此函数的源码如下:
1. /*2. ******************************************************************************************************
3. * 函 数 名: LCD_DispStrEx
4. * 功能说明: 在LCD指定坐标(左上角)显示一个字符串。 增强型函数。支持左\中\右对齐,支持定长清屏。
5. * 形 参:
6. * _usX : X坐标
7. * _usY : Y坐标
8. * _ptr : 字符串指针
9. * _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数。可以指定RA8875字库
10. * 显示汉字。
11. * _Width : 字符串显示区域的宽度. 0 表示不处理留白区域,此时_Align无效
12. * _Align :字符串在显示区域的对齐方式,
13. * ALIGN_LEFT = 0,
14. * ALIGN_CENTER = 1,
15. * ALIGN_RIGHT = 2
16. * 返 回 值: 无
17. ******************************************************************************************************
18.*/
19. void LCD_DispStrEx(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont, uint16_t _Width,20. uint8_t _Align)21. {22. uint32_t i;23. uint8_t code1;24. uint8_t code2;25. uint8_t buf[32 * 32 / 8]; /*最大支持32点阵汉字*/
26. uint8_t width;27. uint16_t m;28. uint8_t font_width = 0;29. uint8_t font_height = 0;30. uint16_t x, y;31. uint16_t offset;32. uint16_t str_width; /*字符串实际宽度*/
33.34. switch (_tFont->FontCode)35. {36. case FC_ST_12: /*12点阵*/
37. font_height = 12;38. font_width = 12;39. break;40.41. caseFC_ST_16:42. font_height = 16;43. font_width = 16;44. break;45.46. caseF