首页 > 编程资源分享区 > C/C++源代码共享 > C语言嵌入式系统编程修炼之屏幕操作(一)
2006
12-01

C语言嵌入式系统编程修炼之屏幕操作(一)

汉字处理

  现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能。例如,一个微波炉的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具有了更加强大的威力,它使得某些数据和函数脱离”对象”而成为”类”的一部分,正是它的这一特点,成就了软件的无数优秀设计。


留下一个回复