Qt嵌入式软件(共7篇)
Qt嵌入式软件 篇1
摘要:为了提高微型生化分析仪界面的友好度,系统稳定性和功能的可扩展性,设计并实现了嵌入式QT界面。设计采用以S3C2440为核心的硬件平台和以Linux为核心的软件平台,并在此基础上使用了开放源代码的QT图形界面库开发程序,移植了SQLite数据库,实现了串口的数据通信等功能。经试验验证,该设计具有界面友好,稳定性高等优点,并且在功能的可扩展性,可跨平台性等方面有显著的改善,对其它工控设备的界面开发有一定的参考和研究价值。由于Linux和QT具有很强的移植性,该方法具有广泛的应用前景。
关键词:嵌入式GUI,Linux,QT,S3C2440
1 引言
微型生化分析仪是以一块几平方厘米或者十几平方厘米的芯片为载体,在其中进行基本的生物和化学领域中的生物化学反应,分离检测等的操作,并用分析仪中的电子设备对检测数据进行分析,存储,输出等操作。该产品适用于食品检测、水质分析、医疗检测等领域,并具有很好的发展前景。而为了该产品的实现便携,小型化,操作友好性强等特征,设计一个美观的操作界面成为其必不可少的要求之一。QT作为嵌入式设备广泛采用的GUI应用程序,具有体积小巧,稳定性强,实时性强,可量身订做等特点[1]。因此,伴随ARM处理器以及Linux系统的使用越来越广泛,开源代码的图形库QT开发的优势显得尤为明显[2]。
本设计以mini2440为硬件载体,linux-2.6.3.2为软件环境,并考虑软件的功能性和运行的流畅度等特征,采用了qt4.6.3进行界面开发。实现了mini2440和外部设备的串口数据通信,并能够利用串口打印机进行数据的打印,实现U盘数据存储等特征。
2 系统结构分析
本设计采用mini2440硬件平台上移植linux-2.6.3.2系统,并编写QT-4.6.3应用程序在系统上运行,设定开机自动运行该应用程序。系统的软件结构如图1。
3 软件开发和运行环境的搭建
实现mini2440上QT软件的开发,除了要在电脑中搭建好开发环境外,还要在开发板中为程序的运行好建立运行环境。这里我们选择的版本是QT-4.6.3,所以首先要完成QT-4.6.3的移植工作。包括将编译好的库文件拷贝到开发板指定的目录下,并为QT做好环境变量的设置等[3]。
QT-4.6.3的移植主要需要完成以下工作:
环境:在电脑中安装好fedora14系统(建议在VMware Workstation中安装),安装好交叉编译工具链:arm-none-linux-gcc-4.3.2,并在系统中安装samba服务器。
软件准备:下载Linux下的安装包qt-every whe re-opensource-src-4.6.3.tar.gz和用于Linux/X11 32位的Qt Creator-1.3.1二进制软件安装包,该二进制安装包名称如下:qt-creator-linux-x86-opensource-1.3.1.bin。
移植步骤如下:
(1)利用samba服务器将两个安装包qt-every where-opensource-src-4.6.3.tar.gz和qt-creatorlinux-x86-opensource-1.3.1.bin上传到fedora系统,并使用命令tar–xzvf qt-everywhere-opensourcesrc-4.6.3.tar.gz对安装包进行解压。
(2)为了使开发的qt程序既能在电脑端Linux系统中进行仿真,又能进行交叉编译生成arm版的二进制文件,需要在fedora中编译X86和embedded版qt-4.6.3。
(3)安装qt-creator-linux-x86-opensource-1.3.1.bin,方便使用qt-creator进行qt的开发。
(4)拷贝编译成功的qt的lib文件到开发板中,注意拷贝到开发板中的路径要和fedora14中的路径相同,否则开发板中运行QT程序时会提示找不到库文件。
4 应用程序软件设计
4.1 软件功能需求分析
该微型生化分析仪结构如图2,由DSP完成对机械结构的控制,并将命令通过串口传送给mini2440,由mini2440返回控制指令。并且通过mini2440界面控制,能够完成采集信号的存储和打印功能。
因此,需要设计的应用软件的主要功能有,通过串口实现指令的接收和发送,对接收的数据进行处理和筛选后在界面上进行显示,实现数据的打印或存储。在程序的设计中,使用了QT的文件处理、数据库、表格显示,时间处理等相关类。并调用了系统指令实现了关机等功能。
4.2 软件详细设计
4.2.1 信号与槽机制
信号和槽机制是QT的核心机制[4]。它是一种高级接口,应用于对象之间的通信。作为一种独立于C++语言的机制,需要借助于QT工具moc进行预处理,生成所需要的附加代码[5]。信号与槽函数的关联函数为bool QObject::connect(const QObject*sender,const char*signal,const QObject*receiver,const char*member),当sender发送信号时,将调用接收函数。一个对象可以与多个槽关联,也可以多个信号与同一个槽关联方式[6]。信号与槽的关联方式如图3。
该软件设计中添加很多按钮,并需要实现界面的切换,下面关联实现了点击按钮调用窗口切换函数的功能,部分程序如下:
4.2.2 串口通信的实现
串口通信的实现并没有涉及QT的部分,由于mini2440系统中串口的驱动程序已经移植好,所以只需要对串口进行初始化,包括设定串口通信的波特率、奇偶校验、停止位数据位等[7]。这里我们设置串口的通信速率是115200,数据位是8位,停止位是1位,无奇偶校验。具体程序如下:
4.2.3 数据库的使用
由于该生化分析仪要对检测的数据进行存储等功能,并且SQLite3数据库功能强大、接口简单、速度快、体积小[8],非常适合嵌入式设备,所以这里进行了数据库SQLITE的移植,具体过程如下:
(1)下载sqlite源码sqlite-3.6.22.tar.gz,复制到Linux系统中并进行解压,输入如下指令:
(2)创建build目录并在这个目录中进行交叉编译,输入如下指令:
mkdir buildcd build
(3)在build目录中运行sqlite-3.6.22中的con figure脚本生成Makefile文件,如下:
../configure--host=arm-linux--prefix=/root/sqlite-3.6.22/build/target
(4)执行make和make install命令,并且在编译和安装完后将生成的bin下的文件下载到开发板/usr/bin目录中,将lib下的文件下载到开发板/usr/lib中,include目录下的是编程中会用到的C语言API的头文件。
数据库使用以及界面显示的部分代码如下:
4.2.4 关机和时间设定功能的实现
关机功能的实现可以调用Linux下的shutdown命令,shutdown命令的语法规则如下[9]:
shutdown[-cf Fhknr(参数名称)][-t秒数]时间[警告信息]
因此,程序中我们可以写为system(“shutdown–s–t 0”);-s表示关机,-t表示设置关机时间[10],这里表示为0秒后实现关机功能。
对于时间的设定,程序中可以调用类QDate和QTime,并使用系统命令hwclock来设置系统时间。具体方法为:使用代码QDate Date=ui->date Edit->date();来返回界面中设定的日期,并使用QTime time=ui->time Edit->time();来返回界面中设置的时间值。并使用QDate::to String()函数来将上面的值转换成字符串形式,最后使用system(“hwclock–w”)来完成系统时间的设定。
5 程序测试
程序编写好后,可以在qt-creator中通过调整project选项来进行计算机端的仿真或者进行交叉编译,生成arm可执行的二进制文件后移植到开发板中。
该程序需要完成检测芯片仓的开启和关闭工作,并完成参数的设定,数据的存储,打印,系统时间设定,以及关机功能等,运行编译好的qt程序,部分测试结果如图4。
6 结束语
该微型生化分析仪界面设计可以配合分析仪其它部分完成检测工作,解决需要实现的功能,并且稳定性好,可靠性高,后续可进行程序的改进和继续开发,并可以带来良好的操作体验,具有很高的实用价值。
参考文献
[1]陈爽,秦攀科,贺荣,杨晨.Linux与Qt程序设计[M].北京:清华大学出版社,2011.12.
[2][加拿大]BLANCHETTE Jasmin,[英]SUMMERFIELD Mark.C++GUI Qt4编程[M].第二版.闫锋欣译.北京:电子工业出版社,2013.5.
[3]蔡志明,卢传富,李立夏.精通QT4编程[M].北京:电子工业出版社,2008.
[4]倪继利.Qt及Linux操作系统窗口设计[M].北京:电子工业出版社,2006.
[5]刘小春,张有为,向伟.嵌入式Linux下Qt/Em bedded应用关键技术研究[J].微计算机信息.2007,(35):62-63.
[6]任善全,吕强,钱培德等.一个基于Qt/Em bedded的嵌入式Linux应用程序的实现[J].计算机应用与软件.2006,(2):105-107.
[7][美]EZUST A,EZUST P.C++设计模式-基于Qt4开源跨平台开发框架[M].李仁见,战晓明译.北京:清华大学出版社,2007
[8]孙天泽,袁文菊,张海峰.嵌入式设计及Linux驱动开发指南[M].北京:电子工业出版社,2005.2.
[9]韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008.
[10]王亚军,刘金刚.Linux运用于嵌入式系统的技术分析[J].计算机应用研究,2005,(5):102-104.
Qt嵌入式软件 篇2
关键词:嵌入式Linux,ARM9,Qt/Embedded,智能控制器,嵌入式GUI
随着嵌入式系统的发展及市场的不断扩大,人们对嵌入式人机交互界面的需求越来越多,要求也越来越高。嵌入式系统或实时系统对图形用户界面(Graphical User Interface,GUI)的基本要求包括轻型、占用资源少、高性能、高可靠性以及可配置等特点,对嵌入式人机交互界面的设计是整个开发过程中必不可少的环节[1]。友好的人机界面往往决定了嵌入式产品能否成功打入市场,因此图形用户界面的开发是产品开发过程中最耗时的工作[2]。为此,笔者针对工业现场中一种通用嵌入式智能控制器,设计了一款具有通用控制功能的图形用户界面。
1 系统结构框架
控制系统由软件和硬件两部分组成(图1)。硬件是一个小型的智能控制器,它采用ARM嵌入式微处理器作为控制核心,将数据采集模块采集的数据进行处理,再将处理后的数据发送给数据输出模块,之间的数据发送与接收都是通过SPI总线模块完成的;显示和操作部分都可以通过图形化的界面在彩色液晶触摸屏上完成,同时为了能进行远程在线实时访问,该控制器还有GPRS模块,将数据发送给上位机。软件部分将采集来的数据进行处理,使用户可以根据实际现场需要配置各通道的数据,还可以对数据进行实时监测与显示,必要的话还可以添加GPRS模块及参数配置等。
2 开发过程
开发过程中所使用的硬件平台处理器是SANSUNG公司的16/32位的RISC微处理器S3C2440,它为手持设备和一般类型的应用提供了低价格、低功耗、高性能的解决方案[3]。数据采集和输出模块将现场采集的信号和数据通过整流、调理及隔离等处理转化成标准信号,再通过SPI总线传送给S3C2440,同时还带有一块七寸液晶显示屏和触摸屏,提高了系统的交互性。GPRS模块选用的是中兴的ME3000,它具有体积小、通讯可靠稳定、价格适中的优点;支持短消息业务,内嵌TCP/IP协议和标准的AT命令,通过AT命令进行语音和数据通讯[4]。控制器BIOS采用基于三星原来的bootloader之vivi改进而来的Surpervivi,移植了Linux-2.6.29的内核,交叉编译工具为arm-linux-gcc-4.1.2。
2.1 开发环境的建立
系统软件的开发采用的是目标机——宿主机的形式。首先在进行开发的宿主机(PC机)上建立Linux编译环境,然后根据目标机的硬件种类对Qt应用程序源码包进行定制,进而交叉编译生成相关函数库,最后制作根文件系统下载到目标板上。
小型智能控制器采用的是嵌入式Linux操作系统。该技术逐渐趋于成熟,系统的定制越发方便,可以支持更多平台,具有以下特点:精简的内核,适用于不同的CPU,支持多种体系结构;针对嵌入式的存储方案;用户可定制,可提供图形化的定制和配置工具;常用嵌入式芯片的驱动集,支持大量的周边硬件设备,驱动丰富[5]。Linux比较常见的版本有RedHat、Fedora、Ubuntu和SUSE Linux。在宿主机的VMware虚拟机上安装的是RedHat Enterprise Linux 5.1。由于系统要求良好的图形用户界面,因此需要一个强大的图形编程工具,综合考虑采用的是Qt。基本上,Qt 同 X Window 上的 Motif、Openwin、GTK 等图形界面库及 Windows 平台上的 MFC、OWL、VCL、ATL 属于同类型,但是 Qt 具有良好的跨平台特性、面向对象、丰富的API、支持2D/3D图像渲染以及大量的开发文档等优点[6]。是为嵌入式设备上的图形用户接口和应用开发而定制的C++开发包。
首先从网上下载免费的Qt/Embedded开发包,本系统采用的是Qt/E4.6.3版。将压缩包解压成3份,分别编译成PC版、嵌入式x86和嵌入式ARM。需要注意编译PC版和嵌入式x86之后要编译PC版中的qvfb,这里提到的qvfb是为Qt做的一个虚拟frambuffer的应用程序,它的最终目的就是把Qt应用程序运行的结果显示在qvfb上,避免了一些小的改动来回烧写根文件系统从而提高研发时的工作效率;由于本系统中有触摸屏,为了添加对触摸屏的支持,在编译嵌入式ARM版之前先编译tslib,版本为tslib1.4.tar.gz。对其环境变量进行设置并配置相关的库,在配置环境变量时,最好建立一个sh脚本,每次使用qt前运行脚本来设置环境变量,避免不同版本带来的冲突,方便不同环境时进行切换。接着,将宿主机生成lib下的库文件下载到目标机上,将 PC 机上/usr/local/Trolltech/QtEmbedded-4.6.3-arm/lib 中的库复制到目标机的 /usr/local/Trolltech/QtEmbedded-4.6.3-arm/lib(对应目录复制)上;将 PC 机上 /usr/local/tslib 中的库复制到目标机的 /usr/local上。至此开发环境建立完成。
2.2 控制界面的设计
准备工作顺利完成以后,就可以进行开发嵌入式GUI程序了。Qt/Embedded主要开发流程如图2所示。
Qt/Embedded编程既可以图形化编程也可以传统的代码编程,二者各有优劣,笔者采用二者相结合的方式编程:通过派生自QWidget的QMainWindow的子类化来实现主窗口的创建;图形的绘制是由子类化的QGraphicsPolygonItem来完成实现;工作区通过QGraphicsScene的子类化来完成,利用Qt所特有的信号和槽机制来实现响应相应的鼠标事件等。进入主窗口可以看到工具栏、菜单栏及工作区等,从功能上可分为3个单元:数据处理单元、数据显示单元和数据传输单元。数据处理单元包括3个模块:算数模块、逻辑模块和控制模块,其中算数模块用于实现数据运算,包括加、减、乘、除等数据运算;逻辑模块用于实现与、或、非、异或等逻辑控制功能;控制模块用于实现PID算法控制功能。用户可以将控制模块进行组态配置,完成数据运算、数据比较及控制算法等复杂的控制功能。数据显示单元主控制器将采集、控制的数据都存储在SQLite数据库中,该单元通过调用数据库的数据,可以实时显示各个通道的运行情况、控制方法及数据变化等,同时也可以查看历史数据,方便用户对现场的分析。数据传输单元主要是完成数据的无线发送,即GPRS模块,该模块是将处理后的数据或历史记录发送至上位机或者服务器,可以实现用户的远程在线实时访问,从而可以使该控制器做到无人值守。在控制界面中,有相应的功能供用户选择,同时可以对模块进行参数设置,完成数据的发送与接收功能。用户界面运行如图3所示。
2.3 程序的发布
将开发好的程序通过交叉编译工具编译成ARM可执行文件,再通过ARM目标板终端的rz命令将可执行文件下载到根文件系统的某个目录下,设置好相应的环境变量,便可以运行程序。为了给用户提供友好的人机界面,把程序再添加到QPE中,如果必要的话,还可以把程序设置成开机自启动,只要把程序的名字和路径添加到启动时的执行文件里即可。
3 结束语
笔者提出了一种基于ARM9的小型通用智能控制器的通用控制界面的设计方法,该GUI 通过跨平台由Qt/Embedded所开发,可移植性和可扩展性好,采用模块化设计,灵活性好,实时性高,能够满足人机交互的需求。
参考文献
[1]孙昌青.基于Qt_Embedded的嵌入式GUI系统的研究与构建[D].武汉:湖北工业大学,2009.
[2]孙天泽,袁文菊.嵌入式设计及Linux驱动开发指南——基于ARM9处理器[M].第2版.北京:电子工业出版社,2007.
[3]吴坤.基于S3C2440的平动式啮合电机驱动控制系统设计[D].北京:北京邮电大学,2010.
[4]吴晓云.基于ARMg和GPRS的电力负控管理系统的设计与实现[D].西安:长安大学,2010.
[5]孙鹤旭,林涛.嵌入式控制系统[M].北京:清华大学出版社,2006.
Qt嵌入式软件 篇3
由于嵌入式系统对实时性、可靠性要求较高,这就需要嵌入式图形用户界面(GUI)具有占用空间小、可裁减定制、运行速度快等特性。当前嵌入式GUI的实现方案有很多,诸如Microwindows、MiniGUI、Qt/Embedded等[1]。Microwindows的通用性好,多种平台都可以支持它,但其网络透明性不好,应用程序及说明文档较少。MiniGUI是国内做得较好的自由软件之一,主要运行于Linux控制台,结构小巧、移植性好[2]。星球科技(Qt)是当前Linux操作系统上最普遍的图形开发工具库,功能强大,具有很好的可移植性,能应用于目前绝大多数操作系统。Qt按照应用环境的不同,可以分为PC机环境的X11版本(qtx11)与嵌入式环境的Embedded版本(qte)。Qt与其他GUI实现方案相比具有面向对象、元对象编译器(MOC)、信号槽(signal-slot)通信机制、丰富的API函数等特点。Qte以原始Qt为基础,并做了许多调整以适用于嵌入式环境。它可以通过API与I/O设施直接交互,能够支持帧缓冲(Framebuffer)驱动,因此具有很高的运行效率[3,4]。
鉴于qte在可移植性、运行效率等方面的优势,本研究将其引入到嵌入式GUI开发方面的研究中来,并对编译平台搭建、交叉编译环境建立及Qt库文件裁剪的关键技术进行相关描述。
1 Linux环境下的Qt编译平台
本机搭建编译平台是开发嵌入式GUI的必要工作。X11环境可以模拟嵌入式系统的运行状态,并在PC机上查看程序的运行结果,但其生成的可执行代码不能在嵌入式环境下执行,需要搭建面向嵌入式系统具体要求的交叉编译环境。合理的开发路线是在X11环境下完成程序的编写、调试,在交叉环境下编译生成可执行代码,然后导入目标系统进行测试。
1.1 X11虚拟环境搭建
用于嵌入式开发的qte是不能单独编译运行的。在此之前,需要编译qtx11,生成用户界面编译器(UIC)与虚拟帧缓冲服务器(QVFB),作为交叉编译环境的支持。因此,要先编译X11版本,才能编译嵌入式版本,其操作过程如下(如图1所示):
(1) 解压Qt镜像压缩文件,将其安装在/usr/local目录下。之所以把Qt安装在这个目录下,因为系统头文件默认的路径为/usr/local。
(2) 修改环境变量,令QTDIR=MYM/usr/local/qtx11、PATH=MYMQTDIR/bin:MYMPATH、LD_LIBRARY_PATH=MYMQTDIR/lib:MYMLD_LIBRARY_PATH。在进行环境变量赋值时要格外仔细,尤其是修改PATH值的时候。如果出错,程序在编译连接过程中会因为找不到Qt的相关支持文件而不能通过,更严重的情况下可能会打乱操作系统的命令路径,给系统运行带来不便。
(3) 进入qtx11目录,键入/configure命令对Qt进行配置。
(4) Qt的自由版,默认状态不支持多线程,如果想建立带多线程支持的库,则需要配置完成以后,键入make命令进行编译,用来创建库文件,编译例程和指南。这需要等待一段比较长的时间,一般在一两个时左右(视编译的版本而定)。如果键入make sub-src命令,只编译库文件,用的时间会少一些。
(5) 将编译生成的uic与qvfb可执行文件复制到qte的bin目录下。
(6) 修改环境变量,令QTDIR=/usr/local/qte,因为另外两个环境变量是引用qt路径的,只要修改第1个环境变量就可以了。
(7) 进入qte目录,对qte做如下配置:./configure-embedded x86-shared-qvfb,然后进行编译。
1.2 交叉编译环境实现
本研究的交叉编译环境面向运行于先进精简指令机(ARM)环境下的嵌入式Linux操作系统,其实现过程如下(如图2所示):
(1) 安装ARM-linux工具链的相关镜像文件:arm-linux-knl、arm-linux-glibc、arm-linux-gcc、arm-linux-binuitls,然后令PATH=/usrlocal/arm-linux/bin:MYMPATH。
(2) 将前面编译生成的uic文件拷贝到qte/bin目录下,这时uic文件的颜色可能会变成灰色,失去了可执行文件的属性,需要恢复其可执行属性。
(3) 对qte进行配置:./configure-xplatform arm-linux-g++-shared-no-xft-no-qvfb-depths 16-system-libpng-system-libjpeg-system-zlib-vnc。
(4) 配置完成将会生成Makefile文件,就可以键入make命令进行编译了。编译成功以后交叉编译环境就搭建完成了。
1.3 Qt库的裁减
Qt库提供了很丰富的API函数,但一般的嵌入式GUI程序不会用到全部库函数,用到的只是其中的一部分,甚至是一小部分。因此完成存文档以后,就可以初步确定应该用到哪一些类,可以裁掉那些没有用处的类,以减小存储空间,提高程序的运行效率。
首先确定QT库准备裁掉哪些组件,不要的组件都要定义相应的关闭宏。MYM(QTDIR)/src/tools/qfeatuers.h文件定义了裁减时所有宏的嵌套关系。父宏开关若被定义,则相关的子宏开关都被定义。所以裁减时要明确有关宏的嵌套关系。MYM(QTDIR)/include/qconfig.h是Qt库编译时的配置文件,在其中定义的一些宏,定义了有关Qt组件是否参加编译。因为有关宏的形式都是类似于QT_NO_DIR,在qconfig.h文件中定义宏都是在裁掉有关的组件,而不是参加编译的组件。Qt库编译默认是最大库编译(约有7 MB),所有的裁减工作都是在这个基础上展开的(最小可以裁至630 KB)。编译裁减过的Qt库时,只需在configure命令之后用相应的qconfig.h文件覆盖本身的qconfig.h,再行编译即可。
2 qte应用程序开发
2.1 程序文件编写与Makefile修改
Qte源程序一般应该包含以下文件:1个主程序文件(main.cpp)、数个源程序文件(source.cpp)与对应的头文件(source.h)以及用来生成Makefile文件的项目文件(xx.pro)。
Qt提供了qmake工具用来生成Makefile文件,大大简化了编程过程。而qmake的使用则需要编写项目文件xx.pro以及设置相应环境变量。项目文件存放了一些系统的描述信息,语法为shell命令格式,用来生成Makefile文件。一般一个相对完整的项目文件主要包含以下内容:①TEMPLATE=app模板变量,告诉qmake为这个应用程序生成哪种Makefile;②DESTDIR=c:helloapp为放置可执行程序目标的目录;③HEADERS=source.haa.h….为头文件列表;④SOURCES=mian.cppsource.cppaa.cpp。...为源文件列表;⑤TARGET=xx为可执行应用程序的名称;⑥DEFINES=QT_DLL为额外的预处理程序定义的列表;⑦CONFIG=qt warn_on release为编译器选项和被连接的库。
按照以上格式内容编写xx.pro文件以后,键入qmake命令,在当前目录下就会生成名为Makefile的文件。项目文件也可以命令实现,用qmake-project命令也可以生成默认的xx.pro文件。
2.2 设置qmake的环境变量QMAKESPEC
qmake工具可以支持多种操作平台与处理器体系结构。只要对系统变量QMAKESPEC进行修改就可以生成适应多种平台的Makefile文件。QMAKESPEC系统变量用来表明操作系统和编译器,如果是X11的虚拟环境则将其赋值为linux-x86-g++;如果是arm环境则将其置为linux-arm-g++就可以了。若直接用命令来实现,可以在shell下输入下述命令:①X11虚拟环境(qmake-spec/usr/local/qte/mkspecks/qws/linux-x86-g++-o Makefile*.pro);②arm-linux交叉编译环境(qmake-spec/usr/local/qte/mkspecks/qws/linux-arm-g++-o Makefile*.pro)。
2.3 编译执行
以上操作完成以后,就可以键入make命令进行编译。编译成功以后则生成与项目文件xx.pro同名的可执行文件。X11虚拟环境下运行时首先需要运行qvfb,并设置相应的几何尺寸及色深(一般为16),然后另开一个终端在当前目录下键入./xx-qws(帧缓冲服务器)查看运行结果。
ARM交叉编译环境下生成的可执行文件是不可以在本机执行的,只有将其下到目标板中才能执行。由于MOC并不能处理所有的C++语法,在C++的某些语法规则与MOC产生冲突的时候会发生编译错误,主要问题是模板类无法使用singal与slot。有时编译会通过,在程序执行时出现段落错误,这时没有相应的错误提示信息,查找错误原因就比较困难了。
常见的的错误主要是由以下因素引起的:①多重继承时,Qobject类没有被首先继承;②多重继承时,虚函数作为slot;③signal与slot不能使用函数指针作参数和friend关键字;④signal与slot不能使用带参数的宏定义;⑤signal与slot不能使用默认参数以及模板类型的参数。
2.4 汉字显示实现
Qte提供了对汉字的良好支持,支持16位的unicode字符集。本研究通过不断的测试,解决了在嵌入式环境中汉字显示的问题。下面就实现的过程做简要描述。
建立一个头文件,其核心内容如下:
#ifdef QTX11_VERSION
#include <qtextcodec.h>
#define GB(s)
(QTextCodec::codecForName("GBK")
->toUnicode(s))
#define AGB(s)
(QTextCodec::codecForName("GBK")
->fromUnicode(s))
#else
#include <qgb18030codec.h>
#define GB(s)
(QGb18030Codec::codecForName("GB18030")->toUnicode(s))
#define AGB(s)
(QGb18030Codec::codecForName("GB18030")->fromUnicode(s))
#endif
然后在应用程序中引用此头文件,就可以实现汉字的显示了。例如实现一个名为“停止系统”的单选按钮:
showRadioButton1=
new QRadioButton(GB(tr("停止采集系统")),setButtonGroup1, "showRadioButton1");
当然还要把编译生成的相应的字库文件烧写到目标板中。Qt交叉编译完成以后,会在qte/lib/fonts目录下生成大量的扩展名为.qpf的字库文件。为了节省空间,并不需要把所有的字库文件烧写到目标板中,只要将unicode的相关字库unifont_160_50.qpf烧写到目标板中就可以了。
2.5 图片的支持
在嵌入式环境中图片的支持可以提高图形用户界面的美观性与质量。虽然本研究在配置qt的时候加入了对图片支持的选项,但是程序在目标板运行时经常会出错,解决的方法是将相关的图片支持库文件烧写到目标板中,然后安装就可以了[5,6]。例如安装图标支持库文件,将libpng3_1.2.8-r0_arm.ipk烧写到目标板,存放到任一目录中,然后用ipkg install libpng3_1.2.8-r0_arm.ipk命令进行安装就行了。
2.6 应用实例
根据以上研究成果,本研究以Intel-PXA255-Linux为目标系统,开发了面向以上嵌入式环境的GUI系统,并将其成功应用于嵌入式机械数据实时采集系统。如图3所示,GUI能够较好地显示汉字与图片,并具有很好的友好性与易用性;通过较完备的测试案例证明,其具有较快的反应速度与很好的可靠性。
3 结束语
本研究提出了一种基于qte的嵌入式GUI开发实现方法。对XII环境下进行模拟编译环境、交叉编译环境的实现进行了详细描述,针对具体的嵌入式系统要求,较好地解决了嵌入式环境下的汉字显示与图标显示问题。应用实例证明,利用该方法开发的GUI反应速度快、占用空间小,且具有较好的稳定性。
摘要:针对当前在嵌入式图形用户界面(GUI)开发中存在的运行效率偏低、可移植性较差等问题,提出了一种基于Qt/Embedded的嵌入式GUI实现方法。详细描述了GUI开发所必需的X11虚拟编译平台搭建技术与交叉编译环境实现技术。根据具体嵌入式目标对Qt库文件进行了裁剪,实现了对汉字与图片的显示,并通过应用实例证明了该方法的有效性。
关键词:嵌入式,图形用户界面,信号与槽,交叉编译
参考文献
[1]AHN S H,SUL D M,CHOI S C et al.Implementation ofLightweight Graphic Library Builder for Embedded System[C]//Proceedings of 8th International Conference AdvancedCommunication Technology,2006:166-168.
[2]于孝辉,陈秋艳,李国义.嵌入式Linux下MiniGUI的移植及软件开发[J].辽宁工学院学报,2006,26(2):90-93.
[3]DALHEIMER M K,HANSEN S.Embedded developmentwith Qt/Embedded[J].Dr.Dobb s Journal,2002,27(3):48-53.
[4]贾小军,谭召均,胡旭东.基于UML的复杂嵌入式系统建模研究[J].机电工程,2006,23(1):33-36.
[5]赵毅,游有鹏.基于Qt/Embedded的嵌入式数控系统人机界面设计与开发[J].工业控制计算机,2008,21(4):68-71.
Qt嵌入式软件 篇4
随着半导体技术的不断发展,嵌入式系统得到了越来越广泛的应用。在嵌入式系统的开发中,越来越多的软件开发工作集中在图形用户接口(GUI)上[1]。Qt/Embedded是一个专门为嵌入式系统设计图形用户界面的工具包,由挪威TrollTech公司开发。Qt/Embedded为C++构架,直接基于Linux中的Frame Buffer,可以运行在被Linux系统支持的多种不同的处理器体系上,例如:Intel X86,ARM,MIPS,PowerPC等。Qt/Embedded在小型化、低功耗、便携式的嵌入式系统中得到了广泛的应用。
使用Qt/Embedded开发应用程序时,开发者一般需要从QWidget、QDialog、QScrollView等类继承以实现用户窗口。而经常困扰开发者的是用户窗口的闪烁问题。本文将介绍Qt/Embedded的绘图机制,分析产生闪烁的原因并给出无闪烁绘图的方法。
2 Qt/Embedded绘图机制
在Qt/Embedded中使用QPainter类创建用户图形。QPainter可以在一个“绘图设备”上进行绘制图形,例如窗口或者位图等[2]。为了避免干扰Qt/Embedded自己的画图功能,使用QPainter创建用户图形时需要将画图代码放在paintEvent()的画图事件函数中,并且用QPainter::begin()和QPainter::end()函数来启动和停止画图。QPainter类提供了低级的画图函数,例如画线,画矩形等。QPainter类还提供了许多函数用来在实际绘图之前设置绘图样式,例如使用QPainter::setPen()函数设置画笔的样式,使用QPainter::setBrush()函数设置填充样式等。在许多情况下,系统会自动产生一个绘图事件,并且paintEvent()被调用,例如一个窗口第一次显示或者大小被调整等。开发者也可以通过调用QWidget::repaint()或QWidget::update()来强制产生一个绘图事件,从而调用paintEvent()来实现用户图形的刷新。repaint()和update()两个函数的区别在于,前者会产生一个立刻的重新绘制,而后者只是向Qt主事件回路中插入一个绘图事件,等待Qt下一个主事件回路执行。连续调用update()时,Qt会将多个绘图事件优化为一个绘图事件以避免闪烁。调用repai(bool erase),如果erase为TRUE,Qt在paintEvent()调用之前先擦除绘图区域;否则不擦除。
3 闪烁的原因分析
当Qt产生一个绘图事件来刷新图形时,Qt首先用背景颜色来擦除绘图区域,然后在背景上绘制图形。这种分两步绘图的方法是很方便的,这样开发者就可以简单地在窗口上绘制需要的图形而不用关心其他的像素。但这种分两步绘图的方法也是产生闪烁的主要原因。这种刷新方法给人的视觉感受是,先看到擦除绘图区域之后的背景颜色,然后看到背景上的绘图,这之间有一个短暂的时间差。如果这样的刷新频繁发生,人眼就能感受到明显的闪烁。
许多情况下,Qt会产生绘图事件,例如移动重叠的窗口,新显现的窗口部分需要重绘;调整窗口的大小;程序调用update()或者repaint()等。每当窗口的大小改变时,系统就会产生一个绘图事件,刷新背景然后重新绘制所有图形,从而导致闪烁。如果窗口大小改变,窗口中的内容也随之改变,则称窗口内容为“动态的”;如果窗口大小改变,其内容不改变,则称之为“静态的”。例如常用的文字处理工具,窗口内容与窗口大小无关,并不随着窗口大小的改变而改变。这种情况下,既然原有的可见部分并不改变,就没有必要重新绘制,而只需绘制新显示的部分。因此通过QWidget::setWFlags()将窗口部件标记设置为WStaticContents可以避免闪烁。
对于那些窗口内容与窗口大小相互独立的窗口,可以通过设置窗口部件标记为WStaticContents来避免闪烁,但这类窗口毕竟是少数。下面介绍两种更为常用和有效的方法来避免闪烁,即部分刷新和双缓冲技术。
4 无闪烁绘图方法
不管窗口内容是静态的还是动态的,许多情况下我们还是要重新绘制窗口的一部分,而这些绘图仍然可能导致闪烁。Qt刷新时先用背景色填充背景,然后绘图事件负责绘制用户图形。如果绘图事件比较慢,例如绘图之前要先进行大量的计算,那么绘制背景和绘制用户图形之间的延迟就比较大,从而导致闪烁;延迟越大,闪烁就越明显。解决问题的根本方法就是我们自己负责擦除背景,并尽可能地减少擦除背景和绘图之间的时间差。
通过QWidget::setWFlags()将窗口部件标记设置为WRepaintNoErase或WResizeNoErase,或者调用repaint(FALSE),可以让Qt在绘图之前不擦除背景。
4.1 部分刷新
程序员自己负责背景的刷新,就可以在擦除背景和绘制图形之前做必要的计算,而不是在擦除背景和绘制图形之间进行计算,从而避免了闪烁。但这样做仍然存在一个问题。
例如如下的绘图:绘制整个背景,绘制线条1,绘制线条2,绘制线条3,…,绘制线条n。设绘制一条线条的时间为t,那么绘制整个背景和绘制线条1之间的延迟就是1×t,这个延迟是很小的,所以当绘制线条1时基本上没有闪烁。而绘制整个背景和绘制线条n之间的延迟为n×t,如果n很大,这个延迟就比1×t大多了,有可能造成闪烁。
解决这一问题的方法是部分刷新,简而言之,就是先绘制部分背景,然后绘制相应部分的图形,再绘制部分背景,接着绘制相应部分的图形,如此反复。如此将背景分为多个部分,然后部分刷新,而不是一下子绘制整个背景。应用到上述例子中,绘图操作为:绘制线条1的背景,绘制线条1,绘制线条2的背景,绘制线条2,…,绘制线条n的背景,绘制线条n,绘制剩余背景。这就使得绘制线条与绘制相应背景的延迟为固定的1×t,可以明显地减少闪烁。需要注意的是,使用部分刷新,需要独立地绘制剩余背景,因为绘制的线条可能没有覆盖整个窗口。
当绘制部分图形的时间t比较短时,部分刷新可以很好地解决闪烁问题。但是如果绘制部分图形的时间t比较长,可能仍会造成闪烁。解决这一问题的方法是将用户图形分解成适当小的部分,每次只刷新很小的部分,但这种方法有时会很复杂,导致编程的难度很大。一个更好的解决方法是双缓冲技术。
4.2 双缓冲技术
双缓冲技术就是在内存中开辟一块缓冲区,将这块缓冲区看作一幅位图,先用背景色填充这幅位图,然后在这幅位图上绘制用户图形,最后将这幅位图显示到窗口中。这样绘制背景和绘制图形之间就没有延迟,可以完全避免闪烁。使用双缓冲技术的简便方法是,先用QPixmap制作一幅位图pixmap,该幅位图与需要刷新的矩形区域大小一致,然后用pixmap.fill()填充位图的背景色,接着用QPainter p(&pixmap)申请一个指向该位图的画笔,并在这幅位图上绘制用户图形,最后用bitBlt()或者p.drawPixmap()将这幅位图填充到窗口。
双缓冲技术可以完全消除闪烁,但是以内存消耗和时间开销为代价。例如,在每一个绘图事件中需要分配(宽×高×位深)比特的内存空间,如果系统使用640×480液晶显示器,位深为16-bpp(每个像素16比特),那么需要分配的内存空间就是680×480×16比特,即600K字节。虽然可以重复利用分配的内存空间以减少分配内存的时间开销,但分配的内存应该为可能需要刷新区域的最大值,内存消耗比较多。解决这一问题的有效方法是将部分刷新和双缓存技术结合起来使用。例如分配线条大小的内存空间作为位图,而不是整个窗口大小,然后在位图上绘制线条的背景和线条,接着复制这幅位图到相应的线条位置。这样需要分配的内存大小为(线条宽度×线条高度×位深)比特,远小于整个窗口所需内存。
需要注意的是,使用双缓冲技术时应该禁止Qt在绘图事件之前擦除背景,可以调用repaint(FALSE)产生绘图事件。
5 直接访问帧缓冲
双缓冲技术可以完全消除闪烁,但其内存消耗和时间开销比较大。尤其对于嵌入式实时系统,双缓冲的时间开销有时无法满足实时性要求。下面讨论一种直接访问帧缓冲的方法,并运用部分刷新,实现快速无闪烁画图。
5.1 帧缓冲
帧缓冲(Frame Buffer)是在Linux内核架构版本2.2以后推出的标准显示设备驱动接口,是显存抽象后的一种设备。帧缓冲设备对应的设备文件为/dev/fb*,而/dev/fb为当前缺省的帧缓冲设备,通常指向/dev/fb0。
帧缓冲设备驱动模块运行在所谓的内核空间里,而应用程序运行在所谓的用户空间中[3]。帧缓冲允许上层应用程序不用关心显存的工作细节而直接对显示缓冲区进行读写操作,写操作可以立即反映在LCD屏上。Frame Buffer的显示缓冲区位于Linux中的内核空间,用户程序需要通过mmap()函数将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址,之后用户程序就可以通过读写这段虚拟地址访问屏幕缓冲区。直接访问帧缓冲,对显示缓冲区进行写操作,是一种最快的显示方式。
5.2 QDir2 QDirectPainter类
Qt/Embedded直接基于Linux中的Frame Buffer。QDirectPainter类继承自QPainter类,提供了直接访问帧缓冲的方法,该类仅可在Qt/Embedded中使用[4]。QDirectPainter类的uchar*frameBuffer()函数返回指向屏幕缓冲区首地址的指针,int depth()const函数返回显示的位深,int width()const函数和int height()const函数分别返回显示的宽度和高度。例如系统使用640×480液晶显示器,位深为16-bpp(每个像素16比特),则由QDirectPainter类获得的位深为16,宽为640,高为480。
由QDirectPainter类uchar*frameBuffer()函数获得指向屏幕缓冲区首地址的指针后,就可以直接对屏幕缓冲区进行写操作,并立即反映到LCD屏上。设LCD屏上坐标为(x,y)的像素点表示该点到LCD屏左方水平距离为x,到LCD屏上方垂直距离为y;系统的位深为16-bpp,且R:G:B为5:6:5,即一个16位数据的高五位表示红色,中间六位表示绿色,低五位表示蓝色。将坐标为(x,y)的像素点刷新为某一颜色的操作就是:*(fb+width*y+x)=color;其中fb为指向屏幕缓冲区首地址的指针,由于位深为16-bpp,所以fb为指向unsigned short int型的指针;width为屏幕宽度;color为表示颜色的16位无符号数据。这就是直接访问帧缓冲的画点函数。有了画点函数后,就可以编写出画线,画矩形等其他函数。
5.3 快速无闪烁画图
笔者参与的某项目使用640×480的LCD屏,位深为16-bpp;系统在每20ms内响应一帧数据,绘图区域为620×400。需要实时绘制的图形为检测的回波波形和刻度线等,如图2所示。由于20ms的实时性要求和绘图区域比较大,使用QPainter直接画图虽然可以满足实时性要求,但有明显的闪烁;使用双缓冲画图,可以消除闪烁,但时间远大于20ms,无法满足实时性要求。
为了快速无闪烁画图,笔者采用了直接访问帧缓冲和部分刷新。直接访问帧缓冲可以获得最快的画图速度,但也要自己负责绘图区域每个像素点的刷新。为了避免闪烁,实时刷新函数在绘制完一帧图形后,将其数据保存。当另一帧数据到达时,先用上一帧数据部分刷新背景,然后部分绘制新一帧图形,即只刷新上一帧图形的某一列,然后用新一帧数据绘制该一列,如此反复。使用直接访问帧缓冲和部分刷新,虽然增加了一些编程复杂度,但可以满足系统的实时性要求并避免闪烁。经过实际测试,系统运行良好,实时绘图时间小于13ms,满足实时性要求,且没有闪烁。
6 结束语
在嵌入式系统的开发中,软件开发工作主要集中在图形用户接口上。Qt/Embedded以其丰富的类库,完善的功能和良好的接口在嵌入式系统中得到了广泛的应用。在Qt/Embedded应用程序开发过程中,经常困扰开发者的是用户窗口的闪烁问题。本文介绍了Qt/Embedded的绘图机制,分析了绘图时产生闪烁的原因,并给出无闪烁绘图的方法。
在嵌入式系统中,系统通常有实时性要求。为了满足实时性要求,必须提高绘图速度。本文讨论了一种利用QDirectPainter类直接访问帧缓冲的绘图方法,并利用部分刷新,实现快速无闪烁绘图。
摘要:首先对Qt/Embedded的绘图机制进行了介绍,然后分析了绘图时产生闪烁的原因,给出无闪烁绘图的方法。为了提高绘图速度,对一种利用QDirectPainter直接访问帧缓冲的绘图方法进行了讨论,实现了快速无闪烁绘图。
关键词:Qt/Embedded,无闪烁,双缓冲,QDirectPainter,嵌入式Linux
参考文献
[1]孙天泽,袁文菊,张海峰.嵌入式设计及Linux驱动开发指南――基于ARM9处理器[M].北京:电子工业出版社,2005.
[2]Blanchette J,Summerfield M.C++GUI Programming with Qt3[M].Prentice Hall PTR,2004.
[3]Corbet J,Rubini A,Hartman G K.Linux Device Drivers[M].3rd ed.南京:东南大学出版社,2005.
[4]Qt参考文档[EB/OL].http://www.qiliang.net/qt/index.html.
Qt嵌入式软件 篇5
数据库几乎是每个较大的软件所必须应用的, 在嵌入式设备中, 由于可使用的资源很有限, 这就要求使用的数据库安装后占用的文件系统的空间要少, 而且所使用其他资源也有很大限制, 这也与开发者使用的数据库有很大冲突。SQLITE是Qt提供的一种进程内数据库, 小巧灵活, 无须额外安装配置且支持大部分ANSI SQL92标准, 是一个轻量级的数据库。Qt为数据库访问提供的Qt Sql模块实现了数据库和Qt应用程序的无缝集成, 同时为开发者提供了一套与平台无关和具体所用数据库均无关的调用接口。这使得开发者只需掌握基本的SQL语句, 就能进行简单的数据库应用程序开发。
一、Qt 中数据库
Qt中使用QtS ql模块实现了对数据库的完美。Qt Sql模块由驱动层 (实现了特定数据库与SQL接口的底层桥接) 、SQL接口层 (提供了数据库类的访问) 和用户接口层 (提供从数据库数据到用于数据库表示的窗体的映射) 3部分组成, 各部分由不同的Qt类支撑。Qt Sql模块为不同层次的用户提供了丰富的数据库操作类, 只要熟悉这些类的结构和功能, 就可以方便使用, 同时还支撑常用的数据库模式, 如主从视图和上下钻取等模式。
Qt Sql模块使用驱动插件 (driver plugings) 与不同的数据库接口通信。由于Qt中的SQL模块的应用程序接口与具体数据库无关, 因此所有与数据库相关的代码均包含在这些驱动插件中。配置Qt时, 可以选择将SQL驱动内置于Qt中或编译成插件。
二、Qt 中数据操作
1、连接数据库
在进行数据库操作前, 必须建立与数据库的连接。Qt提供了QSql Database类完成连接, 连接过程需要指定驱动器、连接名、主机名、数据库名、用户名和密码, 然后使用open函数打开连接。同时, 在使用数据库时, 在Qt工程环境中需要进行相关的配置。具体配置如下:
(1) 环境配置:如果想要使用Qt Sql模块, 则必须对工程进行配置:
1在工程文件上加入一行:QT+=sql
2在头文件中加入语句:#include<QtSql/QtSql>
(2) 本地数据库查询:通过以下语句:
QStringL ist drivers=QSqlD atabase::drivers () ;
q Debug () <<drivers;命令查看Qt中包含的数据库
QSql Database db=QSql Database::add Database ("QSQLITE") ;
q Debug () <<"driver valid?"<<db.is Valid () ;相关的驱动是否有效。
查看结果如下所示:
(3) 数据库连接:
数据库连接由任意字符串表示, 如果没有指定连接的情况下, QSql Database可以提供默认的连接供Qt其他的SQL类使用。建立数据库连接的语句如下:
数据库连接成功如图所示:
2、数据库遍历操作
Qt中仍然支持常用数据库操作的SQL语句。在Qt中, QtSql模块中的QSql Query类提供类一个执行SQL语句的接口, 并可以遍历执行的返回结果集。如果不使用SQL语句进行数据库操作, 可以利用QSqlQ ueryM odel和QSqlT able Model类等进行数据库操作, 而且可以将结果在表格中显示出来。
(1) 使用SQL语句操作数据库
数据库连接成功后, 首先要创建数据库表, 利用SQL语句操作:
QSql Query query
query.exec ("create table information (id int primary key, ""name varchar (20) " "sex varchar (10) ") ;
然后向表中插入记录, 利用SQL语句操作:
query.exec ("insert into information values (0, 'Jhon', ’man’) ") ;
query.exec ("insert into information values (0, 'Alic', ’woman’) ") ;
最后, 对数据库表进行遍历操作, 利用SQL语句, 如插入记录、显示表记录、查询、定位等。
(1) 插入一条记录
query.prepare ("insert into information (id, name, sex) ""values (?, ?, ?) ") ;
query.bind Value (0, 5) ;
query.bind Value (1, "Lin") ;
query.bind Value (2, "woman") ;
(2) 显示全部记录
query.exec ("select * from information") ;
while (query.next () ) {
q Debug () <<"row Num:"<<query.at () <<"id:"<<query.value (0) .toI nt () <<"name:"<<q uery.value (1) .to String () <<"sex:"<<query.value (2) .to String () ;}
(3) 查询定位第二条记录
if (query.seek (2) ) {
q Debug () <<"row Num:"<<query.at () <<"id:"<<query.value (0) .toI nt () <<"name:"<<query.value (1) .to String () <<"sex:"<<query.value (2) .to String () ;
(4) 最后一条记录
if (query.last () ) {
q Debug () <<"row Num:"<<query.at () <<"id:"<<query.value (0) .toI nt () <<"name:"<<query.value (1) .to String () <<"sex:"<<query.value (2) .to String () ; }
运行结果如图所示:
(1) Qt类机制操作数据库
Qt中使用了自己的机制来避免使用SQL语句, 提供了更简单的数据库操作和数据显示模型。分别是只读的QSql QueryModel, 操作单表的QSqlT able Model和以及可以支持外键的QSqlR elationalT ableM odel。QSqlQ uery Model类为SQL的结果集提供了一个只读的数据模型。
(1) 利用QSqlQ uery Model类对数据操作
1在窗口中显示表数据操作
具体操作步骤:首先新建QSqlQ uery Model类对象modelQuery, 并利用SQL语句查询整个information表的内容;然后设置了表中属性显示时的名字;最后建立了一个视图view, 并将这个model模型关联到视图中, 这样数据库中的数据就能在窗口上的表中显示出来了。操作代码如下所示:
运行结果如图所示:
2表数据操作
包括显示表数据中行列数、显示一条记录、插入记录等操作。
运行结果如下所示:
QSqlQ uery Model这个类模型默认是只读的, 所以在窗口上并不能对表格中的内容进行修改。要想使其可读写, 需要自己的类继承自QSqlQ ueryM odel, 并且重写set Data () 和flags () 两个函数。如果我们要改变数据的显示, 就要重写data () 函数。或者利用QSqlT able Model类对数据进行操作。
(2) 利用QSqlT able Model类对数据库操作
QSql Table Model *model=new QSql Table Model (this) ;
model->set Table ("information") ;// 添加表
model->set Edit Strategy (QSql Table Model::On Manual Submit) ;// 提交模式, 手动操作
model->select () ;// 选择数据表
table View->set Model (model) ;// 在QTable View类对象中显示
QSqlR elationalT ableM odel与QSqlT able Model没有太大 区别, 该类为单张的数据库表提供了一个可编辑的数据模型, 它支持外键。
三、Qt 数据库综合应用
按照上述描述方法设计数据库程序, 在Qt进行数据连接, 然后创建数据库表, 在利用Qt中QSqlT able Model类模型对数据库进行增加、删除、提交数据库、撤销、排序及查询等操作。操作界面如所示:
(1) 增、删、提交更新操作
(2) 排序操作
(3) 查询和恢复查询操作
最后, 将Qt移植到开发板上, 配置交叉环境及编译器arm_linux_gcc, 然后将应用程序通过交叉编译器编译, 再将交叉编译后生成的可执行文件移植到开发板上, 这样开发的应用程序可以在开发平台上启动运行。
四、总结
针对嵌入式系统下的数据库设计问题, 利用Qt设计界面, 然后采用Qt提供的Qt Sql模块实现了数据库的设计。利用QSqlD atabase实现数据库连接, QSql Query实现数据库表的创建和添加记录, QTableM odel进行数据表的操作, QTable View实现数据库表的显示, 最后实现嵌入式下的数据库开发与设计。
参考文献
[1]张治国, 董西广.基于Qt平台的数据库编程[J].福建电脑, 2011: (3) :165-167.
[2]王栋财, 梁隆恺, 韩改宁等.基于嵌入式媒体播放器的设计与开发[J].软件工程师.2014:17 (6) 17-18.
[3]Jasmin Blanchette, Mark Summerfield.C++GUI Programming with Qt4[M].Prentice Hall, June, 2006.
Qt嵌入式软件 篇6
随着计算机与视频技术的发展,人们已经可以用摄像装置拍摄自己感兴趣的图像并保存、传输,比如在家庭、办公室、停车场等场所安装的视频监控系统。这些场所安装的监控系统一般要求成本低廉、具有视频存储和传输功能。使用嵌入式系统,可以实现上述目的。不过当前的很多嵌入式视频监控系统是基于GSPCA[1]的系统。GSPCA是法国人编写的Linux视频驱动程序包,支持不少摄像头,也提供了像Spacview之类的视频录制与传输程序。但基于GSPCA软件包构建的监控系统有以下缺陷:首先,GSPCA的图像必须先经过网络传到PC机上才能显示的,如果在嵌入式系统的显示屏上本身反而不能直接显示;第二,GSPCA的图像处理功能并不丰富,不能提供移动检测等功能;第三,GSPCA的图像格式只有MJPEG形式,等于每帧图像都要存储;这样的存储量过大,而如果使用MPEG格式,由于使用帧间压缩,可以节省大量存储空间;第四,缺乏移动侦测功能,因为通常视频如果完全存储下来即便使用MPEG格式也会占据很大的存储空间;如果加入了移动检测功能,在检测到物体运动后再存储视频,就可以大大节省视频文件占据的存储容量;第五,GSPCA所提供的操作界面基本是自己编写的,非常简陋,较之主流的图形化界面库而言,缺乏对于后续开发的良好支撑,这一点严重阻碍了基于GSPCA产品的商业应用。另外,还有以下几点:首先,随着触摸屏技术的快速发展,目前触摸屏的成本已经很低,完全可以把触摸屏应用于监控系统的启动、管理和关闭,这样可以非常方便使用者。其次,如果用户不在现场,此监控系统还应该具备把视频文件通过网络发送给用户的能力。综上所述,在充分考虑后,基于嵌入式技术,开发出了一种成本适中、使用触摸屏、具有视频存储、移动检测和传输功能的视频监控系统。该系统可以独立应用于家庭中的实时监控,也可以用于办公室、车场或和其他大型监控系统集成以执行大范围的监控任务。
1 总体结构
监控系统由数字摄像设备和视频监控终端组成。结构如图1所示。数字摄像设备提供原始图像数据,视频监控终端对图像数据进行处理,数字摄像设备与视频监控终端的视频数据接口相连。监控终端包括管理模块、录制与检测模块、显示模块、触摸屏模块、通信模块。其中管理模块具备系统管理功能,例如报警级别的设置;录制与检测模块完成图像数据压缩、视频录制、差异检测与报警任务;显示模块显示当前实拍的图像或按照不同速率播放录制的视频;触摸屏模块提供触摸输入并传递给管理模块、录制与检测模块和显示模块的功能;通信模块可通过有线或无线方式传输报警信号和视频文件,可以加密传输的数据。
本系统由软件和硬件部分构成。硬件部分由TQ2440开发板和USB摄像头构成。其中TQ2440开发板[2]上包括基于ARM9体系的s3c2410/2440CPU、32 MB内存、32 MB闪存、320×240点阵彩色液晶触摸屏、USB口和以太网口。USB摄像头为中星微ZC301摄像头,支持常见的V4L协议。软件部分包括linux操作系统(内核2.6)、Qt4图形中间件、OpenCV2.0库和自主开发的监控软件。Linux操作系统(内核2.6)具备强大的多进程处理能力、出色的稳定性和良好的扩展性,易于安装各种应用软件和函数库。Qt4图形中间件具有丰富的图形化工具库,OpenCV2.0有强大的图像处理能力。图2为软件系统的架构图。
2 管理模块设计及实现
管理模块功能包含了摄像启动、播放启动、系统设置和系统退出功能。下图为管理界面。管理模块的开发主要是基于Qt4进行的。Qt是一个多平台的C++图形用户界面应用程序框架,属于诺基亚,现在发展到Qt4[3]。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的因此很容易扩展,并且允许真正的组件编程。自从1996年早些时候Qt进入商业领域,它已经成为全世界范围内数千种成功的应用程序的基础,Qt不仅是流行的Linux[4]桌面环境KDE的基础,近年来越来越多的智能化仪表[5]、虚拟仪表[6]也开始采用Qt作为基本的图形化操作界面。
管理模块的主要工作流程是这样的:用户开启系统后即进入主控菜单;在菜单中,选择播放视频、修改设置或摄像;如果是摄像,实时采集图像并提示用户选择图像保存方式究竟是比较节约空间的移动检测方式还是常规方式;用户选择后开始录制;当系统检测到物体移动时将保存当前图像;系统通过网络发送出图像文件;系统结束录制,返回主控菜单;如果是播放,打开当前目录,用户可挑选需要查看的视频文件;选中视频文件后开始播放视频,用户可选择播放视频的速度;系统结束播放,返回主控菜单;如果是修改设置,则调整所需的系统属性,例如背景图案;保存修改的系统属性到设置文件里;设置结束,返回主控菜单;用户关闭系统退出。
管理模块的主要流程如图3所示。
管理模块的部分代码如下:
3 录制与检测模块设计及实现
录制与检测模块功能分成按常规拍摄和移动侦测拍摄两种。后一种拍摄条件的每秒帧数低于常规拍摄,主要是考虑一些用户可能希望长时间监视某个区域,这时若使用常规节奏拍摄就要耗费大量存储空间,而使用移动侦测可大大节省存储空间。
该模块使用了OpenCV函数库,OpenCV[7]是开放源代码的计算机视觉类库,由英特尔公司位于俄罗斯的研究实验室所开发,它是可免费获得的由一些C函数和C++类所组成的库,用来实现常用的图像处理及计算机视觉算法,已广泛运用于人脸识别[8]、目标运动检测[9]、图像处理[10]等领域。选用它有两个原因:首先,OpenCV的图像处理功能相当强大,不仅能处理图像的格式、提供了提供移动检测等功能;其次,OpenCV产生的视频文件可以根据需要选择MPEG4,MJPEG等多种压缩格式,从压缩机理上看,MPEG4算法由于采用插值与帧间预测,不需要压缩每帧图像,压缩效果显然好得多。综合上述因素,选用了OpenCV。
模块接收来自摄像头的图像数据。本模块启动后会调用函数cvCreateCameraCapture检测摄像头是否连接,如果检测到摄像头则得到一个指针,否则会报错退出。之后的工作流程是:先调用cvQueryFrame操作此指针,再调用函数cvCreateVideoWriter指定视频压缩格式并获得视频文件指针。这样可得到一个视频缓冲区A,然后该缓冲区接收从USB摄像头提取的图像数据,如果没有移动检测,则该缓冲区的数据将按照选定的视频压缩格式以调用函数cvWriteFrame的方式被写入视频文件。如果有移动检测,则调用函数motionDetect。该函数的功能如下:将A缓冲区的数据被保存到另外的缓冲区B里等待比较操作,A缓冲区继续接收来自摄像头的数据,A与B的数据在经过相关二值化和降噪处理后进行比较,如果比较中发现数据的不同之处已经超过预设的门限值,则把拍摄时间叠加入B缓冲区的视频数据。此处的视频数据记录以调用cvWriteFrame的方式被写入本地视频文件。本地视频文件的命名是按照数字升序自动产生的,因此不会覆盖之前拍摄的视频。操作过程如图4所示。
录制与检测模块的部分代码如下:
此外,当前后帧差异检测的结果达到或超过了预设的报警门限,不仅可录入到本地视频文件,还可发出报警信号;同时还会将画面再记录入一个很短的临时视频文件中(例如长度为10 s),并将这个临时视频文件连同报警信号提交给通信模块。该临时视频文件在记录时每幅图像都可加入年-月-日-时-分-秒格式的时间戳。临时视频文件的长度可以预先设置,该文件在传输后即被删除以节省装置的存储空间。采用这种方式出于3种考虑:首先,自动发出的报警信息可以满足迅速报警的需要,随后发出的短长度临时视频文件可以提供具体的现场图像信息;其次,上述数据量较之在网络上传输整个的视频文件可明显降低通信带宽,节省运行成本;最后,由于传输的过程耗时短,数据被截获的概率低,安全性也有所提高。当用户从管理界面选择了录制功能后,屏幕上将全屏显示出当前采集的图像。并在屏幕的偏下位置显示出一组半透明的按钮:“录像”、“返回”和“节约/正常”。这是考虑到用户可能需要随时调整拍摄模式或停止摄像、暂停录制:点按了“录像”按钮后液晶屏上的图像会被记录入视频文件;点按“返回”后会中止录制返回上级菜单;点按“节约”按钮之后,系统仅仅在记录到物体移动时才记录视频文件,且该按钮上的字符变为“正常”,这时若再点按该按钮,系统将按照常规速度记录视频文件,不再根据是否有物体移动记录视频。图5为录制与检测模块工作时的界面显示。
4 显示模块设计及实现
显示模块有两种工作模式:一种是本地实时监视模式;另一种是视频回放模式。在本地监视模式下,本模块启动后也会检测与摄像头是否连接,如果没有检测到摄像头则会报错退出。检测通过后,来自摄像头的图像被实时显示在彩色液晶屏上。而且操作界面设计成使用户可以在观看监视画面的同时能够随时开始录制视频文件或结束录制,录制视频期间液晶屏实时显示的内容不受录制操作的任何影响。在视频回放模式下,用户可以在图形化菜单中选择以前记录的视频文件并播放,播放的画面显示在液晶屏上,播放时可以根据用户需要随时调整播放速度的快慢,也可以随时暂停播放。
显示模块综合使用了Qt4和OpenCV的库函数。播放过程如下:通过Qt4提供的文件接口函数在制定路径下找到要播放的视频文件。在打开视频文件前先开辟一个内存缓冲区C,将读出的视频数据写入到此缓冲区内。通过在PaintEvent函数中调用函数drawImage将时间戳等字符数据写入到视频缓冲区C内,这一步是实现在Qt4界面内显示图像所必须的步骤。在这一步中还可以根据需要叠加控制按钮到显示画面中。然后C缓冲区的合成视频数据再写入到操作系统的帧缓冲区内,过程如图6所示。在Qt中设置好每秒写入帧缓冲区25帧画面,用户就可以从液晶屏上看到连续运动的图像了。实时显示的过程与播放过程很相似,不同之处是图像数据的来源从视频文件变成了USB摄像头。
打开视频文件及建立缓冲区C的部分代码如下:
5 通信模块设计
通信模块使用了socket函数,通过线程机制独立于其他程序运行。模块分成初始化和传输两部分。在摄像模块分配视频缓冲区之后就初始化通信模块。初始化过程首先以函数pthread_create启动了一个独立的线程,该线程调用cvCreateVideoWriter获取被传输视频文件指针,待函数正确返回指针后再建立socket连接,至此初始化过程结束。当摄像模块检测到物体移动后,调用cvWriteFrame在抓取的帧图像中打上时间戳并将其存储为临时视频文件,随后向远端服务器发送连接请求,连接建立后,通过TCP连接传送该文件。在传输结束后再等待一段时间后删除临时文件;之后释放视频文件指针,释放socket连接,最后注销线程。
通信模块的部分代码如下:
6 结语
经过测试,证明嵌入式家用视频监控系统达到了预期的功能:既可以按照普通速率录制视频并实时显示在液晶屏上,也可以通过移动检测方式,只记录变化较大的图像;可以通过图形化界面,以触摸方式选择实时录制视频或者查看以前录制的视频。在移动检测方式下,可以报警并将图像通过网络发送给远端服务器。
后续的开发包括:加强移动侦测处理能力,做到能够识别某些特征物;加入镜头移动功能,增大监视范围;增添移动互联网接口,利用手机查看视频文件;增加视频记录格式,支持更多文件格式;丰富图形化界面功能,增添报时、对讲、夜光等功能。
摘要:当前有不少视频监控系统是基于GSPCA开发的,它们存在不能在本地显示视频,缺乏移动检测等图像处理功能,对于存储空间要求高,难于升级等缺点。为解决上述问题,结合Qt4和OpenCV开发了一种嵌入式视频监控系统。该系统的硬件环境为ARM9系统,操作系统为Linux。系统不仅能够在本地实时显示监视画面,还能够根据移动检测的结果记录视频,大大节省了存储空间。系统还可以在上述检测中加入与预设报警门限值进行比较的功能,根据比较结果决定是否报警并通过网络将拍摄的图像传递给远端系统。达到了在本地显示视频,节约存储空间,可进行移动检测,便于升级的效果。
关键词:嵌入式视频监控系统,移动检测,Qt,OpenCV
参考文献
[1]Linweig.GSPCA驱动移植介绍[OL].[2010-02-10].http://blog.csdn.net/linweig/article/details/5305334.
[2]广州天嵌计算机科技有限公司.TQ2440开发板使用手册[R].广州:天嵌计算机科技有限公司,2009.
[3]成洁,卢紫毅.Linux窗口程序设计:Qt4精彩实例分析[M].北京:清华大学出版社,2008.
[4]陈莉君.Linux操作系统内核分析[M].北京:人民邮电出版社,2000.
[5]陈卿,戴仙金,唐玉国.基于Qt/Embedded的新生儿监护仪软件系统设计与实现[J].微计算机信息,2012,28(9):431-432.
[6]王润民,赵祥模,惠飞,等.基于嵌入式Linux与QT的汽车虚拟仪表设计[J].现代电子技术,2012,35(6):1-4.
[7]BRADSKI Gary,KAEHLER Adrian.Leanring OpenCV[M].United States:O'Reilly Media,Inc.,2008.
[8]刘静.基于OpenCV机器视觉库的人脸图像预处理方法研究与实现[J].电子设计工程,2012,20(16):186-187.
[9]刘馨,马宏峰,王宏斌.基于OpenCV和DirectShow的交通运动目标检测算法研究[J].华东交通大学学报,2012,29(3):21-25.
Qt嵌入式软件 篇7
随着嵌入式处理器运算能力的不断提高, 对外设支持的不断丰富, 嵌入式Linux系统的应用也逐渐增多。与其它GUI相比, QT/E可以直接访问底层设备, 速度非常快, 使得QT/E成为用于运行基于QT的程序的最紧凑环境, 很适合高端的手持设备和移动设备[2]。但由于它没有分层, 使其结构层次欠佳, 软件代码维护不便, 因此, 需要对其进行优化。
1 QT/E的客户/服务器结构分析
在KDE桌面系统中, KDE通过X Window的客户/服务器 (以下简称C/S) 系统完成显示和设备的输入工作。对于嵌入式设备来说, 系统内存小且CPU速度相对较慢, 故嵌入式设备的桌面系统不可能建立在X Window之上[3], 因此, QT/E给出了自己的C/S模型, 并提供了类似X Window的功能, 完成显示和设备的输入工作。QT/E的C/S结构如图2所示。
QT/E中的服务器的功能主要包括:接收鼠标、键盘、触摸屏等外部设备产生的事件, 并把事件分配给对应的客户机处理;协调客户机之间的行为。客户机功能主要是根据服务器发送来的鼠标、键盘等外设事件进行具体处理, 将处理结果以图形方式表示出来 (如窗口的缩放、移动等) 。QT/E的服务器功能主要由QWSServer类来实现, 客户机的功能主要由QWSDisplay类来实现[4]。
QT/E中的C/S结构分为两种情况: (1) 当服务器端与客户在同一个进程中, QT/E在服务器端启动的同时, 系统会自动启动一个客户端, 并生成一个client对象保持与这个客户端的通讯, 当服务器端有消息发送给客户端则把此消息放到与服务器对应的消息队列 (outgoing) 中, 待客户端处理时从服务器消息队列取出消息, 把消息放入到客户端消息队列中;当客户端有消息发给服务器端时, 则把此消息放到与客户端对应的消息队列 (incoming) 中, 待服务器端处理时从客户端消息队列取出消息, 把消息放入到服务器端消息队列中; (2) 当服务器端和客户端在不同的进程中, 客户/服务器间的通信通过socket文件描述符csocket进行。服务器将来自鼠标及键盘等硬件输入的数据通过QWSClient:sendEvent () socket以事件形式发送给客户端, 另外还把服务器对窗口的全局管理方面的事件发送给客户端。每启动一个客户端服务器端都会创建一个特定定义 (QWSClient类描述) 的对象与客户端对应, 这个对象会构造一个与客户端对应的套接字 (socket) , 当有消息发送给客户端时, 服务器找到这个特定对象, 把消息写到这个对象中构造的套接字中, 这样客户端通过系统调用select () 能发现有消息到来, 从而激发函数到本进程中的socket中去读。同理, 客户端将一些需要服务器处理的窗口管理及鼠标键盘命令数据通过socket以事件形式发送给服务器。同时, 客户端还通过socket接收来自服务器的事件, 分发给客户端相关的窗口进行处理。
QT/E的C/S模型被封装在QT/E内核中, 通过QAPPlication建立模型的各种关系, 用QT/E类库完成与模型的各种通信及操作。对于应用程序开发者来说, 开发QT/E应用程序与开发PC机的Qt应用程序基本上是一样的, 几乎感觉不到QT/E的C/S模型的存在。
2 QT/E进程间通讯方式分析
在QT/E中, 进程内的通讯可以通过信号与槽, 其内封装了回调函数, 而进程间的通讯是通过通道, 通道通讯底层同样是封装了socket机制, 所以通道通讯同样是socket通讯[5]。在应用系统中, 服务器端保存着一个QCopServerMap队列, 里面存放的是通道名和对这个通道感兴趣的客户端对象的索引, 在客户端保存着一个QCopClientMap队列, 里面存放着通道名和对这个通道感兴趣的对象。客户端间在使用通道通讯前必须先在服务器端进行通道注册。具体过程是需要通讯的进程先构造一个QCopChannel对象, 把这个对象与要注册的通道名字放入到QCopClientMap队列中, 然后向服务器端发送注册命令, 服务器端在接到消息后读出注册命令, 找到与这个客户端相对应的客户端对象, 然后把这个通道名和这个客户端对象的索引加入到QCopServerMap中。当客户端需要与其它客户端通讯时, 客户端把本身所属通道的名字与消息数据一起发送到服务器端, 服务器端判断是通道信息就调用相关函数处理, 其过程是先在QCopServerMap中找到这个通道名, 取出其对应的客户端对象列表, 再把这个消息通过循环调用相应的发送函数发给所有注册了此通道名的客户端对象, 最后通过socket机制发送到客户端。C/S通讯关系如图3所示。
3 QT/E的C/S结构的优化方案
通过以上分析, 可知QT/E的服务器不是独立运行的, 而是附加在客户端应用程序上, 服务器端本身也具有客户端的功能。在QT/E的内核中, 客户和服务器的代码在上层基本上是在一个函数中处理, 只是用一些变量来标识是否是服务器用的代码, 程序在编写时必须把服务器端与客户端功能的代码都包含在一起, 因此就要用大量的条件判断进行区别, 结果造成代码可读性较差, 不便修改和维护。
通过把QT/E中服务器的功能与客户端的功能在代码上分离, 使服务器启动时不启动客户端, 以-qws启动的进程只作为服务器端, 仅在系统中起协调作用, 这样可使软件结构更加清晰合理, 此时客户端只有一种情况, 从而可以省去很多不必要的判断和一些为服务器端启动的特定的消息队列等。
服务器端与客户端在底层只通过socket通讯, 从而在服务器端与客户端的消息处理循环中减少了大量的判断与不必要的函数调用, 不仅增强了程序的可读性, 也方便了程序的移植和维护。同时, 由于减少了一些不必要的函数调用以及对QT/E中大量的线形函数的优化, 系统运行速度和效率也会有所提高。
4 结束语
QT是KDE等项目使用的GUI支持库, 所以其可移植性非常好, 许多基于QT的Xwindow程序可以非常方便地移植到嵌入式系统。自从QT/E以GPL条款发布以来, 就有大量的嵌入式Linux开发商转到了QT/E系统上, QT/E作为Linux系统上主要的图形引擎将在以后得到更为广泛的应用。因此, 对QT/E的内核结构进行进一步分析与优化是非常必要的。
参考文献
[1]倪继利.QT及linux操作系统窗口设计[M].北京:电子工业出版社, 2006.
[2]Prentice Hall Ptr.C++GUI Programming with Qt4[M].2版.齐亮, 译.北京:北京航空航天大学出版社, 2008.
[3]纪君峰.基于QT/E的嵌入式系统研究及应用[M].北京邮电大学, 2008.
[4]trolltech公司QT/E源代码4.0.1[Z/OL].http://www.trolltech.com/download/tech previews.html.