单片机驱动TFT LCD屏显示汉字的方法详解
前言
使用单片机对spi串口屏进行文本显示应该怎么做呢?虽然lcd厂商会提供单片机的驱动但是很多简单的示例是不满足项目需求的!我会详细的介绍给大家字库是如何导入到keil工程的!
一、常规汉族格式
一般对于较小尺寸的屏幕比如2.4 2.6 3.2寸屏幕,根据需要一般有16、24、32号字体,而lcd厂商一般会提供这类的底层示例,比如下方的:
Display a single 16×16 Chinese character
void GUI_DrawFont16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
{ LCD_SetWindows(x,y,x+16-1,y+16-1);
for(i=0;i<16*2;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont16[k].Msk[i]&(0x80>>j)) Lcd_WriteData_16Bit(fc);
else Lcd_WriteData_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont16[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==16)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏
}
Display a single 24×24 Chinese character
void GUI_DrawFont24(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
{ LCD_SetWindows(x,y,x+24-1,y+24-1);
for(i=0;i<24*3;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont24[k].Msk[i]&(0x80>>j)) Lcd_WriteData_16Bit(fc);
else Lcd_WriteData_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont24[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==24)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏
}
Display a single 32×32 Chinese character
void GUI_DrawFont32(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont32)/sizeof(typFNT_GB32); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
{ LCD_SetWindows(x,y,x+32-1,y+32-1);
for(i=0;i<32*4;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont32[k].Msk[i]&(0x80>>j)) Lcd_WriteData_16Bit(fc);
else Lcd_WriteData_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont32[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==32)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏
}
二、如何创造出字体呢?
1.软件怎么用?
一般使用zimo22来生成,我们以16*16为例
打开软件
选择参数设置,其他选项
点击文字输入区字体选择
如果是16*16 就是小四大小即可,点击确定
在文字输入区输入文字,比如:成功
然后ctrl+enter之后如下图:
然后点击取模方式如下图
点击c51格式之后代码就出来了
/*– 文字: 成 –*/
/*– 宋体12; 此字体下对应的点阵为:宽x高=16×16 –*/
0x00,0x50,0x00,0x48,0x00,0x40,0x3F,0xFE,0x20,0x40,0x20,0x40,0x20,0x44,0x3E,0x44,
0x22,0x44,0x22,0x28,0x22,0x28,0x22,0x12,0x2A,0x32,0x44,0x4A,0x40,0x86,0x81,0x02,
/*– 文字: 功 –*/
/*– 宋体12; 此字体下对应的点阵为:宽x高=16×16 –*/
0x00,0x40,0x00,0x40,0x00,0x40,0xFE,0x40,0x11,0xFC,0x10,0x44,0x10,0x44,0x10,0x44,
0x10,0x44,0x10,0x84,0x10,0x84,0x1E,0x84,0xF1,0x04,0x41,0x04,0x02,0x28,0x04,0x10,
3.怎么用呢?这个玩意只是数组而已,我们调用方式其实很简单
1)先做数组
2)学会调用
void Apf_GUI_Show_Str(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode)
{
uint16_t x0=x;
uint8_t bHz=0; //字符或者中文
while(*str!=0)//数据未结束
{
if(!bHz)
{
if(x>(lcddev.width-size/2)||y>(lcddev.height-size))
return;
if(*str>0x80)bHz=1;//中文
else //字符
{
if(*str==0x0D)//换行符号
{
y+=size;
x=x0;
str++;
}
else
{
if(size>16)//字库中没有集成12X24 16X32的英文字体,用8X16代替
{
LCD_ShowChar(x,y,fc,bc,*str,16,mode);
x+=8; //字符,为全字的一半
}
else
{
LCD_ShowChar(x,y,fc,bc,*str,size,mode);
x+=size/2; //字符,为全字的一半
}
}
str++;
}
}else//中文
{
if(x>(lcddev.width-size)||y>(lcddev.height-size))
return;
bHz=0;//有汉字库
if(size==32)
GUI_DrawFont32(x,y,fc,bc,str,mode);
else if(size==24)
GUI_DrawFont24(x,y,fc,bc,str,mode);
else
GUI_DrawFont16(x,y,fc,bc,str,mode);
str+=2;
x+=size;//下一个汉字偏移
}
}
}
参数:x,y,前景色,背景色,汉字,大小,是否覆盖
Apf_GUI_Show_Str(190+16,47,WHITE,BLACK,"图",16,0);
24*24 32*32就是字模生成软件的字体大小不同而已,其他的一样,这个框架可以用在任何tftlcd上来绘制字体
总结
后期会将图片如何显示在tftlcd上做简单的介绍!
作者:C电子喵C