如何在LCD上写字
- 说明: 在LCD上显示ASCII码时,会先将ASCII码对应的图像数组录入到内部FLASH,再直接读取写入就好。但是由于字库过大,甚至比芯片内部FLASH的存储内存还大,所以需要将字库录入外部FLASH,由于字库中每个汉字的顺序也是固定的,所以可以定位到对应的FLASH存储区来读取汉字图像信息。
- 思路:我采用的是最简单粗暴的方式,通过串口发送字库的二进制文件到单片机中,单片机接收到信息再转存到FLASH中。
1.字库录入
(1)芯片清除 一般外部FLASH的封装库都会带有这个API函数(或类似名称),因为写入FLASH非0xFF的内存会失败,所以要先擦除数据,再进行不检查(即默认内存都是0xFF)写入。
W25QXX_Erase_Chip();
(2)写入字库存在标志位 FONTINFOADDR:自定义的汉字存储区域的起始地址,一个地址对应了FLASH中一个字节。 0xAA:自定义的字库存在标志,这个需要跟使用的字库检测代码相匹配。
#define FONTINFOADDR 1024*1024*25
data = 0xAA;
W25QXX_Write(&rev_buff,FONTINFOADDR,1);
(3)开启串口接收中断
__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);
(4)定义接收中断处理函数
void User_USART_IRQHandler(UART_HandleTypeDef* huart)
{
uint8_t Res;
if((__HAL_UART_GET_FLAG(huart,UART_FLAG_RXNE)!=RESET))
{
HAL_UART_Receive(huart,&Res,1,100);
W25QXX_Write_NoCheck(&Res,addr,1);
addr ++;
}
}
上面的addr在录入不同规格的字库时为不同的值。
#define GBK12_SIZE 574560
#define GBK16_SIZE 766080
#define GBK24_SIZE 1723680
#define GBK32_SIZE 3064320
addr = FONTINFOADDR + 1;
addr = FONTINFOADDR + 1 + GBK12_SIZE;
addr = FONTINFOADDR + 1 + GBK12_SIZE + GBK16_SIZE;
addr = FONTINFOADDR + 1 + GBK12_SIZE + GBK16_SIZE + GBK24_SIZE;
(5)生成字库 我用的是点阵字库生成器V3.8,正点原子的资料里有,我也会把软件和字库文件都上传到CSDN上。生成字库要注意几个点
- 字体选择中文(PRC GBK)
- 宽和高用来确定点阵大小,比如GBK12对应宽高都是12,以此类推。
- 修改字体大小,保证预览图正常显示。
- 修改模式,这个决定了生成字库的编码格式,这个要和显示汉字的解码函数相匹配,我采用的是模式二。
(6)字库写入
- 单片机运行。
- 串口打开对应规格字库的.DZK文件, 勾选16进制发送,然后发送文件。
- 修改addr值,重复1和2。
2.字库解码
- 里面的W25QXX_Read函数要替换成自己外部FLASH的写入函数。
void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size)
{
unsigned char qh,ql;
unsigned char i;
unsigned long foffset;
u8 csize=(size/8+((size%8)?1:0))*(size);
qh=*code;
ql=*(++code);
if(qh<0x81||ql<0x40||ql==0xff||qh==0xff)
{
for(i=0;i<csize;i++)*mat++=0x00;
return;
}
if(ql<0x7f)ql-=0x40;
else ql-=0x41;
qh-=0x81;
foffset=((unsigned long)190*qh+ql)*csize;
switch(size)
{
case 12:
W25QXX_Read(mat,foffset+ftinfo.f12addr,csize);
break;
case 16:
W25QXX_Read(mat,foffset+ftinfo.f16addr,csize);
break;
case 24:
W25QXX_Read(mat,foffset+ftinfo.f24addr,csize);
break;
case 32:
W25QXX_Read(mat,foffset+ftinfo.f32addr,csize);
break;
}
}
void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode)
{
u8 temp,t,t1;
u16 y0=y;
u8 dzk[128];
u8 csize=(size/8+((size%8)?1:0))*(size);
if(size!=12&&size!=16&&size!=24&&size!=32)return;
Get_HzMat(font,dzk,size);
for(t=0;t<csize;t++)
{
temp=dzk[t];
for(t1=0;t1<8;t1++)
{
if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}
}
}
效果图:
|