Linux在台式机上的成功,使大家看到了Linux在嵌入式系统领域中的辉煌应用前景。嵌入式Linux具有源码开放、硬件需求低、软件模块化、可随意配置免许可、可移植等特点,符合工控领域可靠性、实时性、稳定性等要求。Qt是奇趣(Trolltech)公司开发的一套跨平台的应用程序开发框架,拥有直观、强大的API接口和C++类库,2000年发布的Qt/Embedded Linux版本可用于Linux嵌入式设备,Qt/Embedded Linux提供了自己的窗口系统,并且可以作为X11的轻量级替代产品。半导体激光器具有体积小、重量轻、运转可靠、耗电少、效率高等优点,作为一种新颖的激光光源,已经广泛用于军事、医疗、通信、工业等领域,如激光通信、激光雷达、激光手术、激光焊接。半导体激光器的特性受驱动电流和温度的影响,阈值电流随温度的升高而增大,当达到阈值电流时输出光功率随注入电流成线性变化,相同注入电流在不同温度下的输出光功率也不同,温度的变化也会引起中心波长的漂移,所以,半导体激光器的控制包括对驱动电流的控制和工作温度的控制。半导体激光器驱动电源的控制方法多样,利用Qt/Embedded开发的嵌入式图形用户界面能够方便地实现对驱动源系统的实时监测、控制、数据存储等功能。
1开发环境的搭建
半导体激光器驱动电源的控制核心处理器采用Sitare系列ARM处理器AM3354,其最高运行频率可达800 MHz,集成了基于ARM Cortex A8的微处理器单元(MPU),POWERVR SGXTM图形加速器,可编程实时单元和工业用通信子系统,保证系统在低功耗运行的同时拥有高性能。硬件结构如图1所示,外接256 MB的SDRAM和2 GB的NANDFLASH;电源管理芯片TPS65217用于处理器的电源管理,它能提供灵活的加电和断电时序并拥有电源正常输出、按钮监视器等附加功能;外接7寸LCD液晶显示触摸屏,处理器内的LCD控制器集成了LCD接口显示驱动器控制器,经过驱动电路后可直接连接LCD模块;AM3354处理器最多可支持6个UART,系统通过串口与LD驱动源连接进行数据的传输。
图1 LD驱动源控制硬件结构图
嵌入式应用软件的开发属于跨平台开发,由于目标机CPU和宿主机CPU拥有不同的架构,需要构建一个交叉编译环境,使在宿主机上开发出来的程序经过交叉编译后能够在目标机上运行。用来开发的计算机称为宿主机,一般运行Linux操作系统。嵌入式设备属于目标机。这里使用的宿主机为安装了Ubuntu操作系统的X86计算机(Ubuntu是一个以桌面应用为主的Linux操作系统),目标机为AM3354为处理器的嵌入式主板,操作系统采用嵌入式Linux.由于Qt /Embedded和Qt/X11有一样的API,在开发嵌入式环境的应用程序时,可以先在带Qt/X11库的宿主机上开发。
在此安装的交叉编译器版本为arm-linux-gcc-4.4.3,支持硬浮点运算。解压到某一目录下,在系统启动文件/etc/profile设置交叉编译器环境变量,最后导入环境变量,#arm-linux-gcc-v命令可以查看编译器是否添加成功。安装嵌入式Qt应用程序开发库,解压Qt/Embedded库到相应目录下并编译。在应用程序运行时,要正确设置环境变量,以使应该程序能正确调用安装目录下的库文件。
2 Qt/Embedded应用程序软件设计
Qt/Embedded软件体系摒弃了X lib库,将外部输入设备抽象为键盘和鼠标事件,采用帧缓冲作为底层图形接口,应用程序可以直接写内核帧缓冲,避免了使用繁琐的X lib/Server机制。
Qt/Embedded应用程序设计有两种方式,一种是用集成开发环境图形编程方式,一种是代码编程方式。无论使用哪种方式都会涉及元对象系统。元对象系统是对C++进行扩展的一种机制,Qt使用这种机制创建了独立的软件组件,它提供了关键的两项技术:信号-槽以及内省。内省功能对于实现信号和槽是必需的,并且允许应用程序的开发人员在运行时获得有关QObject子类的“元信息”,包括一个含有对象的类名以及它所支持的信号和槽的列表。信号和槽是Qt通信机制的核心。当一个特殊的事情发生时便可以发射一个信号,而槽就是一个函数,它在信号发射后被调用来响应这个信号,通常一个信号对应一个槽,一个信号也可以关联多个槽,多个信号也可以关联到同一个槽上。
2.1串口通信的实现
在Qt中并没有特定的串口控制类,大部分使用第三方写的qextserialport类。该类包含两个类:QextSeri-alBase类和Posix_QextSerialPort类,后者继承前者,而QextSerialBase类又继承自Qt软件自带的QIODevice类。在QextSerialBase类中涉及到了一个枚举变量QueryMode,它有两个值Polling和EventDriven,Polling指的是查询方式读/写串口,EventDriven是事件驱动方式。事件驱动方式就是使用事件处理串口的读取,一旦有数据到来,就会发出readyRead()信号,就可以关联该信号来读取串口的数据。
在事件驱动的方式下,串口的读/写是异步的,调用读/写函数会立即返回,它们不会冻结调用线程。而查询方式Polling读/写函数是同步执行的,信号工作在这种模式下是不起作用的,但这种模式下开销较小,可以建立定时器来读取串口的数据,并将结果显示在Qt的图形用户界面上。这里采用Polling查询方式读/写串口。设置一个100 ms的定时器,通过Qt特有的信号与槽机制,将定时溢出信号关联到读串口槽函数上,实现数据的实时采集显示。
程序流程:首先新建一个串口类,设置串口通信的属性,最常见的属性设置包括通信端口、波特率、数据位、奇偶校验、停止位以及控制流等,然后读/写串口。
每个设备端口在/dev目录下都有一个对应的文件,Linux下的文件用文件描述符来描述,它指向内核中每个进程打开的文件记录表。串口资源的文件路径是/dev/ttyO*,因此对串口的操作就像对普通文件的操作一样,部分操作程序如下:
struct PortSettings myComSetting = {BAUD9600,DATA_8,PAR_NONE,STOP_1,FLOW_OFF,500};
QString portName ="/dev/ttyO2";
myCom=new Posix_QextSerialPort(portName,myComSetting,QextSerialBase::EventDriven);
myCom->open(QIODevice::ReadWrite);
QByteArray temp=myCom->readAl(l);
2.2软键盘的调用
文中设计的软键盘包括字母、数字的输入、大小写字母的切换以及退格、回车等功能。在Linux环境的QtDesigner下,创建一个新的Widget,将Buttons选项中的PushButton按键拖入到软键盘区域内,然后根据需要修改每个按键上面的文本属性和名字属性。
软键盘的实现是基于信号与槽机制。利用Qt的多信号映射机制,首先使用QSignalMapper类来捆绑不同按键所发送的一系列无参数信号,并将其转化为有参数的信号,实现一个函数可以响应不同按钮的功能;然后需要建立每一键值对应的信号与槽之间的关系connect(ui->pushButton,SIGNAL(clicked()),码值信号调用sendCharacter(QChar)槽,从而实现正确的键值输入。界面设计如图2所示。
图2软键盘界面
Qt设计师窗口部件简单有限,某些情况下要自定义窗口部件。它有两种方法:改进法和插件法。插件法需要创建一个插件库,它为可选的额外功能提供了一个特殊接口。Qt设计师运行时可以加载这个库,并且利用该库创建窗口部件的实例,本设计自定义了三个窗口部件QMeter、thermometer和led.
3程序的移植和发布
安装了交叉工具链以及经过交叉编译的Qt/E库后,就可以将前面编辑好的应用程序进行交叉编译生成可执行二进制文件,然后发布到嵌入式控制板中。另外,在发布之前需要先移植tslib和Qt/E库,tslib是电阻式触摸屏用于校准的一个软件库,是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用提供了一个统一的接口。解压根文件系统到home路径下,复制编译好的tslib、Qt/E库文件到根文件系统中,最后导出相应的环境变量。应该程序可以以界面图标的形式运行,这时,就需要自己制作启动器文件,在for-linx/web/lighttpd/webpages/apps目录下新建current.desk-top文件,然后编辑该文件:
#!/usr/bin/env xdg-open
[Desktop Entry]
Name=Serial
GenericName=Demo App
Icon=/forlinx/web/lighttpd/webpages/apps/images/current.png
Exec=/forlinx/web/lighttpd/webpages/shell/current.sh
Type=Application
ProgramType=gui
current.png是一个32×32的PNG图标文件,可根据自己的需要制作并存于相应路径下。交叉编译生成的二进制文件current放于forlinx/qt/bin目录中。current.sh是编写的shell脚本,当用户点击界面图标时会自动执行脚本文件里的命令:
#!/bin/sh
if test -e /dev/fb0;
then
width=′fbset | grep′geometry′| awk′{print $2}′′
height=′fbset | grep′geometry′| awk′{print $3}′′
let height=height-38
geo=′echo $width\x$height+0+0′
fi
pidof matrix_gui > /dev/null 2>
if [ $? == 0 ]
then /forlinx/qt/bin/serial -geometry $geo$*
else
export TSLIB_TSDEVICE=/dev/input/touchscreen0
export QWS_MOUSE_PROTO=Tslib:/dev/input/touchscreen0
/forlinx/qt/bin/current -qws -geometry $geo$*
fi
如果需要开机自动运行程序,可以编辑启动时的执行文件/etc/init.d/rcS,将启动程序路径和可执行应用程序名添加到这里,就可以实现系统启动时程序的自动运行,在嵌入式主板上运行效果如图5所示。
4结语
嵌入式系统的实时性、高可靠性以及友好高效的GUI被广泛用于工业控制当中。基于Qt/Embedded设计的嵌入式控制界面实现了与单片机的串口通信、文字的编辑、控件的载入和显示、数据的保存记忆、软键盘的调用等功能。本文根据光纤激光器泵浦源的特点,以设计泵浦源驱动的人机交互界面为前提,结合用户需求和Qt/Embedded特点来开发嵌入式控制面板。详细介绍了基于Qt/Embedded的嵌入式应用程序的开发过程,并成功移植到嵌入板中控制LD正常工作。 |