完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
46.1 汉字显示原理简介
常用的汉字内码系统有 GB2312,GB13000,GBK,BIG5(繁体)等几种,其中 GB2312 支持的汉字仅有几千个,很多时候不够用,而 GBK 内码不仅完全兼容 GB2312,还支持了繁体 字,总汉字数有 2 万多个,完全能满足我们一般应用的要求。 本实例我们将制作三个 GBK 字库,制作好的字库放在 SD 卡里面,然后通过 SD 卡,将字 库文件复制到外部 FLASH 芯片 W25Q256 里,这样,W25Q256 就相当于一个汉字字库芯片了。 汉字在液晶上的显示原理与前面显示字符的是一样的。汉字在液晶上的显示其实就是一些 点的显示与不显示,这就相当于我们的笔一样,有笔经过的地方就画出来,没经过的地方就不 画,我们以 12*12 的汉字为例,假设其取模方向为从上到下,从左到右的方向取模,且高位在 前,那么其取模原理如图 46.1.1 所示: 图 46.1.1 从上到下,从左到右取模原理 图中,我们取模的时候,从最左上方的点开始取(从上到下,从左到右),且高位在前(bit7 在表示第一个位),那么第一个字节就是:0X11(1,表示浅蓝色的点,即要画出来的点,0 则表示不要画出来),第二个字节是:0X10,第三个字节(到第二列了,每列 2 个字节)是: 0X1E……,依次类推,一个 12*12 的汉字,总共有 12 列,每列 2 个字节,总共需要 24 个字节 来表示。 在显示的时候,我们只需要读取这个汉字的点阵数据(12*12 字体,一个汉字的点阵数据 为 24 个字节),然后将这些数据,按取模方式,反向解析出来(坐标要处理好),每个字节, 是 1 的位,就画出来,不是 1 的位,就忽略,这样,就可以显示出这个汉字了。 所以要显示汉字,我们首先要知道汉字的点阵数据,这些数据可以由专门的软件来生成。 知道显示了一个汉字,就可以推及整个汉字库了。汉字在各种文件里面的存储不是以点阵数据 的形式存储的(否则那占用的空间就太大了),而是以内码的形式存储的,就是 GB2312/GBK/BIG5 等这几种的一种,每个汉字对应着一个内码,在知道了内码之后再去字库 里面查找这个汉字的点阵数据,然后在液晶上显示出来。这个过程我们是看不到,但是计算机 是要去执行的。 单片机要显示汉字也与此类似:汉字内码(GBK/GB2312)→查找点阵库→解析→显示。 所以只要我们有了整个汉字库的点阵,就可以把电脑上的文本信息在单片机上显示出来了。 这里我们要解决的最大问题就是制作一个与汉字内码对得上号的汉字点阵库。而且要方便单片 机的查找。每个 GBK 码由 2 个字节组成,第一个字节为 0X81~0XFE,第二个字节分为两部分, 一是 0X40~0X7E,二是 0X80~0XFE。其中与 GB2312 相同的区域,字完全相同。 我们把第一个字节代表的意义称为区,那么 GBK 里面总共有 126 个区(0XFE-0X81+1), 每个区内有 190 个汉字(0XFE-0X80+0X7E-0X40+2),总共就有 126*190=23940 个汉字。我 们的点阵库只要按照这个编码规则从 0X8140 开始,逐一建立,每个区的点阵大小为每个汉字 所用的字节数*190。这样,我们就可以得到在这个字库里面定位汉字的方法: 当 GBKL<0X7F 时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2); 当 GBKL>0X80 时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2); 其中 GBKH、GBKL 分别代表 GBK 的第一个字节和第二个字节(也就是高位和低位),size 代表汉字字体的大小(比如 16 字体,12 字体等),Hp 则为对应汉字点阵数据在字库里面的起 始地址(假设是从 0 开始存放)。 这样我们只要得到了汉字的 GBK 码,就可以显示这个汉字了。从而实现汉字在液晶上的 显示。 上一章,我们提到要用 cc936.c,以支持长文件名,但是 cc936.c 文件里面的两个数组太大 了(172KB),直接刷在单片机里面,太占用 flash 了,所以我们必须把这两个数组存放在外部 flash。cc936 里面包含的两个数组 oem2uni 和 uni2oem 存放 unicode 和 gbk 的互相转换对照表, 这两个数组很大,这里我们利用 ALIENTEK 提供的一个 C 语言数组转 BIN(二进制)的软件: C2B 转换助手 V1.1.exe,将这两个数组转为 BIN 文件,我们将这两个数组拷贝出来存放为一个 新的文本文件,假设为 UNIGBK.TXT,然后用 C2B 转换助手打开这个文本文件,如图 46.1.2 所示: 图 46.1.2 C2B 转换助手 然后点击转换,就可以在当前目录下(文本文件所在目录下)得到一个 UNIGBK.bin 的文 件。这样就完成将 C 语言数组转换为.bin 文件,然后只需要将 UNIGBK.bin 保存到外部 FLASH 就实现了该数组的转移。 在 cc936.c 里面,主要是通过 ff_convert 调用这两个数组,实现 UNICODE 和 GBK 的互转, 此段代码,通过二分法(16 阶)在数组里面查找 UNICODE(或 GBK)码对应的 GBK(或 UNICODE)码。当我们将数组存放在外部 flash 的时候, 代码中的 ftinfo.ugbksize 为我们刚刚生成的 UNIGBK.bin 的大小,而 ftinfo.ugbkaddr 是我们 存放 UNIGBK.bin 文件的首地址。这里同样采用的是二分法查找,关于 cc936.c 的修改,我们就 介绍到这。 字库的生成,我们要用到一款软件,由易木雨软件工作室设计的点阵字库生成器 V3.8。该 软件可以在 WINDOWS 系统下生成任意点阵大小的 ASCII,GB2312(简体中文)、GBK(简体中 文)、BIG5(繁体中文)、HANGUL(韩文)、SJIS(日文)、Unicode 以及泰文,越南文、俄文、乌克 兰文,拉丁文,8859 系列等共二十几种编码的字库,不但支持生成二进制文件格式的文件,也 可以生成 BDF 文件,还支持生成图片功能,并支持横向,纵向等多种扫描方式,且扫描方式 可以根据用户的需求进行增加。该软件的界面如图 46.1.3 所示: 图 46.1.3 点阵字库生成器默认界面 要生成 16*16 的 GBK 字库,则选择:936 中文 PRC GBK,字宽和高均选择 16,字体大小 选择 12,然后模式选择纵向取模方式二(从上到下,从左到右,且字节高位在前,低位在后), 最后点击创建,就可以开始生成我们需要的字库了(.DZK 文件,在生成完以后,我们手动修改 后缀为.fon)。具体设置如图 46.1.4 所示: 图 46.1.4 生成 GBK16*16 字库的设置方法 注意:电脑端的字体大小与我们生成点阵大小的关系为: fsize=dsize*6/8 其中,fsize 是电脑端字体大小,dsize 是点阵大小(12、16、24、32 等)。所以 16*16 点阵 大小对应的是 12 字体。 生成完以后,我们把文件名和后缀改成:GBK16.FON(这里是手动修改后缀!!)。同样的 方法,生成 12*12 的点阵库(GBK12.FON)、24*24 的点阵库(GBK24.FON)和 32*32 的点阵 库(GBK32.FON),总共制作 4 个字库。 另外,该软件还可以生成其他很多字库,字体也可选,大家可以根据自己的需要按照上面 的方法生成即可。该软件的详细介绍请看软件自带的《点阵字库生成器说明书》,关于汉字显示 原理,我们就介绍到这。 46.2 硬件设计 本章实验功能简介:开机的时候先检测 W25Q256 中是否已经存在字库,如果存在,则按 次序显示汉字(四种字体都显示)。如果没有,则检测 SD 卡和文件系统,并查找 SYSTEM 文件 夹下的 FONT 文件夹,在该文件夹内查找 UNIGBK.BIN、GBK12.FON、GBK16.FON、 GBK24.FON 和 GBK32.FON(这几个文件的由来,我们前面已经介绍了)。在检测到这些文 件之后,就开始更新字库,更新完毕才开始显示汉字。通过按按键 KEY0,可以强制更新字库。 同样我们也是用 DS0 来指示程序正在运行。 所要用到的硬件资源如下: 1) 指示灯 DS0 2) KEY0 按键 3) 串口 4) LCD 模块 5) SD 卡 6) SPI FLASH 这几部分分,在之前的实例中都介绍过了,我们在此就不介绍了。 46.3 软件设计 打开本章实验目录可以看到,首先在工程根目录文件夹下面新建了一个 TEXT 的文件夹。 在 TEXT 文件夹下新建 fontupd.c、fontupd.h、text.c、text.h 这 4 个文件。同时,我们在实验工 程中新建了 TEXT 分组,将新建的源文件加入到了分组之下,并将头文件包含路径加入到了工 程的 PATH 中。 打开 fontupd.c,代码如下: 此部分代码主要用于字库的更新操作(包含 UNIGBK 的转换码表更新),其中 ftinfo 是我 们在 fontupd.h 里面定义的一个结构体,用于记录字库首地址及字库大小等信息。因为我们将 W25Q256 的前 25M 字节给 FATFS 管理(用做本地磁盘),随后,紧跟字库结构体、UNIGBK.bin、 和三个字库,这部分内容首地址是:(1024*12)*1024,大小约 6.01M,最后 W25Q256 还剩下约 0.99M 给用户自己用。 接下来我们打开 fontupd.h 文件代码如下: 此部分代码总共有 4 个函数,我们省略了两个函数(Show_Str_Mid 和 Show_Str)的代码, 另外两个函数,Get_HzMat 函数用于获取 GBK 码对应的汉字字库,通过我们 47.1 节介绍的办 法,在外部 flash 查找字库,然后返回对应的字库点阵。Show_Font 函数用于在指定地址显示一 个指定大小的汉字,采用的方法和 LCD_ShowChar 所采用的方法一样,都是画点显示,这里就 不细说了。 text.h 头文件是一些函数申明,我们这里不细说了。 前面提到我们对 cc936.c 文件做了修改,我们将其命名为 mycc936.c,并保存在 exfuns 文件 夹下,将工程 FATFS 组下的 cc936.c 删除,然后重新添加 mycc936.c 到 FATFS 组下,mycc936.c 的源码就不贴出来了,其实就是在 cc936.c 的基础上去掉了两个大数组,然后对 ff_convert 进行 了修改,详见本例程源码。 最后,我们看看 main 函数如下: 此部分代码就实现了我们在硬件描述部分所描述的功能,至此整个软件设计就完成了。这 节有太多的代码,而且工程也增加了不少,我们来看看工程的截图吧,整个工程截图如图 46.3.1 所示: 图 46.3.1 工程建成截图 46.4 下载验证 在代码编译成功之后,我们通过下载代码到 ALIENTEK 水星 STM32 开发板上,可以看到 LCD 开始显示汉字及汉字内码,如图 46.4.1 所示: 图 46.4.1 汉字显示实验显示效果 一开始就显示汉字,是因为 ALIENTEK 水星 STM32F767 开发板在出厂的时候都是测试过 的,里面刷了综合测试程序,已经把字库写入到了 W25Q256 里面,所以并不会提示更新字库。 如果你想要更新字库,那么则必须先找一张 SD 卡,把:光盘5,SD 卡根目录文件 文件夹下 面的 SYSTEM 文件夹拷贝到 SD 卡根目录下,插入开发板,并按复位,之后,在显示汉字的时 候,按下 KEY0,就可以开始更新字库了。 字库更新界面如图 46.4.2 所示: 图 46.4.2 汉字字库更新界面 我们还可以通过 USMART 来测试该实验,将 Show_Str 函数加入 USMART 控制(方法前 面已经讲了很多次了),就可以通过串口调用该函数,在屏幕上显示任何你想要显示的汉字了, 有兴趣的朋友可以测试一下。 |
|
|
|
只有小组成员才能发言,加入小组>>
3311 浏览 9 评论
2994 浏览 16 评论
3493 浏览 1 评论
9058 浏览 16 评论
4087 浏览 18 评论
1176浏览 3评论
604浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
598浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2334浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1895浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 23:02 , Processed in 1.175937 second(s), Total 49, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号