引子:
原先知道IAR可以建立一个数组,而数组的值直接就可以写中文字。但是却不知道IAR里的中文字编码格式是什么。近几天又不停的遇到客户有想用TFT显示汉字的应用。因此还是了解一下IAR支持的汉字格式,以及汉字编码格式会比较好一些。
实验:
在IAR中定义一个unsigned char ucData[] = {"母"};然后进入Debug状态,会发现其实ucData[] = {0xC4, 0xB8, 0x00}; 这样就知道了IAR的将汉字 "母" 变成两个字节的数据。我们知道汉字使用两个字节的数据来表示的,但是还不确定是什么编码格式。
于是下载了一个汉字编码查询器(彩虹汉字编码查询器),如下图所示,因此知道了IAR内部对汉字的编码是GBK编码。
(以下部分引用http://ir.hit.edu.cn/~taozi/bianma.htm)
汉字编码格式:
到此,有必要了解一下GBK是何东东,汉字编码大约有几种格式。
汉字编码中现在主要用到的有三类,包括GBK,GB2312和Big5。
1、GB2312又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆。新加坡等地也使用此编码。它是一个简化字的编码规范,当然也包括其他的符号、字母、日文假名等,共7445个图形字符,其中汉字占6763个。我们平时说6768个汉字,实际上里边有5个编码为空白,所以总共有6763个汉字。
GB2312规定“对任意一个图形字符都采用两个字节表示,每个字节均采用七位编码表示”,习惯上称第一个字节为“高字节”,第二个字节为“低字节”。GB2312中汉字的编码范围为,第一字节0xA1-0xF7(对应十进制为161-247),第二个字节0xA1-0xFE(对应十进制为161-254)。
GB2312将代码表分为94个区,对应第一字节(0xa1-0xfe);每个区94个位(0xa1-0xfe),对应第二字节,两个字节的值分别为区号值和位号值加32(2OH),因此也称为区位码。01-09区为符号、数字区,16-87区为汉字区(0xb0-0xf7),10-15区、88-94区是有待进一步标准化的空白区。
2、Big5又称大五码,主要为香港与台湾使用,即是一个繁体字编码。每个汉字由两个字节构成,第一个字节的范围从0X81-0XFE(即129-255),共126种。第二个字节的范围不连续,分别为0X40-0X7E(即64-126),0XA1-0XFE(即161-254),共157种。
3、GBK是GB2312的扩展,是向上兼容的,因此GB2312中的汉字的编码与GBK中汉字的相同。另外,GBK中还包含繁体字的编码,它与Big5编码之间的关系我还没有弄明白,好像是不一致的。GBK中每个汉字仍然包含两个字节,第一个字节的范围是0x81-0xFE(即129-254),第二个字节的范围是0x40-0xFE(即64-254)。GBK中有码位23940个,包含汉字21003个。
在大约了解了汉字的编码格式之后,我们已经可以用IAR直接解析到汉字的编码了。但是要在TFT上显示汉字,用的是点阵,而不是编码。因此我们还需要弄到一套对应编码格式的点阵字库,以及编码和点阵折算的公式。
由于GBK是GB2312的扩展,因此GBK的字库会比GB2312大的多。以16*16为例,每个字需要32个字节来表示。简单的折算,6763汉字*32字节 = 216416字节。大约200多K的代码空间。而GBK则需要766080,大约800K。因此,如果想将字库做到片内的话,则GB2312比较有利。毕竟6000个汉字已经包含的大多数的应用了。而使用GBK的场合,一般会使用外部串行Flash或则直接使用字库芯片了。
汉字编码和字库之间的折算公式:
对于GB2312编码,设输入的汉字为GBword,我们可以采用公式(C1-161)*94 + (C2-161)确定GBindex。其中,C1表示第一字节,C2表示第二字节。具体如下:
GBindex = ((unsigned char)GBword.at(0)-161)*94 + (unsigned char)GBword.at(1) - 161;
对于GBK编码,设输入的汉字为GBKword,则可以采用公式 index=(ch1-0x81)*190+(ch2-0x40)-(ch2/128),其中ch1是第一字节,ch2是第二字节。具体的如下:
GBKindex = ((unsigned char)GBKword[0]-129)*190 + ((unsigned char)GBKword[1]-64) - (unsigned char)GBKword[1]/128;
汉字编码字库
知道了汉字的编码与字库的折算公式之后,开始着手用google大神来搜索。但是搜索一番之后,却并没有找到适用于单片机或则是嵌入式的字库档。在灰心丧气间,寻得一利器。点阵字库生成器,易木雨软件工作室的软件。
大家应该知道这16*16的点阵,折算成32字节的数据,有多种折算方式,例如高低位。而该软件则可以通过配置这些方式之后,生成GBK,GB2312,BIG5等点阵字库。绝对是一利器。
以下举个例子来说明生成字库的流程:
点击创建之后,可能需要稍等几分钟。另外,如果是未注册版本,点阵里面会有一条对角线。另外,在设置取模方式的时候,是需要根据具体的LCD或则TFT的规格来的。这样就避免了高低位切换以及高字节低字节切换等繁琐的流程。
在生成字库之后,使用使用该工具附带的另外一个软件来测试(thzk.exe)。但是测试发现thzk.exe仅支持默认的横向取模方式一。还是以汉字"母"为例,利用上面的公式,0xc4,0xb8,折算之后的偏移量为12849. 带入该软件之后,确实为"母"字。
最后我们来确认一下,生成的字符库是否符合我们的要求。
还是以"母"字为例,还记得我们的点阵取模方式为横向取模方式一(具体请参考上图).
母字具体的如下图:
我们上面折算的12849是GBK编码表格中的偏移量,而又因为每个字的点阵需要32字节来表示,因此在字库中的偏移量就是:
Offset = GBKindex * 32, 以"母"字为例, GBKinxex = 12849, 因此在字库中的偏移量就是 Offset = 12849 * 32 = 411168 = 0x64620.
用Ultraedit打开生成的字库文件*.dzk文件。来看看我们的点阵数据是否和上图一致。
通过比对,确实符合在取模方式为横向取模方式一下,生成的点阵字库。
到此为止,已经成功的生成了程序所需要的GBK编码的点阵字库。后续的工作就是将点阵的数据变成一个数组,放到工程里面,然后再显示到LCD点阵或则TFT上了。
利用Ultraedit的16进制编辑,将这些数据拷贝出来,然后用列方式操作,删掉多余的东西,加入逗号等东东,很快就能变成一个能够使用的数组了.
最后,GB2312就不在多说了。应该也是一样的道理。
后续看能否在LG/GG的DK上实现汉字显示。
注:
原先GB2312的公式有误,先已改正。