汉字处理
现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能。例如,一个微波炉的LCD上没有必要提供显示”电子邮件”的功能;一个提供汉字显示功能的空调的LCD上不需要显示一条”短消息”,诸如此类。但是一部手机、小灵通则通常需要包括较完整的汉字库。
如果包括的汉字库较完整,那么,由内码计算出汉字字模在库中的偏移是十分简单的:汉字库是按照区位的顺序排列的,前一个字节为该汉字的区号,后一个字节为该字的位号。每一个区记录94个汉字,位号则为该字在该区中的位置。因此,汉字在汉字库中的具体位置计算公式为:94*(区号-1)+位号-1。减1是因为数组是以0为开始而区号位号是以1为开始的。只需乘上一个汉字字模占用的字节数即可,即:(94*(区号-1)+位号-1)*一个汉字字模占用字节数,以16*16点阵字库为例,计算公式则为:(94*(区号-1)+(位号-1))*32。汉字库中从该位置起的32字节信息记录了该字的字模信息。
对于包含较完整汉字库的系统而言,我们可以以上述规则计算字模的位置。但是如果仅仅是提供少量汉字呢?譬如几十至几百个?最好的做法是:
定义宏:
# define EX_FONT_CHAR(value) # define EX_FONT_UNICODE_VAL(value) (value), # define EX_FONT_ANSI_VAL(value) (value), |
定义结构体:
typedef struct _wide_unicode_font16x16 { WORD value; /* 内码 */ BYTE data[32]; /* 字模点阵 */ }Unicode; #define CHINESE_CHAR_NUM … /* 汉字数量 */ |
字模的存储用数组:
Unicode chinese[CHINESE_CHAR_NUM] = { { EX_FONT_CHAR(“业”) EX_FONT_UNICODE_VAL(0x4e1a) {0×04, 0×40, 0×04, 0×40, 0×04, 0×40, 0×04, 0×44, 0×44, 0×46, 0×24, 0x4c, 0×24, 0×48, 0×14, 0×50, 0x1c, 0×50, 0×14, 0×60, 0×04, 0×40, 0×04, 0×40, 0×04, 0×44, 0xff, 0xfe, 0×00, 0×00, 0×00, 0×00} }, { EX_FONT_CHAR(“中”) EX_FONT_UNICODE_VAL(0x4e2d) {0×01, 0×00, 0×01, 0×00, 0×21, 0×08, 0x3f, 0xfc, 0×21, 0×08, 0×21, 0×08, 0×21, 0×08, 0×21, 0×08, 0×21, 0×08, 0x3f, 0xf8, 0×21, 0×08, 0×01, 0×00, 0×01, 0×00, 0×01, 0×00, 0×01, 0×00, 0×01, 0×00} }, { EX_FONT_CHAR(“云”) EX_FONT_UNICODE_VAL(0x4e91) {0×00, 0×00, 0×00, 0×30, 0x3f, 0xf8, 0×00, 0×00, 0×00, 0×00, 0×00, 0x0c, 0xff, 0xfe, 0×03, 0×00, 0×07, 0×00, 0×06, 0×40, 0x0c, 0×20, 0×18, 0×10, 0×31, 0xf8, 0x7f, 0x0c, 0×20, 0×08, 0×00, 0×00} }, { EX_FONT_CHAR(“件”) EX_FONT_UNICODE_VAL(0x4ef6) {0×10, 0×40, 0x1a, 0×40, 0×13, 0×40, 0×32, 0×40, 0×23, 0xfc, 0×64, 0×40, 0xa4, 0×40, 0×28, 0×40, 0x2f, 0xfe, 0×20, 0×40, 0×20, 0×40, 0×20, 0×40, 0×20, 0×40, 0×20, 0×40, 0×20, 0×40, 0×20, 0×40} } } |
要显示特定汉字的时候,只需要从数组中查找内码与要求汉字内码相同的即可获得字模。如果前面的汉字在数组中以内码大小顺序排列,那么可以以二分查找法更高效的查找到汉字的字模。
这是一种很有效的组织小汉字库的方法,它可以保证程序有很好的结构。
系统时间显示
从NVRAM中可以读取系统的时间,系统一般借助NVRAM产生的秒中断每秒读取一次当前时间并在LCD上显示。关于时间的显示,有一个效率问题。因为时间有其特殊性,那就是60秒才有一次分钟的变化,60分钟才有一次小时变化,如果我们每次都将读取的时间在屏幕上完全重新刷新一次,则浪费了大量的系统时间。
一个较好的办法是我们在时间显示函数中以静态变量分别存储小时、分钟、秒,只有在其内容发生变化的时候才更新其显示。
extern void DisplayTime(…) { static BYTE byHour,byMinute,bySecond; BYTE byNewHour, byNewMinute, byNewSecond; byNewHour = GetSysHour(); byNewMinute = GetSysMinute(); byNewSecond = GetSysSecond(); if(byNewHour!= byHour) { … /* 显示小时 */ byHour = byNewHour; } if(byNewMinute!= byMinute) { … /* 显示分钟 */ byMinute = byNewMinute; } if(byNewSecond!= bySecond) { … /* 显示秒钟 */ bySecond = byNewSecond; } } |
这个例子也可以顺便作为C语言中static关键字强大威力的证明。当然,在C++语言里,static具有了更加强大的威力,它使得某些数据和函数脱离”对象”而成为”类”的一部分,正是它的这一特点,成就了软件的无数优秀设计。
>> 本文固定链接: http://www.vcgood.com/archives/1337