基于Nios II自助点菜系统的μC/GUI应用
随着嵌入式系统在各领域的广泛应用,对图形化人机交互界面的需求逐渐增加。由于嵌入式系统硬件资源有限,从而要求图形用户界面具有轻型、占用资源少、高性能等特点。μC/GUI是一种用于嵌入式应用的Windows风格图形支持软件,它为任何使用图形LCD的应用提供一个有效的不依赖于处理器和LCD控制器的图形用户接口,工作在单任务或多任务系统环境下,适用于使用任何LCD控制和任何CPU尺寸的物理或虚拟显示。因此,掌握μC/GUI在嵌入式系统中的应用极为重要。移植μC/GUI到Nios II嵌入式软核处理器[1]成了最佳选择。本文根据自助点菜系统的实际应用,详细介绍了μC/GUI移植方法,并在融合触摸屏操作的基础上实现控件使用和操作系统开发。
1 硬件
系统中顾客使用终端触摸屏浏览服务信息并实现相关操作,通过无线局域网络和前台通信。各个点菜终端作为独立系统工作,所有数据传到前台上位机协调处理。本文仅介绍与μC/GUI相关的点菜终端构成部分。终端硬件框图如图1所示,利用片上可编程系统(SoPC)技术将Nios II处理器、外设接口控制器等功能模块集成到FPGA,构成可编程片上系统[2]。SDRAM、Flash控制器用于处理程序和数据的存储;512 KB SRAM作为图像数据缓存区;FPGA内部自定义LTM控制器和SD卡控制器模块,辅助软核工作,操作触摸屏并读取SD卡内的JPEG图片;UART接口用于和移植到CC2430的ZigBee模块通信;采用定时器以嵌入式uC/OS II操作系统。
触摸显示屏是4.3英寸数字LCD触碰面板TRDB-LTM,长宽比为15:9,支持24 bit并行RGB接口,能通过内置模数转换器(AD7843)将触碰点X/Y坐标转换成对应数字信息。触摸屏物理分辨率为800×480,支持16 bit RGB565格式。
2 μC/GUI移植
本系统的用户界面采用uC/GUI,其最新版本是3.98,其中一些组件不太完整。根据点菜系统使用需求,特添加3.94版本的JPEG模块来显示图片数据。ucgui398StartConfig和ucgui398StartGUI是源码包最重要的两个文件夹,其中包括各种配置文件、μC/GUI内核文件、与字体相关的代码文件、LCD驱动代码文件、μC/GUI支持的控件代码以及视窗管理部分代码等[3]。
2.1 修改LCD配置文件
为使系统正确工作,必须修改文件LCDConf.h(GUI目录中)中的一些配置宏。该文件与硬件直接相关,根据所使用的LCD类型和LCD控制器进行配置。由于μC/GUI提供不同型号的LCD配置文件(文件夹SampleLCDConfxxx中,xxx代表LCD驱动器名称),应用程序开发者可直接在此基础上修改程序。实际应用中,选择LCDLin.c驱动文件。由于LTM控制器对显示分辨率进行硬扩处理,因此LCD尺寸选择400×240。系统底层配置的部分宏如表1所示。
LCD_READ_MEM(off)、LCD_WRITE_MEM(off,data)宏定义是μC/GUI与LTM控制器接口的关键[4]。SRAM_BASE是512 KB SRAM读写操作的基地址,这些宏定义能实现对图像数据缓存区的16 bit读写操作。此外,一般移植操作必须定义LCD_INIT_CONTROLLER(),以实现LCD屏初始化配置。LTM控制器初始化了触摸屏,因此软件配置中省略此项。
2.2 修改GUI和触摸屏配置文件
在调整系统或减小内存消耗时需配置LCDConf.h。具体步骤如下:(1)备份原始配置文件;(2)检查所有配置开关;(3)删除配置中不使用部分。除此之外,系统工程编译时,会出现一些未定义错误,需要将SampleGUI_XGUI_X.c添加到工程中,该文件定义GUI与操作系统的接口,以及Debug错误报告等函数。由于系统使用μ/OS II,可选择GUI_X_uCOS.c文件,并在文件结尾处添加以下函数:
void GUI_X_Log(const char *s){GUI_USE_PARA(s);}
void GUI_X_Warn(const char *s){GUI_USE_PARA(s);}
void GUI_X_ErrorOut(const char *s){GUI_USE_PARA(s);}
同时将GUI_X_ExecIdle( )中的OS_X_Delay(1)替换为OSTimeDly(1)。
GUI文件夹中另一个需要配置的文件是GUITouchConf.h,根据触摸屏类型不同,宏参数也不同。执行触摸屏操作的主要流程在GUICoreGUI_TOUCH_DriverAnalog.c文件中。头文件部分宏配置如表2所示。
2.3 触摸屏与GUI接口
μC/GUI支持键盘、鼠标、触摸屏等外设,并在源码级对其消息响应。为使触摸屏正常工作,系统除对相应配置文件修改和添加一些相关函数外,必须实现触摸屏底层驱动,即修改LCDLin.c驱动文件。
理论上,GUI_TOUCH_AD_LEFT和GUI_TOUCH_AD_RIGHT取值应当为0或1 024,但实际操作时,必须根据具体情况校准。系统取触摸屏四个角坐标作为校正标准,经过多次试验,四个坐标分别是(29,160)、(3 936,160)、(29,3 900)和(3 936,3 900)。在GUICoreGUI_TOUCH_DriverAnalog.c中修改相应宏,再据实际情形确定余下开关宏的值。
通过调用GUI_TOUCH_Exec()函数来获得触摸屏触点位置:系统通过中断服务程序读回触点实际坐标值(x,y);接着将实际坐标值转换到逻辑坐标;最后调用GUI_TOUCH_StoreState(x,y)保存逻辑坐标值。为实时得到触点坐标,需不断调用GUI_TOUCH_Exec()函数,因此建立单独任务对该函数调用,以保证触摸屏任务的实时响应。该部分设计难点在于中断标志清零,如果每次得到触点位置后不能即刻清零,则会影响GUI内部去抖操作和校准处理,因此在保存稳定坐标值后再清除标志位。
3 μC/GUI应用开发
3.1 触摸屏消息响应机制
GUI所有外设输入均以消息形式发送给当前窗体回调函数处理,具体流程如图2所示[5]。触摸屏的消息传递实质是对全局变量_State记载和更新。_State有3个成员变量:消息发生点x坐标、y坐标、外设按下与否的操作状态。外设输入消息统称为WM_TOUCH,函数WM_HandlePID()专门处理这种消息。通过GUI_PID_GetState获取GUI_PID_STATE结构的WM_TOUCH消息,将新获取消息与函数内静态旧消息变量比较,包括该消息发生点的屏幕坐标及外设操作状态。状态发生变化是将操作状态变化作为独立消息WM_PID_STATE_CHANGED发送,再发送WM_TOUCH消息。构造WM_TOUCH消息所用到的数据,需要获取当前焦点窗体句柄,当前焦点窗体是用WM_hCapture全局变量记载,如果为0则调用函数WM_Screen2hWin(),根据消息发生点屏幕坐标获取窗体句柄。向当前焦点窗体发送消息后,更新当前消息到旧消息变量,结束本次消息处理。
3.2 窗口、控件和对话框应用
系统界面丰富,频繁用到页面切换,因此使用?滋C/GUI视窗管理器(WM)进行窗口创建、显示、隐藏和删除等。用户程序中对不同窗口指定不同回调函数,当指定事件发生时,通知图形系统调用指定函数,如窗口内容改变时自动重绘的场合等。图3(a)、图3(b)分别为菜品推荐及菜单显示窗口。
为使点菜系统功能更加丰富,界面中加入按钮、列表框、单选按钮、框架窗口等控件。控件是构造用户接口的元素,能自动对某些事件反应。控件也是通过其构造函数返回的句柄而引用。控件使用视窗管理器,一旦一个控件建立,它被处理成与其他窗口一样,WM保证它在需要时能正确显示(及重绘)。
控件消息响应机制在使用中十分重要,包括按钮触碰响应、单选按钮序列号获取、列表框滑动等。下面以按钮为例介绍其功能。Button按钮在其回调函数中对相关消息(WM_MOUSEOVER/WM_PID_STATE_CHANGED/WM_TOUCH)进行处理,在button.c文件中可找到相关实现函数,用触摸屏点击该按钮时发送以下三种消息之一:WM_NOTIFICATION_MOVED_OUT、WM_NOTIFICATION_RELEASED、WM_NOTIFICATION_PRESSED,之后在该按钮父窗口捕获并处理消息。系统是通过捕获WM_NOTIFICATION_RELEASED消息实现按钮触碰功能的。
系统除了点菜外,还能存储会员信息,用于累积会员积分,如图3(c)。对于新建和登录账户界面,使用对话框是很需要的。建立对话框需要做两件基本工作:一个资源表,定义包括的控件;另一个是定义控件的初始化。对话框包含多个控件(框架窗口、按钮、编辑框、文本框),通过对不同控件的选择向系统发出请求信息。多数消息被对话框自动处理,其他传送给对话框指定的回调函数。其中,将WM_INIT_DIALOG和WM_NOTIFY_PARENT两种类型的附加消息传送到对话框窗口进行处理。对话框显示前,WM_INIT_DIALOG消息立即被发送到对话框处理,对话框程序用这个消息初始化控件以及实现其他影响对话框显示的初始化任务;通过对话框的子窗口发送WM_NOTIFY_PARENT消息到对话框,通知父窗口以保证事件同步。
3.3μC/OS II应用
系统使用接口函数OSTaskCreateExt 创建任务,根据系统要求,设计四个任务,分别是:初始化任务(TaskStart)、接收消息任务(TaskRxmsg)、响应触摸任务(TaskTouch)和更新任务(TaskUpdate)。任务间通过信号量、全局变量等方式通信,具体状态转移如图4所示。
(1)初始化任务
优先级别最高,用于建立和调用系统初始化函数。系统上电后,首先对各个硬件模块、软件内各数据初始化,如果SD卡读取不成功、无线运行不正常,LED灯提示系统初始化失败,同时系统退出运行状态。反之,初始化完毕,系统开始任务调度。
(2)接收消息任务
接收上位机传回的确认信息,实时显示菜单状态:准备中、制作中、传送中和已上菜。由于无线发回数据不定时,且为了避免数据丢失,该任务优先级别高于TaskTouch。该任务与TaskTouch之间用信号量通信。
(3)响应触摸任务
用于执行GUI_TOUCH_Exec()函数,更新触摸点状态,设置窗口、对话框等的回调函数,进行界面切换。放弃对CPU占用后,系统调度将CPU占用权交给TaskUpdate。
(4)更新任务
由于使用视窗管理回调机制,该任务必须实现,并定期调用(至少每秒钟100次),优先级别最低。仅从一个任务调用GUI更新函数(即GUI_Exec(),GUI_Delay()),有助于保持程序结构清晰。任务完成后,按任务优先级高低开始新一轮调度。
以μC/OS-II操作系统为基础,系统在响应触摸任务和更新任务中分别调用μC/GUI函数。该项工作通过在配置中使能多任务支持及配合内核接口函数来完成。由于任务实时行为只受运行在更高级别任务的影响,所以在低级别任务中设置用户界面,使其切换到用户界面时不会影响实时行为。
本文介绍的系统,在Nios II架构上移植了可视化图形库μC/GUI,系统重点研究了如何应用?滋C/GUI。在实现触摸屏操作的基础上,结合消息响应机制实现窗口、控件和对话框的使用,并融合多任务操作系统提高点菜的实时性。LTM触摸屏显示带有Windows风格图形界面,顾客可根据菜品图片、营养介绍及价格随时点餐。通过GUI整合的触摸操作,实现了自助点菜、查看菜品状态、加菜、退菜以及结账功能,可提供更优质、更人性化的服务。
加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW
或用微信扫描左侧二维码