汉字的动态编码与显示方案
javascript:window.open(this.src);" style="cursor:pointer;"/>
3 汉字动态编码的具体实现
实现汉字动态编码的关键是建立编码字典和改写机内码。下面以是显示1行汉字"天上有个太阳,水中有个月亮"为例,说明动态编码的实现过程。
(1)汉字识别
汉字在PC机内的存储和处理是用机内码来实现的。每个汉字的机内码是唯一的,由2个字节组成,分区码和位码,为了和西文的ASCII码有区别,汉字机内码的区码和位码的取值都大于0A0H。我们要处理的源程序文件都是文本文件,存储的都是西文字符、控制符的ASCII码和中文字符的机内码,当扫描到文件中大于0A0H的字节内容时,即可判断该字节是汉字机内码的1个字节,而且肯定是成对出现,第1个字节是区别,第2个字节是位码,都大于0A0H,否则出错。
在C和汇编程序中表示字符的方式有所不同,但最终字符在文件中的存储格式是一样的。显示上面那行汉字,用C语言可以表示为:
char OneSent[]="天上有个太阳,水中有个月亮";
printfhz(OneSent);/*printfhz()显示函数*/
用十六进制编辑器(我们用的是UEdit32)察看文件中C语言字符串定义语句为:
63 68 61 72 20 20 4F 6E 65 53 65 6E 74 5B 5D 20 3D 20 22 CC EC C9 CF D3 D0 B8 F6 CC AB D1 F4 A3 AC CB AE D6 D0 D3 D0 B8 F6 D4 C2 C1 C1 22 20 3B 0D 0A
用汇编语言可以表示为:
ONESENT:DB '天上有个太阳,水中有个月亮',00H
MOV DPTR,ONESENT
LCALL DISPLAY;DISPLAY是显示子程序
用十六进制编辑器察看上面用汇编语言定义字符串的那一条语句为:
4F 4E 45 53 45 4E 54 3A 44 42 20 27 CC EC C9 CF D3 D0 B8 F6 CC AB D1 F4 A3 AC CB AE D6 D0 D3 D0 B8 F6 D4 C2 C1 C1 27 2C 30 30 48 0D 0A
由此可以观察到情况确如前所述。
(2)建立编码字典
编码字典是在扫描的同时逐步建立起来的,每扫描到一个汉字(包括全角符号),即与字典中已有的字符进行比较,如没有重复,是新的字符就顺序存入字典,否则继续扫描,直至文件结属。由于每个字符都是从尾部添加的,它们的序号也是依次递增的,根据序号就可以进行动态编码了。由于显示的汉字一般都得在256个以上,即使进行动态编码,也需要用2字节编码来实现。以MCS51系列单片机和16×16点阵汉字做一优化编码示例:8051的地址指针DPTR是16位指针,由高、低2字节指针DPH、DPL组合而成,如果将存储器按0FFH(256)字节分布,修改DPH即可直接寻址到任一页,修改DPL可寻址该页的任一字节。一个16×16点阵汉字的字模是32字节大小,每页存储器正好能容纳8个汉字字模。可以优化设计动态编码的高字节指向字模的页地址(DPH),低字节指向字模在该页的首地址(DPL)。考虑地址空间的有效分配,将字库的地址放在0A000H以后(程序或数据存储器均可),动态编码的高字节要加上地址有效分配,将字库的地址放在0A000H以后(程序或数据存储器均可),动态编码的高字节要加上地址的页偏移量(大于等于0A0H);考虑汉字与西文字符的区别,动态编码的低字节也需要加上一个大于或等于0A0H的偏移量。设某汉字在编码字典中的序号为Num,则该汉字的动态编码为:
动态编码高字节=页偏移量+Num/8
动态编码低字节=偏移量+(Num%8)×32 (1)
偏移量一般可设为0A0H。当单片机显示某个汉字时,只需将其动态编码的高字节送DPH,低字节减0A0H后送DPL,即可得到对应字模的地址指针。
(3)提取字模、建立动态字库
汉字机内码与点阵字库的详细关系可参考有关资料,它们存在如下联系:
字模首地址=((机内码高字节-1)×94+(机内码低字节-1))×N (2)
注:N为一个汉字点阵字模的字节数。
按照编码字典内容,根据字模首地址,依次取出汉字字模,顺序写入一个二进制文件,即建成动态字库(其它方法略),用烧录器写入EPROM,就可以使用了。
(4)编码改写
机内码是PC机识别处理汉字用的,单片机只能处理我们建立起来的动态编码,还得把程序中汉字的仅机码根据编码字典改成对应的动态编码才行。由于在编写源程序的文本编辑器中看到的是经过系统处理过的字节,看不到汉字的机内码,也无法对其进行改写。根据"汉字识别"一节所述,不经过文本编辑器,直接将动态编码(十六进制数)定改磁盘文件对应位置即可,但是处理过后的汉字在文本编辑器里会显示出乱码。
(5)汉字显示
在明白了动态编码与动态字库中字模的关系后,可以完成按照PC机下汉字显示原理进行单片机下的程序设计,编写前面的函数printhz()或子程序的DISPLAY,可参考相关资料[4]。
javascript:window.open(this.src);" style="cursor:pointer;"/>
4 MCS51汉字显示例程
根据上述汉字动态编码方法,我们利用Borland C++编写了PC机预处理程序,将ASM51或C51源程序用PC机预处理后,建立了动态字库和改写了机内码,并且用ASM51写了一个针对MCS51进行优化的子程序DIS_CHAR。它显示一个西文或中文字符,实现过程如图2所示。
西文字符码的显示与流字显示基本相同,将西文字库(仅数字和字符部分)装入程序存储器中,根据ASCII码的值计算出字模首地址,将字符字模依次读出,再送显示即可。
此方案不但可用