您现在的位置: 主页 > MCU > 单片机应用 > 24. 汉字显示实验 -
本文所属标签:
为本文创立个标签吧:

24. 汉字显示实验 -

来源: 网络用户发布,如有版权联系网管删除 2018-09-08 

[导读]一。汉字显示原理1. 常用汉字编码这里我们采用GBK编码2. 汉字显示原理假如显示一个16*8的汉字,高16,宽8,则高需要2个字节,显示这个汉字需要2*8=16个字节,这16个字节的数据就是汉字的点阵数据。3. 字符/汉字显示方

一。汉字显示原理

本文引用地址: http://www.21ic.com/app/mcu/201807/778914.htm

1. 常用汉字编码


这里我们采用GBK编码

2. 汉字显示原理


假如显示一个16*8的汉字,高16,宽8,则高需要2个字节,显示这个汉字需要2*8=16个字节,这16个字节的数据就是汉字的点阵数据。

3. 字符/汉字显示方法


利用软件取模

取模方向设置:

扫描方向:纵向为先显示第一个字节,然后显示第二个字节,从低位到高位,然后换到第二列。

数据前缀改为“0x”,数据后缀改为“,”,行后缀为“;”。

对于汉字显示采用16*16。

例如:开,为16*16,得到下面的字模数据。


得到字模数据后,程序中就可以从中取得相应的字节进行显示。

4. 汉字显示的过程

如何显示字库中所有的汉字?利用专用的软件实现。


根据内码,查找相应的字库点阵,然后解析,显示。

对于汉字的内码常用GBK码。每一个汉字都对应一个GBK的编码。

认识GBK码:


GBK码共有126个区,每个区里有190个汉字。

如何根据GBK编码找到汉字:

1.首先找到GBK编码的高位,得到这个汉字在哪个区。(高位-0x81)确定在哪个区。

(GBKH-0x81)*190表示这个汉字所在区的前面几个区已经有这么多个汉字。

当GBKL<0x7F时:汉字所在区的偏移为GBKL-0x40。

当GBKL>0x7F时:汉字所在区的偏移为GBKL-0x41,因为前面空掉一个0x7F。

因为每个汉字占用的字节数为size*2,比如16*16的汉字,那么每个汉字占用的空间是16*2=32个字节。

当 GBKL<0X7F 时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2);

当 GBKL>0X80 时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2);

根据GBK编码得到这个汉字所在汉字库的起始地址。

从以上的方法找到了汉字所在的位置,下面开始制作点阵字库。

采用字库制作软件制作汉字库。



制作点阵字库

生成字库软件设置:

注意字体大小选12,这个是电脑端字体的大小。


注意电脑端的字体大小与生成点阵的字体大小有区别

模式选择纵向取模方式二。

生成点阵字库后,要用文件系统读取字库,然后存到SPI-Flash中。


在SPI FLASH中的某个地方写个标志0xAA,表示已经更新过字库。


Show_Str函数既能显示字符,也能显示汉字,如果是显示汉字就调用Show_Font函数。

Get_HzMat函数根据编码取得字库中汉字的字模。然后根据字模数据解析,显示。

二。实验讲解

生成的字库文件名为:16.DZK,字库大小为766,080字节,然后把名字改成:GBK16.FON。

然后把这个文件存进SD卡,程序会从SD卡中把这个文件写入SPI FLASH。

fontupd.c 更新字库

text.c 显示汉字

1. 程序主函数中开始的时候会检查字库,调用fontinit()函数。

//初始化字体

//返回值:0,字库完好.

//其他,字库丢失

u8 font_init(void)

{

SPI_Flash_Init(); //初始化25Q**系列。

FONTINFOADDR=(1024*6+500)*1024; //W25Q64,6M以后

ftinfo.ugbkaddr=FONTINFOADDR+25; //UNICODEGBK 表存放首地址固定地址

SPI_Flash_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//读出ftinfo结构体数据

if(ftinfo.fontok!=0XAA)return 1; //字库错误.

return 0;

}

字体信息保存地址,占25个字节,第1个字节用于标记字库是否存在.后续每8个字节一组,分别保存起始地址和文件大小。

//字库信息结构体定义

//用来保存字库基本信息,地址,大小等

__packed typedef struct

{

u8 fontok; //字库存在标志,0XAA,字库正常;其他,字库不存在

u32 ugbkaddr; //unigbk的地址

u32 ugbksize; //unigbk的大小

u32 f12addr; //gbk12地址

u32 gbk12size; //gbk12的大小

u32 f16addr; //gbk16地址

u32 gkb16size; //gbk16的大小

}_font_info;

__packed是字节对齐的意思。

比如说int float double char它的总大小是4 + 4 + 8 + 1 = 17
但如果不用__packed的话,系统将以默认的方式对齐(假设是4字节),那么它占4 + 4 + 8 + 4 = 20;(不足4字节以4字节补齐)。

ftinfo 是我们在 fontupd.h 里面定义的一个结构体,用于记录字库首地址及字库大小等信息。

因为我们将W25Q64 的前 6M 字节给 FATFS 管理(用做本地磁盘),然后又预留了 500K 字节给用户自己使用,最后的 1.5M 字节(W25Q64 总共 8M 字节),才是 UNIGBK 码表和字库的存储空间。

finfo结构体的存放地址为:

FONTINFOADDR=(1024*6+500)*1024;

GBK字库存放的首地址为:

ftinfo.ugbkaddr=FONTINFOADDR+25;

2. 主函数如果没有检测到字库

a. 初始化SD卡

while(SD_Initialize()) //检测SD卡

没检测到SD卡报错

LCD_ShowString(60,70,200,16,16,"SD Card Failed!");

b. 调用 update_font(20,110,16,0); 从SD卡更新字库

自己做的字库要放在SD卡SYSTEM/FONT目录下

文件名为GBK16.FON或GBK24.FON

//更新字体文件,UNIGBK,GBK12,GBK16一起更新

//x,y:提示信息的显示地址

//size:字体大小

//提示信息字体大小

//src: 0, 从SD卡更新.

//src:1, 从25QXX更新

//返回值:0,更新成功;

//其他,错误代码.

u8 update_font(u16 x,u16 y,u8 size,u8 src)

{

u8 *gbk16_path;

u8 *gbk12_path;

u8 *unigbk_path;

u8 res;

if(src)//从25qxx更新

{

unigbk_path=(u8*)UNIGBK_25QPATH;

gbk12_path=(u8*)GBK12_25QPATH;

gbk16_path=(u8*)GBK16_25QPATH;

}else//从sd卡更新

{

unigbk_path=(u8*)UNIGBK_SDPATH;

gbk12_path=(u8*)GBK12_SDPATH;

gbk16_path=(u8*)GBK16_SDPATH;

}

res=0XFF;

ftinfo.fontok=0XFF;

SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //清除之前字库成功的标志.防止更新到一半重启,导致的字库部分数据丢失.

SPI_Flash_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //重新读出ftinfo结构体数据

LCD_ShowString(x,y,240,320,size,"Updating UNIGBK.BIN");

res=updata_fontx(x+20*size/2,y,size,unigbk_path,0); //更新UNIGBK.BIN

if(res)return 1;

LCD_ShowString(x,y,240,320,size,"Updating GBK12.BIN ");

res=updata_fontx(x+20*size/2,y,size,gbk12_path,1); //更新GBK12.FON

if(res)return 2;

LCD_ShowString(x,y,240,320,size,"Updating GBK16.BIN ");

res=updata_fontx(x+20*size/2,y,size,gbk16_path,2); //更新GBK16.FON

if(res)return 3;

//全部更新好了,写入标志位0xAA。

ftinfo.fontok=0XAA;

SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字库信息

return 0;//无错误.

}

调用updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx);

//更新某一个

//x,y:坐标

//size:字体大小

//fxpath:路径

//fx:更新的内容 0,ungbk;1,gbk12;2,gbk16;

//返回值:0,成功;其他,失败.

u8 updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx)

{

u32 flashaddr=0;

FIL * fftemp;

u8 *tempbuf;

u8 res;

u16 bread;

u32 offx=0;

u8 rval=0;

fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //为文件系统分配内存

if (fftemp==NULL) rval=1; //分配失败,rval = 1;

tempbuf=mymalloc(SRAMIN,4096); //为数据缓存区分配4096个字节空间

if (tempbuf==NULL) rval=1; //分配失败,rval = 1;

res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ); //根据文件路径打开文件

if (res) rval=2; //打开文件失败

if (rval==0)

{

if(fx==0) //更新UNIGBK.BIN

{

ftinfo.ugbkaddr = FONTINFOADDR+sizeof(ftinfo);//信息头之后,紧跟UNIGBK转换码表

ftinfo.ugbksize = fftemp->fsize; //UNIGBK大小

flashaddr = ftinfo.ugbkaddr; //UNIGBK字库的地址

}else if (fx==1) //更新GBK12

{

ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize; //UNIGBK之后,紧跟GBK12字库

ftinfo.gbk12size=fftemp->fsize; //GBK12字库大小

flashaddr=ftinfo.f12addr; //GBK12的起始地址

}else //更新GBK16

{

ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size; //GBK12之后,紧跟GBK16字库

ftinfo.gkb16size=fftemp->fsize; //GBK16字库大小

flashaddr=ftinfo.f16addr; //GBK16的起始地址

}

while (res==FR_OK) //死循环执行

{

res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取数据

if(res!=FR_OK)break; //执行错误

SPI_Flash_Write(tempbuf,offx+flashaddr,4096);//从0开始写入4096个数据

offx+=bread;

fupd_prog(x,y,size,fftemp->fsize,offx); //进度显示

if (bread!=4096) break; //,如果读出来的数据不是4092个,说明数据读完了,跳出死循环.

}

f_close(fftemp); //关闭文件

}

myfree(SRAMIN,fftemp); //释放内存

myfree(SRAMIN,tempbuf); //释放内存

return res;

}

f_open函数用法:

The f_open function creates afile objectto be used to access the file.

FRESULTf_open(
FIL*fp,
constTCHAR*path,
BYTEmode
);
f_read函数的用法:
Thef_readfunctionreadsdatafromafile.
FRESULTf_read(
FIL*fp,
void*buff,
UINTbtr,
UINT*br
);
text.c中的函数:
1.根据GBK码找到字模函数Get_HzMat(unsignedchar*code,unsignedchar*mat,u8size)

//code字符指针开始
//从字库中查找出字模
//code字符串的开始地址,GBK码
//mat字模数据存放地址size*2bytes大小
voidGet_HzMat(unsignedchar*code,unsignedchar*mat,u8size)//汉字取模
{
unsignedcharqh,ql;
unsignedchari;
unsignedlongf



              查看评论 回复



嵌入式交流网主页 > MCU > 单片机应用 > 24. 汉字显示实验 -
 

"24. 汉字显示实验 -"的相关文章

网站地图

围观()