>
首页 » 业界动态 » 基于uClinux的手持设备GUI应用系统的设计

基于uClinux的手持设备GUI应用系统的设计

作者:皇良斌,朱巧明  时间:2007-04-30 22:18  来源:

摘要:手持设备现已被广泛应用于通讯、仪器、仪表、消费类产品等众多领域。如何快速开发手持设备的图形用户界面成为嵌入式系统开发中的一个热门课题。本文以uClinux操作系统和华恒HHDREZ328开发板为开发环境,介绍了一个手持设备的GUI应用系统的设计方法。文章首先分析了uClinux操作系统中的LCD设备驱动程序和LCD库函数,然后讨论了在LCD上显示汉字的方法。为了方便用户进行开发,文章提出并实现了一个脚本执行引擎,并给出了使用脚本来开发嵌入式系统的GUI应用程序的方法。

关键词:uClinux;图形用户接口;嵌入式系统;脚本执行引擎;手持设备

引言

随着软硬件技术的快速发展,嵌入式系统变得越来越复杂。嵌入式操作系统uClinux是标准Linux的一个分支,并且专为嵌入式系统做了许多小型化的工作。它支持多任务和多种文件系统,且易于移植,现已成功地应用在Freescale龙珠系列、PowerPC、ARM等处理器上。

华恒HHDREZ328开发板使用Freescale龙珠EZ328集成处理器,主要配置包括8MSDRAM、4M FLASH、通用I/O、一路RS232接口等。它与uClinux操作系统紧密结合,充分发挥了硬件的特性与优势,成为低端手持设备、PDA、显示终端等设备开发商的首选开发平台。

手持设备的嵌入式系统已经成为嵌入式系统中的一个重要的应用领域,手持设备的GUI的研究也成为这一领域的一个新的方向。李平等[4]介绍了一种三星S3C44BOX单片机与嵌入式系统uc/OS-II的实时嵌入式系统的解决方案,并提出了通用实用型GUI方案,但该方案仅仅针对三星S3C44BOX单片机的I/O系统。吴峰等[5]提出了一个基于Linux的Frame Buffer的嵌入式GUI系统。韩会敏等[6]提出了一种用于嵌入式手持设备产品的人机交互应用程序的设计框架,并针对嵌入式实时内核NucleusPlus实现了相关交互功能。本文在深入研究Windows GUI应用程序开发的基础上,提出了通过设计并实现一个脚本执行引擎(Script Executing Engine),把嵌入式设备上的GUI开发,转移到PC机上开发,从而有效地提高了嵌入式手持设备上的GUI应用程序的开发效率。

uClinux中LCD设备驱动程序和LCD库函数分析

驱动程序分析
uClinux把硬件设备当成一个个设备文件,LCD被看成是字符设备。为了使应用程序能像操作普通文件一样对硬件设备进行操作,uClinux提供了一个统一的操作函数接口file-operations结构体,这个数据结构中包括许多操作函数的指针,如open()、read()和write()等。在uClinux/linux-2.4.x/drivers/char/目录下新建一个lcd.c文件,就可作为LCD驱动程序的源程序。在文件中添加如下代码:

staticstructfile-operationsxyz-fops={
read:lcd-read,/*读操作*/
write:lcd-write,/*写操作*/
ioctl:lcd-ioctl,/*控制操作*/
open:lcd-open,/*打开操作*/
release:lcd-release,/*关闭操作*/
};

以写操作为例,介绍一下lcd-write()函数:使用一个图像缓冲区存储与屏幕相对应的点阵数据,这个缓冲区的大小为:点阵行数×点阵列数×用于表示一个像素的比特数/8。本文采用的LCD显示方式为160×96,单色,则需要分配的显示缓冲区为160×96×2/8=3840字节。lcd-write函数的声明如下:

ssize-tlcd-write(structfile*fd,constchar*buf,size-tcount,loff-t*ppos)

其中buf指向要显示的点阵数据,count是size-t类型,即32位的整数,用一个联合体类型的变量把这个32位的数分成四个8位的整数,代表left、top、width、height,说明buf指向的点阵数据在缓冲区中的位置和大小。根据这四个参数,把buf指向的点阵数据复制到缓冲区中的相应位置。

定义的lcd-write函数只是把数据写到驱动程序维护的缓冲区中,写完后LCD上还不会显示。我们把从应用层写到缓冲区和驱动再把缓冲区中的数据写到LCD显存这两个步骤分开,这样灵活性比较好,由上层用户决定何时刷新屏幕。

因此在ioctl的命令项中增加一个paint命令:

intlcd-ioctl(structinode*inode,structfile*fd,
unsigned int cmd,unsigned long arg)
{
switch(cmd){
caseLCD-PAINT:
lcd-paint(arg);
return0;
caseOTHER-COMMAND:
do-something();
return0;
}
}

由lcd-paint()这个函数把缓冲区的点阵数据送到LCD的显存中,同上,把32位的arg参数分成四个8位的整数,代表left、top、width、height,这样可以计算出要送的数据在缓冲区中的位置和大小,然后设置LCD控制器的指令寄存器,告诉控制器目的地址,最后把要送的数据串行送到LCD控制器的数据寄存器中即可。这样LCD上就会显示出相应的图像。

LCD库函数分析

LCD库函数主要负责在屏幕上显示文字和维护每个屏幕的点阵数据。我们使用HZK12字模来显示汉字,HZK12文件的格式有些特别,字库设计者为了使用的方便,字模每行的位数均补齐为8的整数倍,于是实际该字库的位长度是16*12,每个字模大小为24字节,每个字的行上都多出了4位,但这4位都是0,不显示,所以两个相邻的字之间会有一点空隙。对于160×96的LCD来说,一屏可显示8行,一行10个字。坐标系统这样规定:把屏幕划分为8行10列,左上角的坐标为(0,0),右下脚的坐标为(7,9)。用户在LCD上显示字符时,应先设置光标的位置。LCD库函数主要提供如下函数供用户调用:

(1)int Create-Screen(char*screen-name):
使用malloc函数,申请4kB空间,空间的指针作为返回值,代表Screen-Id。
(2)voidSet-Current-Screen(intScreen-Id):
把Screen-Id代表的屏幕作为当前屏幕。
(3)voidPuts(char*string):在当前屏幕的当前光标处显示一个字符串。string参数中是汉字的内码,一个汉字的内码是2个字节,通过内码,就可以计算出汉字的区位码:
qh=c1-0xa0wh=c2-0xa0
qh、wh为汉字的区号和位号,c1、c2为汉字的第一字节和第二字节。根据区号和位号可以得到汉字字模在文件中的位置:
location=(94*(qh-1)+(wh-1))*24。

打开hzk12文件,把文件指针移到location所指的地方,读出字模点阵24个字节的数据,根据当前坐标X和Y,把点阵数据复制到当前屏幕点阵空间的相应位置即可。随后当用户调用paint命令时,就可以把汉字显示在LCD上。

开发和调试方法
由于嵌入式系统的调试比较困难,所以使用软件测试理论中的“驱动模块(driver)”和“桩模块(stub)”的方法,在开发库函数时,仿照LCD驱动,在PC上做了模拟模块,这个模块把库函数传过来的点阵数据转换成PC上的驱动能够识别的格式,然后调用PC上的驱动即可。这样LCD库函数就可以在PC上调试运行,等调试正确后再用交叉编译器编译。当确保嵌入式系统中的LCD驱动是正确时,在PC上正确运行的库函数下载到嵌入式平台上时也就能正常运行了。同时这也使库函数做到了平台无关性。

脚本执行引擎的设计和应用

脚本执行引擎的设计思路
有了库函数,就可以在库函数上使用C语言开发应用程序,这样的开发模式类似以前在DOS上开发界面程序,与现在面向对象、面向事件的开发模式有很大区别,给开发人员增加了难度。因此我们部分借鉴VisualBasic6的窗体(.frm)文件结构,使用脚本组织程序,然后仿照VB6的RunTimeDLL,开发出一个执行引擎来解释执行脚本。这个引擎通过调用库函数实现具体功能,因为库函数可以做到与平台无关,所以引擎也可以做到与平台无关,在开发平台和目标平台上都可以运行。

这个引擎由两部分组成,一个是主控模块,主要负责流程的调度。另一部分是“包”,“包”是一个组织单位,例如这个引擎中有Windows、System、Db等包。每个包里有若干个方法,方法是在库函数上再做了一些扩充的函数。Windows包里主要是关于显示方面的方法,System包里主要是关于键盘、系统设置方面操作的方法,Db包里主要是关于数据库方面操作的方法。各个方法要实现具体功能时,可以调用相应的库函数。脚本执行引擎的示意图如图1所示。


图1 脚本执行引擎的示意图


图2 应用程序示例

使用脚本开发应用程序的方法
当用户要开发如图2所示的应用程序时,可以按照以下的步骤:

(1)在PC上,使用文本编辑器编写一个脚本文件,具体内容如下:
Menu1=Windows.Create Menu(4/*itemcount*/,1/*left*/,1/*top*/)
Item1=Windows.Create MenuItem(Menu1, “1.液晶屏背光设置”)
Item2=Windows.Create MenuItem(Menu1,“2.传输速度设置”)
Item3=Windows.Create MenuItem(Menu1,“3.自动关机设置”)
Item4=Windows.Create MenuItem(Menu1,“4.时间设置”)
Event Menu1 Handles System.Menu Event
Select System.get-key()
Case Up Key
Dosomething
Case DownKey
Dosomething
Case EnterKey
Dosomething
End Select
End Event
Windows.CreateMenu(item-count,left,top)主要做以下工作:

①根据item-count参数,开辟一个空间,随后调用的Windows.CreateMenuItem中的各个参数就线性保存在这个空间中。
②保存left、top两个坐标参数的值,随后绘制的各菜单项的left坐标值都相同,top坐标值自动增加。
③把所开辟的空间的地址作为返回值返回。
Windows.CreateMenuItem(Menu1,“1.液晶屏背光设置”)主要做以下工作:

①根据Menu1参数所指向的地址空间中left、top参数的值设置光标,随后把top参数的值增加一个单位。
②调用Puts()库函数把菜单标题的点阵数据写到当前屏幕点阵空间的相应位置。
③把菜单标题参数登记到Menu1参数所指向的地址空间中。

(2)在PC上,使用编译程序把文本脚本编译成二进制文件。若引擎直接处理文本文件,效率很低,所以先用编译程序把文本脚本编译成二进制文件。当然这里的“编译”与平时C语言编程时用的gcc编译器不一样,它输出的并不是可执行的代码,而是一个能被引擎识别的二进制文件。在编译时做了这些工作:词法分析,语法分析,参数个数检查等。这样如果脚本文件中有语法错误等,可以在编译时先检查出来。
(3)在PC上,可以先使用PC上的脚本执行引擎模拟运行这个二进制脚本,看是否达到所需的效果,如果不对,再返回第一步进行修改。

引擎解释执行脚本时是这样工作的:
①程序中用一个二维数组记录各个方法的名称和地址,地址其实即为一个函数指针。初始化时把这个数组按方法的名称排序。
②引擎按顺序读入二进制文件,如果是类似“Windows.Create279 2006年第11期皇良斌等:基于uClinux的手持设备GUI应用系统的设计Menu”这样的方法调用,则根据方法名用二分法去查找二维数组,找到对应的方法地址,然后直接调用即可。如果是“Event”关键字,则把它添加到一个事件的链表中,链表的节点记录以下信息:当前的二进制文件的指针,事件的名称和类型。
③当引擎把二进制文件读完一遍后,随即进入一个无限循环,每隔一段时间去调用键盘库函数,如果有键值,则根据当前的屏幕号和键值,去事件链表中查找是否有匹配的事件处理代码。如能找到,则执行相应事件的处理代码;如找不到,则把键值丢弃即可。
④通过串口连线,把这个二进制脚本从PC机上传送到嵌入式平台上,由uClinux上的引擎解释执行。当脚本在PC上模拟执行都正确时,在嵌入式平台上也就能正常运行了。

交互式开发脚本程序
GUI开发时最好能做到交互式开发,达到“所见即所得”的效果,因此我们也可以仿照VisualBasic开发环境中的可视化设计器,做一个简单的界面设计器,让用户在设计器里摆放菜单和文本输入框等控件,定义各个响应事件的脚本,然后综合起来自动生成脚本文件。因为脚本执行引擎在PC上就能工作,所以设计的脚本程序不用下载到手持设备里调试,在PC上马上就能看到运行结果,等PC上的运行结果都正确后再下载到手持设备里,这样不但方便了用户,而且提高了工作效率。

结束语

嵌入式操作系统的诞生,使嵌入式系统的开发进入了一个新的阶段,与传统的单片机开发模式有一定的区别。本文基于uClinux操作系统,介绍实现一个手持设备的GUI应用系统,由点到面叙述了系统的设计要点。由于系统层次结构比较清晰,同时引入脚本执行引擎,让用户使用脚本开发应用程序,符合现代编程的思维模式,所以这个应用系统可以作为一个通用架构,对于在嵌入式设备中,特别是基于嵌入式Linux的开发应用有重要的参考意义。

相关推荐

从TI“蝗虫战略”到雷军“芯片免费”

芯片  嵌入式系统  2013-11-07

嵌入式系统领域迎来创新与转型时代

嵌入式系统  通信  2013-05-30

VDC:物联网将改写嵌入式系统开发趋势

物联网  嵌入式系统  2013-05-14

ARM-Linux嵌入式系统的BootLoader分析与设计

嵌入式系统  Linux  2011-09-19

嵌入式系统的实时数据接口扩展

嵌入式系统  CPLD  2011-09-02

嵌入式系统U盘实时启动技术

VxWorks  嵌入式系统  2011-09-01
在线研讨会
焦点