介绍用MiniGUI设计小键盘输入的方法
扫描二维码
随时随地手机看文章
嵌入式系统通常拥有特定的输入设备。嵌入式系统是“控制、监视或者辅助装置、机器和设备运行的装置”(devices used to control, monitor, or assist the operation of equipment, machinery or plants)。从中可以看出嵌入式系统是软件和硬件的综合体,还可以涵盖机械等附属装置。目前国内一个普遍被认同的定义是:以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。嵌入式系统必须根据应用需求对软硬件进行裁剪,满足应用系统的功能、可靠性、成本、体积等要求。所以,如果能建立相对通用的软硬件基础,然后在其上开发出适应各种需要的系统,是一个比较好的发展模式。目前的嵌入式系统的核心往往是一个只有几K到几十K微内核,需要根据实际的使用进行功能扩展或者裁减,但是由于微内核的存在,使得这种扩展能够非常顺利的进行。
1 MiniGUI对键盘输入的处理方式
MiniGUI是由北京飞漫软件技术有限公司创办的开源Linux图形用户界面支持系统,经过近些年的发展,MiniGUI已经发展成为比较成熟的性能优良的、功能丰富的跨操作系统的嵌入式图形界面支持系统。“小”是MiniGUI的特色,它目前已经广泛应用于通讯、医疗、工控、电子、机顶盒、多媒体等领域。目前,MiniGUI的最新版本为MiniGUI 3.0,所以MiniGUI对中文的支持最好。它支持GB2312与BIG5字元集,其他字元集也可以轻松加入。MiniGUI 为嵌入式 Linux 系统提供了完整的图形系统支持,是全球针对嵌入式 Linux仅有的两个商用嵌入式GUI系统之一。MiniGUI为嵌入式Linux 系统提供了完整的多进程支持;可以 MiniGUI-Processes、MiniGUI-Threads或者MiniGUI-Standalone 三种运行模式运行。
开发特定的键盘输入,主要完成底层的两部分工作:键盘驱动程序设计和键盘输入引擎开发。前者负责从键盘接收原始输入事件和数据,后者负责把原始的输入事件和数据转抉成MiniGUI抽象的键盘事件和数据。至于抽象键盘事件和数据转换成上层的击键消息等工作,则是由MiniGUI提供的底层事件处理例程自己完成,无需用户设计。
2 键盘驱动程序设计
该设备驱动要实现的主要功能是进行小键盘行列扫描,接收原始键盘输入事件和数据,如有无键按下、按下某键或释放某键。返回的字符型按键信息(小键盘扫描码)由两部分组成:“高位”代表键盘输入事件,即按下(高位为O)或释放(高位为1);“低7位”代表键盘输入数据,即按下或释放的按键值。
2.1 键盘按键值的获取
当按下某个键时,和该键所在行列相连的两路通用外设I/O引脚就会导通,其电平就会相同,因此驱动中只需要轮询各路I/O引脚就可以知道按键值。比如,使各行线输入低电平,各列线都通过上拉电阻接高电平,此时检测各列,如果某一列电平为低,则说明该列所在的键盘已经按下,使该列与行导通变为低电平,这样就可以确定按键所在列号(j);同理,将各列置低电平,再依次查询各行,就可以确定按键的行号(i)。若定义一个键值映射数组key_arrow[5][5]表示所有键盘按键值:Key_arrow[5][5]={{0,O,O,O,0,0},{0,‘7’,‘8’,‘9’,‘A’},{0,‘4’,‘5’,‘6’,‘B’},{0,‘1’,‘2’,‘3’,‘C’},{0,‘D’,‘O’,‘。’,‘E’}},则按键值就为key_arrow[i][j]。初始化时行列号均为0,因此当小键盘无键按下时,返回按键值为0(即字符NULL)。
2.2 键盘扫描码的获取
为了判断键盘事件是按下还是释放,定义两个无符号型字符变量last和key。前者是静态变量,存放等待释放的键的按键值,即前一次扫描读到的按键值;后者存放当前键盘扫描码。当键盘事件为按下时,它的值和键盘按键值相同;当键盘事件为释放时,它的值等于last高位置l后的值。
2.3 功能实现流程
我们用驱动程序read接口函数实现这些功能。当应用程序凋用read函数后,该函数先进行行列扫描,得到键盘按键值key_arrow[i][j]后进行判断。着其非零,即有键按下,则直接将此按键值作为键盘的扫描码(key=key_arrow[i][j]),并将其赋给字符变量last,表示该键等待释放。如果key_arrow[i][j]为零,即无键按下,则判断是否有需要释放的键:若没有(即last为O),就直接将按键值(key=0)作为键盘扫描码;若有键需要释放(1ast非零),就把1ast高位置1作为键盘扫描码(key=last 10x80),表示释放刚按下的键,然后last清零,表示已没有按键等待释放。
3 键盘输入引擎的设计
第2部分要开发的是小键盘输入引擎。它负责把键盘驱动提供的原始键盘输入事件和数据(即小键盘扫描码)转换为MiniGUI抽象的键盘事件和数据(由系统扫描码索引的键盘数组)。
3.1 MiniGUI的IAL接口
前面已提到,IAL定义了一组不依赖于任何特殊硬件的抽象接口,而用于实现这一抽象接口的底层代码就称为输入引擎。在代码实现上,MiniGUI通过INPUT结构来表示“输入引擎”。它实际是一个拥有若干函数指针成员的结构体,MiniGUI在特定的时候调用这些函数来达到操作硬件的目的,因此,编写特定的输入引擎,主要就是编码实现INPUT结构中的各个函数。该结构定义在/minigui-free/libminigui-1.3.3/ src/ial/ial.h中,其中的主要成员函数如表l所列。
3.2 编写小键盘输入引擎
3.2.1 底层输入操作函数实现
对于小键盘输入,鼠标操作接口函数不用进行任何操作,直接返回即可,主要需要编写的是keyboard_update及wait_event函数。当。MiniCUI应用程序运行时,相关的底层事件处理例程会不断调用wait_event函数查询是否有输入事件发生,故在该函数中调用小键盘驱动的read函数,获取用户输入的按键信息。
需要注意的是,由于系统以很高的频率不断调用wait_event函数,因此当该函数捕捉到键按下事件时,需要一定时间(如100 ms)延时再返回,以避免一次按键产生多次键盘事件。
MiniGUI使用一个一维数组state[128]记录按键的状态。该数组定义在include/common.h中。State[128]中每个元素均对应一特定的按键,如果某一元素为l,说明它所对应的键被按下,否则该键未被按下。因此,key-board_update函数要做的工作就是,根据键盘扫描驱动程序的返回值,更新state数组的元素值,从而向上层驱动程序和应用程序反映按键状态。
3.2.2 初始化及终止函数实现
在初始化函数中先打开小键盘输入设备,成功以后对输入引擎的其他成员(底层输入操作接口函数)赋值,返回TRUE。终止清除函数的主要工作是关闭键盘输入文件。输入引擎相关内容的格式可参照 src/ial/目录下的其他输入引擎。
3.3 输入引擎的使用原理
在 src/ial/ial.c中,用inputs结构数组定义了MiniGUI支持的所有输入引擎信息。系统启动后,将根据MiniGUI.cfg配置文件,在inputs结构中寻找特定的输入引擎作为当前的输入引擎。然后,调用该引擎的初始化函数,对全局变量cur_input(表当前使用的输入引擎)的其他成员函数进行赋值。
在 src/sever/server.c中,函数IdleHandler4Server凋用输入引擎中IAL_WaitEvent成员函数,检查是否有底层输入事件发生。当有事件发生时,检查是鼠标(触摸屏)事件还是键盘事件发生,并分别用parseEvent(msg_que, event)处理这些事件。parseEvent函数中首先调用Getl-wevent(event,&1we)函数。该函数利用IAL引擎中相应底层操作函数收集底层输入事件1we(该结构定义在paxseEverlt函数中),parseEvent再将收集到的这些事件转化为上层能理解的消息。具体实现细节可参考server.c文件。
4 键盘输入在MiniGuI中的实现步骤
4.1 加载小键盘驱动
有两种方法加载:一是把该驱动加载入内核;二是可以将编译的*.o文件拷贝到目标板根文件系统巾,目标板启动后用insmod命令动态加载。
4.2 添加小键盘输入引擎
添加小键盘输入引擎方法步骤如下:
①仿照 src/ial/2410.h编写mykbd.h文件,与myk—bd.c文件一同保存到 src/ial下;
②在 src/ial/ial.c文件中添加新引擎的人口(位置及格式参考该文件中其他引擎);
③在conflgure.in、acconfig.h及 src/ial/Make-fne.am文件中的其他引擎信息之后加人新引擎信息;
④执行aclocal及autoheader,分别生成aclocal_m4及config.h.in文件;
⑤执行|dLltoconI’,生成。onfigurt:,修改该con矗lgure文件,在开头处添加交叉编译器路径(否则会使用gcc进行编译);
⑥执行aLit0131~lke—add_misslng命令,生成MaItefile.in等文件;
⑦执行。/configure--enable-jpgsupport=no--enaable=pngsupport=no--enable-gifsupport=no--disable-lite--prefix=
/minigui-free/install--enable-mykbdial=yes(指定安装路径在/tnlr电心free/lnstall目录下,若configure.in中设置该输入引擎默认为安装,则不用加最后一项配置参数);
⑧执行make,及rrlake,instaII命令进行编译和安装;
⑨把安装路径下的Iib/libminigui一1.3.so.3.0.O库文件复制到目标板根文件系统lIb目录下(前提是已拷贝了MiniGLfI运行库和资源环境到根文件系统中);
⑩修改配置文件(目标板根文件系统/et~:/MinigLti. cfg),令iaLenglne—mylebd,使用这个新的输入引擎。
4.3 根文件系统的移植
将交叉编译后的MiniGtII应用程序复制到根文件系统中,制作并下载根文件系统映像文件到目标板中,目标板系统启动后加载小键盘驱动并运行该应用程序即可。
结语
MiniGUI 丰富的功能和可配置特性,使得它既可运行于 CPU 主频只有 60MHz 的低端产品中,亦可运行于高端嵌入式设备中,并使用 MiniGUI 的高级控件风格及皮肤界面等技术,创建华丽的用户界面。 MiniGUI 的跨操作系统特性,使得 MiniGUI 可运行在最简单的嵌入式操作系统之上,如 uC/OS-II,也可以运行在具有现代操作系统特性的嵌入式操作系统之上,如 Linux,而且 MiniGUI 为嵌入式 Linux 系统提供了完整的多窗口图形环境。这些特性,使得 MiniGUI 具有非常强的可伸缩性。可伸缩性是 MiniGUI 从设计之初就考虑且不断完善而来的。这个特性使得 MiniGUI 可应用于简单的行业终端,也可应用于复杂的消费类电子产品。
开发MiniGIJI对特定输入设备的支持,主要完成的是输入设备驱动及输入引擎的编写、新输入引擎的添加。调试过程中,应根据串口终端的错误提示和程序运行时的现象判断是驱动程序或输入引擎编写有误,还是设有正确添加输入引擎造成了错误,再进行相应的修改。建议先用非Mini(:u1程序调试驱动程序,确保其能正确实现所提供的功能后,再运行MiniGIJI应用程序进行调试。如果出现的错误为无法找到匹配的输入设备,则多是未能正确掭加输入引擎造成;若错误为初始化输入引擎失败,则是驱动未成功加载或输入引擎初始化函数中打开的设备名与驱动注册的设备名不符合造成的。