前言
已知字模是图形数据,而图形在计算机中是由一个个像素点组成的,所以字模实质是一个个像素点数据。为方便处理,我们把字模定义成方块形的像素点阵,且每个像素点只有0和1这两种状态(可以理解为单色图像数据),下图两个宽、高为16x16的像素点阵组成的两个汉字图形,其中的黑色像素点即为文字的笔迹。计算机要表示这样的图形,只需使用16x16个二进制数据位,每个数据位记录一个像素点的状态,把黑色像素点以“1”表示,无色像素点以“0”表示即可。这样的一个汉字图形,使用16x16/8=32个字节来就可以记录下来。
目录
一、LCD显示屏软/硬件准备
二、LCD显示屏硬件关键方面
三、LCD显示中英文步骤
四、编写代码
1.取模
2.字库
一、LCD显示屏软/硬件准备
1.软件:Keil5编程软件
2.PCtoLCD2002字模软件
3.硬件:STM32板子
二、LCD显示屏硬件关键方面
LCD显示屏通常用于显示各种文本和图像,包括中英文。要在LCD显示屏上显示中英文,你需要考虑以下几个关键方面:
1、硬件支持:
确保你的LCD显示屏支持中文字符集,如GB2312、GBK、GB18030或Unicode(UTF-8)。
检查显示屏的控制器或驱动器是否支持这些字符集。
2、软件/编程:
使用适当的编程语言或框架(如C、C++、Python、Arduino等)来编写显示中英文的代码。
根据显示屏的接口和协议(如SPI、I2C、HD44780等),选择或编写适当的库或驱动程序。
在代码中指定要显示的文本,并确保使用正确的字符编码。
3、字体和字符集:
对于LCD显示屏,字体通常是预定义的位图或矢量图形。确保你有可用的中文字体,并将其集成到你的系统中。如果你使用的是图形LCD(如TFT LCD),你可能需要使用图形库(如Adafruit GFX、u8g2等)来绘制文本和图像。对于简单的字符LCD(如HD44780),你可能需要使用自定义的字符生成器来创建中文字符的位图表示,并将这些位图存储在显示屏的字符生成器RAM(CGRAM)中。
4、内存限制:
考虑LCD显示屏的内存限制。对于字符LCD,CGRAM空间有限,可能无法存储大量中文字符的位图。对于图形LCD,确保你有足够的内存来存储字体和图像数据。
5、测试和调试:
在将代码部署到实际硬件之前,在模拟器或开发环境中进行测试。检查文本显示是否正确,特别是中文字符的显示。如果遇到问题,使用调试工具或日志记录来诊断问题。
6、用户界面设计:
考虑中英文混合显示的用户界面设计。确保文本布局和大小适合显示屏的尺寸和分辨率。
使用易于理解的词汇和短语,避免复杂的句子和术语。
7、文档和支持:
提供用户手册或在线文档,说明如何在LCD显示屏上查看和解释中英文文本。提供技术支持和常见问题解答(FAQ),以帮助用户解决在使用过程中遇到的问题。
三、LCD显示中英文步骤
在LCD显示屏上显示中文通常涉及多个步骤,以下是一个清晰的步骤指南,结合了参考文章中的相关信息:
1、准备字库或字模
生成字库:使用专门的字库生成软件(如PCtoLCD2002完美版)为LCD显示屏生成中文字库。这些软件通常允许用户输入汉字并生成对应的点阵数据(字模)。
设置字库选项:在生成字库时,需要设置一些选项,如字体大小(通常是16x16像素)、字体样式等。
配置字模的解析顺序,解析顺序要和代码配套,否则会显示乱码。
生成后的字模数据如下,以“物联网”为例:
2、将字库数据集成到系统中
赋值到MDK5或创建.h文件:将生成的字模数据赋值到嵌入式系统的开发环境中,如MDK5。也可以创建一个头文件(.h)来存储这些数据,以便在代码中引用。
注意内存限制:确保系统有足够的内存来存储这些字模数据。对于字符LCD,CGRAM空间有限,可能无法存储大量中文字符的位图。
3、编写显示中文的函数
LCD_ShowChinese函数:编写一个函数(如LCD_ShowChinese)来处理在LCD上显示中文的功能。这个函数通常接受起点坐标、要显示的汉字在字库中的编号、字体大小以及显示模式等参数。
解析字模数据:在函数内部,根据提供的汉字编号从字库中取出对应的字模数据,并解析这些数据以在LCD上绘制出对应的汉字。
4、 调用显示函数
调用LCD_ShowChinese函数:在需要显示中文的地方,调用LCD_ShowChinese函数,并传入适当的参数。
设置颜色和模式:根据需要,可以使用其他函数(如LCD_SetBackColor、LCD_SetTextColor)来设置文本的背景色和前景色,以及使用其他模式选项。
5、测试和调试
在模拟器或开发环境中测试:在将代码部署到实际硬件之前,在模拟器或开发环境中进行测试,确保中文能够正确显示。
检查显示效果:检查LCD显示屏上的中文显示效果,包括文字清晰度、颜色、位置等。
6、注意事项
考虑LCD的分辨率和尺寸:确保选择的字体大小和显示模式适合LCD的分辨率和尺寸。
注意内存管理:对于资源有限的嵌入式系统,需要仔细管理内存使用,避免内存溢出等问题。
提供文档和支持:为用户提供相关的文档和支持信息,帮助他们更好地理解和使用LCD显示屏上的中文显示功能。
四、编写代码
1.设置字体:使用“LCD_SetZNFont”函数设置字体,一般在main函数中while(1)之前调用一次即可,除非要更换字体则需重新调用。
LCD_SetZNFont(&ZN_Font16x16);
2.使用字体:调用“LCD_DrawCharCN”函数显示中文字体,注意,必须是由字模数据的字才能显示,没有字模数据的字不会显示,所以想显示哪些中文字体,需要生成这些字模的字体并添加到代码中。
LCD_DrawCharCN(210,220,"物联网·"); //在坐标点(210,220)显示“物联网”四个中文字体
3.中文和英文混合显示:LCD_DrawCharCN函数既可以显示中文也可以显示英文
LCD_DrawCharCN(210,220,"物联网 Welcom");//显示 物联网 Welcom
注意,其中的英文字符所使用的字体,由“LCD_SetFont()”函数来设置。
4.需要显示的文字代码:
a.取模
uint8_t ZN16x16_Table[] = {
// 物(0) 联(1) 网(2)
0x10,0x80,0x10,0x80,0x50,0x80,0x50,0xFC,0x7D,0x54,0x52,0x54,0x90,0x54,0x10,0x94,0x1C,0x94,0xF1,0x24,0x52,0x24,0x10,0x44,
0x10,0x44,0x10,0x84,0x11,0x28,0x10,0x10,/*"物",0*/
0x00,0x88,0xFC,0x48,0x48,0x50,0x48,0x00,0x79,0xFC,0x48,0x20,0x48,0x20,0x78,0x20,0x4B,0xFE,0x48,0x20,0x4C,0x50,0x78,0x50,
0xC8,0x88,0x08,0x88,0x09,0x04,0x0A,0x02,/*"联",1*/
0x00,0x00,0x7F,0xFC,0x40,0x04,0x40,0x04,0x42,0x14,0x52,0x94,0x4A,0x54,0x44,0x24,0x44,0x24,0x4A,0x54,0x4A,0x54,0x52,0x94,
0x61,0x04,0x40,0x04,0x40,0x14,0x40,0x08,/*"网",2*/
};
unsigned char zm16x16_index[]="物联网";
znsFONT ZN_Font16x16 = {
ZN16x16_Table,
zm16x16_index,
16, /* Width */
16, /* Height */
};
显示文字的核心就是将文字的字模通过显示屏显示,所以程序在运行工程中就需要能读取字模,有两种方式可以实现,第1种是将字体文件作为程序的一部分,保存在片内flash中;第二种是将字体文件保存在SD卡或者其他存储介质中,再让芯片去读取SD卡内的字模数据。两种方法各有优缺点,第1种直接下载包含了字体文件的HEX文件即可使用,并且不会因为外部存储设备丢失等问题导致文字显示异常,缺点是芯片存储空间有限(STM32F429片内可用空间位1024KB),字体文件如果太大或者放入多个字体文件时,存储空间就不够了。
第2种优点是SD存储空间很大,可以放很多种字体文件,但是如果SD丢失或者连接失败,那么字体文件就不可用了,也就无法显示字体。
b.字库
下文使用第2种方法,假设生成的字体文件名字为“GB2312_H2424.FON”,字体文件大小约为576KB,芯片存储空间位1024KB,是可以放得下的。
在keil中新建一个名字为“import_font.s”的文件,并加入到文件列表中。注意:该文件后缀是“.S”,然后在该文件中添加以下内容。
AREA |subr|,DATA,READONLY
EXPORT GB2312_H2424 ;以这个变量表示字库文件
;声明这个变量
GB2312_H2424
incbin .\GB2312_H2424.FON ;包含字库文件
END
程序说明及注意如下图,字体文件和“import_font.s”文件需要再同一个目录下
lcd_show_zn_font.c代码
//File name : lcd_show_zn_font.c
//Description : 通过读取字库的方式显示中文字符
//Author : 梁斌强
//Version : V1.0
//Date : 2024.5.20
#include "lcd_show_zn_font.h"
#include "string.h"
#include "bsp_lcd.h"
#define ZOOMMAXBUFF 16384
uint8_t zoomBuff[ZOOMMAXBUFF] = {0}; //用于缩放的缓存,最大支持到128*128
//读取中文字库,现在读取的是放在片内flash的字库
/**
* @brief 获取FLASH中文显示字库数据
* @param pBuffer:存储字库矩阵的缓冲区
* @param c : 要获取的文字
* @retval None.
*/
static void GetGB2312Code_from_Flash( uint8_t * pBuffer, uint16_t c)
{
unsigned char High8bit,Low8bit;
unsigned int pos;
High8bit= c >> 8; /* 取高8位数据 */
Low8bit= c & 0x00FF; /* 取低8位数据 */
/*GB2312 公式*/
pos = ((High8bit-0xa1)*94+Low8bit-0xa1)*macWIDTH_CH_CHAR*macHEIGHT_CH_CHAR/8;
memcpy(pBuffer,macFontName+pos,macWIDTH_CH_CHAR*macHEIGHT_CH_CHAR/8);
}
/**
* @brief 在显示器上显示一个中文字符
* @param usX :在特定扫描方向下字符的起始X坐标
* @param usY :在特定扫描方向下字符的起始Y坐标
* @param usChar :要显示的中文字符(国标码)
* @retval 无
*/
static void LCD_DispChar_CH( uint16_t usX, uint16_t usY, uint16_t usChar)
{
uint8_t ucPage, ucColumn;
uint8_t ucBuffer [ macWIDTH_CH_CHAR*macHEIGHT_CH_CHAR/8 ];
uint32_t usTemp;
uint32_t xpos =0;
uint32_t Xaddress = 0;
/*xpos表示当前行的显存偏移位置*/
xpos = usX*LCD_PIXEL_WIDTH*2;
/*Xaddress表示像素点*/
Xaddress += usY;
GetGB2312Code_from_Flash( ucBuffer, usChar ); //取字模数据
/*ucPage表示当前行数*/
for ( ucPage = 0; ucPage < macHEIGHT_CH_CHAR; ucPage ++ )
{
/* 取出3个字节的数据,在lcd上即是一个汉字的一行 */
usTemp = ucBuffer [ ucPage * 3 ];
usTemp = ( usTemp << 8 );
usTemp |= ucBuffer [ ucPage * 3 + 1 ];
usTemp = ( usTemp << 8 );
usTemp |= ucBuffer [ ucPage * 3 + 2];
uint16_t CurrentBackColor = 0;
uint16_t CurrentTextColor = 0;
uint32_t CurrentFrameBuffer = LCD_SetCursor(0,0);
LCD_GetColors(&CurrentTextColor,&CurrentBackColor);
for ( ucColumn = 0; ucColumn < macWIDTH_CH_CHAR; ucColumn ++ )
{
if ( usTemp & ( 0x01 << (macWIDTH_CH_CHAR - 1) ) ) //高位在前
{
//字体色
/* Write data value to all SDRAM memory */
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentTextColor;
}
else
{
//背景色
/* Write data value to all SDRAM memory */
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentBackColor;
}
/*指向当前行的下一个点*/
Xaddress++;
usTemp <<= 1;
}
/*显示完一行*/
/*指向字符显示矩阵下一行的第一个像素点*/
Xaddress += (LCD_PIXEL_WIDTH - macWIDTH_CH_CHAR);
}
}
/**
* @brief 在显示器上显示中英文字符串,超出液晶宽度时会自动换行。
中英文混显示时,请把英文字体设置为Font16x24格式
* @param Line :行(也可理解为y坐标)
* @param Column :列(也可理解为x坐标)
* @param pStr :要显示的字符串的首地址
* @retval 无
*/
void LCD_DispString_EN_CH(uint16_t Column, uint16_t Line, const uint8_t * pStr )
{
uint16_t usCh;
while( * pStr != '\0' )
{
if ( * pStr <= 126 ) //英文字符
{
/*自动换行*/
if ( ( Column + LCD_GetFont()->Width ) > LCD_PIXEL_WIDTH )
{
Column = 0;
Line += LCD_GetFont()->Height;
}
if ( ( Line + LCD_GetFont()->Height ) > LCD_PIXEL_HEIGHT )
{
Column = 0;
Line = 0;
}
LCD_DisplayChar(Line,Column,*pStr);
Column += LCD_GetFont()->Width;
pStr ++;
}
else //汉字字符
{
if ( ( Column + macWIDTH_CH_CHAR ) > LCD_PIXEL_WIDTH )
{
Column = 0;
Line += macHEIGHT_CH_CHAR;
}
if ( ( Line + macHEIGHT_CH_CHAR ) > LCD_PIXEL_HEIGHT )
{
Column = 0;
Line = 0;
}
/*一个汉字两字节*/
usCh = * ( uint16_t * ) pStr;
usCh = ( usCh << 8 ) + ( usCh >> 8 );
LCD_DispChar_CH (Line,Column, usCh);
Column += macWIDTH_CH_CHAR;
pStr += 2; //一个汉字两个字节
}
}
}
/**
* @brief 缩放字模,缩放后的字模由1个像素点由8个数据位来表示
0x01表示笔迹,0x00表示空白区
* @param in_width :原始字符宽度
* @param in_heig :原始字符高度
* @param out_width :缩放后的字符宽度
* @param out_heig:缩放后的字符高度
* @param in_ptr :字库输入指针 注意:1pixel 1bit
* @param out_ptr :缩放后的字符输出指针 注意: 1pixel 8bit
* out_ptr实际上没有正常输出,改成了直接输出到全局指针zoomBuff中
* @param en_cn :0为英文,1为中文
* @retval 无
*/
void LCD_zoomChar(uint16_t in_width, //原始字符宽度
uint16_t in_heig, //原始字符高度
uint16_t out_width, //缩放后的字符宽度
uint16_t out_heig, //缩放后的字符高度
uint8_t *in_ptr, //字库输入指针 注意:1pixel 1bit
uint8_t *out_ptr, //缩放后的字符输出指针 注意: 1pixel 8bit
uint8_t en_cn) //0为英文,1为中文
{
uint8_t *pts,*ots;
//根据源字模及目标字模大小,设定运算比例因子,左移16是为了把浮点运算转成定点运算
unsigned int xrIntFloat_16=(in_width<<16)/out_width+1;
unsigned int yrIntFloat_16=(in_heig<<16)/out_heig+1;
unsigned int srcy_16=0;
unsigned int y,x;
uint8_t *pSrcLine;
uint8_t tempBuff[1024] = {0};
u32 uChar;
u16 charBit = in_width / 8;
u16 Bitdiff = 32 - in_width;
//检查参数是否合法
if(in_width >= 32) return; //字库不允许超过32像素
if(in_width * in_heig == 0) return;
if(in_width * in_heig >= 1024 ) return; //限制输入最大 32*32
if(out_width * out_heig == 0) return;
if(out_width * out_heig >= ZOOMMAXBUFF ) return; //限制最大缩放 128*128
pts = (uint8_t*)&tempBuff;
//为方便运算,字库的数据由1 pixel 1bit 映射到1pixel 8bit
//0x01表示笔迹,0x00表示空白区
if(en_cn == 0x00)//英文
{
//这里以16 * 24字库作为测试,其他大小的字库自行根据下列代码做下映射就可以
//英文和中文字库上下边界不对,可在此次调整。需要注意tempBuff防止溢出
pts+=in_width*4;
for(y=0;y<in_heig;y++)
{
uChar = *(u32 *)(in_ptr + y * charBit) >> Bitdiff;
for(x=0;x<in_width;x++)
{
*pts++ = (uChar >> x) & 0x01;
}
}
}
else //中文
{
for(y=0;y<in_heig;y++)
{
/*源字模数据*/
uChar = in_ptr [ y * 3 ];
uChar = ( uChar << 8 );
uChar |= in_ptr [ y * 3 + 1 ];
uChar = ( uChar << 8 );
uChar |= in_ptr [ y * 3 + 2];
/*映射*/
for(x=0;x<in_width;x++)
{
if(((uChar << x) & 0x800000) == 0x800000)
*pts++ = 0x01;
else
*pts++ = 0x00;
}
}
}
//zoom过程
pts = (uint8_t*)&tempBuff; //映射后的源数据指针
ots = (uint8_t*)&zoomBuff; //输出数据的指针
for (y=0;y<out_heig;y++) /*行遍历*/
{
unsigned int srcx_16=0;
pSrcLine=pts+in_width*(srcy_16>>16);
for (x=0;x<out_width;x++) /*行内像素遍历*/
{
ots[x]=pSrcLine[srcx_16>>16]; //把源字模数据复制到目标指针中
srcx_16+=xrIntFloat_16; //按比例偏移源像素点
}
srcy_16+=yrIntFloat_16; //按比例偏移源像素点
ots+=out_width;
}
/*!!!缩放后的字模数据直接存储到全局指针zoomBuff里了*/
out_ptr = (uint8_t*)&zoomBuff; //out_ptr没有正确传出,后面调用直接改成了全局变量指针!
/*实际中如果使用out_ptr不需要下面这一句!!!
只是因为out_ptr没有使用,会导致warning。强迫症*/
out_ptr++;
}
/**
* @brief 利用缩放后的字模显示字符
* @param Xpos :字符显示位置x
* @param Ypos :字符显示位置y
* @param Font_width :字符宽度
* @param Font_Heig:字符高度
* @param c :要显示的字模数据
* @param DrawModel :是否反色显示
* @retval 无
*/
void LCD_DrawChar_Ex(uint16_t Xpos, //字符显示位置x
uint16_t Ypos, //字符显示位置y
uint16_t Font_width, //字符宽度
uint16_t Font_Heig, //字符高度
uint8_t *c, //字模数据
uint16_t DrawModel) //是否反色显示
{
uint32_t index = 0, counter = 0, xpos =0;
uint32_t Xaddress = 0;
xpos = Xpos*LCD_PIXEL_WIDTH*2;
Xaddress += Ypos;
uint16_t CurrentBackColor = 0;
uint16_t CurrentTextColor = 0;
uint32_t CurrentFrameBuffer = LCD_SetCursor(0,0);
LCD_GetColors(&CurrentTextColor,&CurrentBackColor);
for(index = 0; index < Font_Heig; index++)
{
for(counter = 0; counter < Font_width; counter++)
{
if(*c++ == DrawModel) //根据字模及反色设置决定显示哪种颜色
{
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentBackColor;
}
else
{
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentTextColor;
}
Xaddress++;
}
Xaddress += (LCD_PIXEL_WIDTH - Font_width);
}
}
/**
* @brief 利用缩放后的字模显示字符串
* @param Xpos :字符显示位置x
* @param Ypos :字符显示位置y
* @param Font_width :字符宽度,英文字符在此基础上/2。注意为偶数
* @param Font_Heig:字符高度,注意为偶数
* @param c :要显示的字符串
* @param DrawModel :是否反色显示
* @retval 无
*/
void LCD_DisplayStringLineEx(uint16_t x, //字符显示位置x
uint16_t y, //字符显示位置y
uint16_t Font_width, //要显示的字体宽度,英文字符在此基础上/2。注意为偶数
uint16_t Font_Heig, //要显示的字体高度,注意为偶数
uint8_t *ptr, //显示的字符内容
uint16_t DrawModel) //是否反色显示
{
uint16_t refcolumn = x; //x坐标
uint16_t Charwidth;
uint8_t *psr;
uint8_t Ascii; //英文
uint16_t usCh; //中文
uint8_t ucBuffer [ macWIDTH_CH_CHAR*macHEIGHT_CH_CHAR/8 ];
while ((refcolumn < LCD_PIXEL_WIDTH) && ((*ptr != 0) & (((refcolumn + LCD_GetFont()->Width) & 0xFFFF) >= LCD_GetFont()->Width)))
{
if(*ptr > 0x80) //如果是中文
{
Charwidth = Font_width;
usCh = * ( uint16_t * ) ptr;
usCh = ( usCh << 8 ) + ( usCh >> 8 );
GetGB2312Code_from_Flash( ucBuffer, usCh ); //取字模数据
//缩放字模数据
LCD_zoomChar(24,24,Charwidth,Font_Heig,(uint8_t *)&ucBuffer,psr,1);
//显示单个字符
LCD_DrawChar_Ex(y,refcolumn,Charwidth,Font_Heig,(uint8_t*)&zoomBuff,DrawModel);
refcolumn+=Charwidth;
ptr+=2;
}
else
{
Charwidth = Font_width / 2;
Ascii = *ptr - 32;
//缩放字模数据
LCD_zoomChar(16,24,Charwidth,Font_Heig,(uint8_t *)&LCD_GetFont()->table[Ascii * LCD_GetFont()->Height],psr,0);
//显示单个字符
LCD_DrawChar_Ex(y,refcolumn,Charwidth,Font_Heig,(uint8_t*)&zoomBuff,DrawModel);
refcolumn+=Charwidth;
ptr++;
}
}
}
#if 0
/**
* @brief 显示一行字符,若超出液晶宽度,不自动换行。
中英混显时,请把英文字体设置为Font16x24格式
* @param Line: 要显示的行编号LINE(0) - LINE(N)
* @param *ptr: 要显示的字符串指针
* @retval None
*/
void LCD_DisplayStringLine_EN_CH(uint16_t Line, uint8_t *ptr)
{
uint16_t refcolumn = 0;
/* Send the string character by character on lCD */
while ((refcolumn < LCD_PIXEL_WIDTH) && ((*ptr != 0) & (((refcolumn + LCD_Currentfonts->Width) & 0xFFFF) >= LCD_Currentfonts->Width)))
{
/* Display one character on LCD */
if ( * ptr <= 126 ) //英文字符
{
LCD_DisplayChar(Line, refcolumn, *ptr);
/* Decrement the column position by width */
refcolumn += LCD_Currentfonts->Width;
/* Point on the next character */
ptr++;
}
else //汉字字符
{
uint16_t usCh;
/*一个汉字两字节*/
usCh = * ( uint16_t * ) ptr;
usCh = ( usCh << 8 ) + ( usCh >> 8 );
LCD_DispChar_CH ( Line, refcolumn, usCh );
refcolumn += macWIDTH_CH_CHAR;
ptr += 2;
}
}
}
#endif
lcd_show_zn_font.h代码
#ifndef __LCD_SHOW_ZN_FONT_H_
#define __LCD_SHOW_ZN_FONT_H_
#include "stm32F4xx.h"
#define FONT_FILESIZE 588818 //该数值必须与字体文件的大小完全一致
extern const uint8_t GB2312_H2424[FONT_FILESIZE];
#define macFontName GB2312_H2424
#define macWIDTH_CH_CHAR 24 //中文字符宽度
#define macHEIGHT_CH_CHAR 24 //中文字符高度
//显示字符串
void LCD_DispString_EN_CH(uint16_t Column, uint16_t Line, const uint8_t * pStr );
//显示字符串,并可以设置字体的大小
void LCD_DisplayStringLineEx(uint16_t x, //字符显示位置x
uint16_t y, //字符显示位置y
uint16_t Font_width, //要显示的字体宽度,英文字符在此基础上/2。注意为偶数
uint16_t Font_Heig, //要显示的字体高度,注意为偶数
uint8_t *ptr, //显示的字符内容
uint16_t DrawModel); //是否反色显示
#endif
显示文字:
1.直接调用LCD_DispString_EN_CH()函数即可显示中文字体
2.调用LCD_DisplayStringLineEx()函数还可以设置显示字体的大小(基于字体缩放实现的)。
注意:因为字体文件有500KB左右,这就导致HEX文件也会变大,所以每次下载程序的时候耗时会变长