yaneng 2020-02-14
在嵌入式Linux应用中,有时会用到图形界面。在目前流行的图形界面中,比较有名的当数Qt。Qt是1991年由挪威Trolltech公司开发的一个跨平台C++图形用户界面应用程序开发框架,主要用来开发GUI(Graphical User Interface)程序。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt作为一个跨平台的GUI 框架,在源码上对所有平台都是一致的,Unix/Linux上最流行的桌面环境之一KDE就是采用Qt来写的。
Qt具有以下优点:
1、优良的跨平台特性。Qt支持下列操作系统: Microsoft Windows 95/98,Microsoft Windows NT,Linux,Solaris,SunOS,HP-UX,Digital UNIX(OSF/1,Tru64),Irix,FreeBSD,BSD/OS,SCO,AIX,OS390,QNX 等等。
2、面向对象。Qt的良好封装机制使得Qt的模块化程度非常高,可重用性较好,对于用户开发来说是非常 方便的。 Qt提供了一种称为signals/slots的安全类型来替代callback,这使得各个元件之间的协同工作变得十分简单。
3、丰富的API。Qt包括多达250个以上的C++类,还提供基于模板的collections,serialization,file,I/O device,directory management,date/time类,甚至还包括正则表达式的处理功能。
4、支持2D/3D图形渲染,支持OpenGL。
5、支持XML。
Qt目前的名称分类较为混乱,一般来说,Qt泛指Qt software的所有版本的图像界面库,包括Qt/X11(Unix/Linux),Qt Windows,Qt Mac等。Qte(Qt Embeded)则专指用于嵌入式Linux系统的Qt版本,它也是一套界面库。而Qtopia则是一个基于Qte的类似桌面系统的应用环境,同时又为开发者为嵌入式设备编写程序提供了一套面向对象的API,包含有PDA版本和Phone版本。Qt Creator则是一款轻量级的集成开发环境(IDE),它能够跨平台运行,支持包括Linux(32 位及 64 位)、Mac OS X以及Windows系统。Qt Designer则是集成在Qt Creator中的一个图形设计器,是用来设计图形界面的一个工具。
从上面的叙述中可以了解到,Qt本质上其实是一组生成图像界面的库文件,它可跨多种操作系统平台使用,而专用于嵌入式Linux下的Qt称为Qte,它在原来Qt的基础上进行了裁减和改良,去掉了X Lib的依赖而直接工作在Framebuffer上,并实现了自己的窗口管理系统QWS(Qt Windows System),这是Qte与Qt最大的区别。因此Qte可以在嵌入式Linux系统中没有X11库的环境下构建独立的图形用户界面,而且不会占用太多的嵌入式系统资源。另外,Qte为方便嵌入式Qt应用的开发,还提供qvfb和makeqpf等工具,qvfb实现了Qte的应用程序能在PC上进行调试和测试,避开了X11库的干扰,makeqpf则用来制作qpf字体文件,用于在嵌入式界面中显示特殊渲染字体。至于Qtopia,其实它就是利用Qte这个库开发出来的应用程序,相当于嵌入式设备上的桌面环境,类似于PC上的KDE,它提供了自己的窗口管理、控制等GUI接口,简化了Qte应用程序的开发,但就算不使用Qtopia也可以使用Qte创建自己的图形界面。最后,Qt Creator只是让开发人员能够利用Qt这个应用程序框架更加快速及轻易的完成开发任务的一个开发工具。
Qt可从其官方网站(http://download.qt.io/archive/qt/)上下载,目前的最新版本为5.11,从4.5版本之后,Qte的名称就从原来的“qt-embedded-linux-opensource”改为“qt-everywhere-opensource”,但缩写不变,还是Qte。另外,Qtopia只发展到了2.2.0版本,后来就更名为“qt-extended-opensource”,但也只到了4.4.3版本就终结了,目前没有再发展,而且它把所依赖的Qte也更名为“qtopia core”。Qt Creator目前的最新版本为2.5.2,有Windows版本、Mac版本和Linux版本的可供下载。
下面就来讨论Qte在S3C2416上的移植。
为了实现界面显示,首先要让Linux支持LCD屏和触摸屏。
先看LCD屏。这里给硕数公司的S3C2416核心板使用的是群创的7寸液晶屏,型号为:AT070TN83 V.1,能提供800X480的屏幕分辨率,支持262K色,它带有一个40pin的FFC接口,可通过排线直接插入到开发板对应的LCD接口上。由于该LCD的控制引脚和控制时序都与S3C2416的LCD接口一样,所以在移植上就简单多了,只要让Linux支持Framebuffer就行了。在Linux中执行“make menuconfig”打开配置对话框,勾选Device Drivers -> Graphics support -> Support for frame buffer devices -> Samsung S3C framebuffer support项。同时可勾选Device Drivers -> Graphics support -> Console display driver support -> Framebuffer Console support项,以支持终端字符显示,完成后保存退出。
接下来看触摸屏的移植。S3C2416支持电阻式触摸屏,但它需要借助A/D转换才能实现触摸功能,因此先要让Linux支持A/D转换模块。在Linux中执行“make menuconfig”打开配置对话框,勾选System Type -> ADC common driver support 项即可。除了A/D模块以外,还需要配置触摸屏支持,勾选Device Drivers -> Input device support -> Touchscreens -> Samsung S3C2410/genric touchscreen input driver项,完成后保存退出。以上配置完成后,还需要修改部分代码,用vi打开arch/arm/mach-s3c2416/mack-smdk2416.c文件,先添一个触摸屏的头文件:#include <plat/ts.h>,然后新创建一个内容如下的结构体:
static struct s3c2410_ts_mach_info smdk2416_ts_cfg __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
};
上面结构体中的oversampling_shift一项决定了触摸移动时鼠标的跟随紧密程度。接下来找到*smdk2416_devices[] __initdata结构体,并在其末尾加入一句“&s3c_device_adc,”和一句“&samsung_device_ts,”,完成后的结构内容如下:
static struct platform_device *smdk2416_devices[] __initdata = {
&s3c_device_fb,
&s3c_device_wdt,
&s3c_device_ohci,
&s3c_device_i2c0,
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_usb_hsudc,
&s3c_device_smsc911x,
&s3c_device_rtc,
&samsung_asoc_dma,
&s3c_device_adc,
&s3c_device_ts,
};
再接着找到smdk2440_machine_init()函数,在其中加入下面一句,完成后存盘退出。
s3c24xx_ts_set_platdata(&smdk2416_ts_cfg);
接下来修改触摸屏程序文件,用vi打开drivers/input/touchscreen/s3c2410_ts.c文件,先找到touch_timer_fire()函数,然后在其中找到“input_report_key(ts.input, BTN_TOUCH, 0);”一句,紧接着在其下面加入一句:“input_report_abs(ts.input, ABS_PRESSURE, 1);”,然后再找到“input_report_key(ts.input, BTN_TOUCH, 0);”一句,同样紧接着在其下面加入一句:“input_report_abs(ts.input, ABS_PRESSURE, 0);”。接下来找到s3c2410ts_probe()函数,并在其中找到“ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);”一句,把它改为:“ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT(EV_SYN);”。接着往下找到“input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0);”一句,紧接着在其下面加入一句:“input_set_abs_params(ts.input, ABS_PRESSURE, 0, 1, 0, 0);”,完成后存盘退出。
全部修改完成后,执行make zImage编译内核,完成后把zImage文件下载到开发板上并启动系统,启动完成后输入命令“ls /dev/event0”,查看一下是否存在设备节点文件event0,若有就说明触摸屏设备移植成功了。其实触摸屏设备移植成功也可以从系统的启动信息中看出来,会有“samsung-ts s3c2410-ts: driver attached, registering input device”和“input: S3C24XX TouchScreen as /devices/virtual/input/input0”的信息提示。
触摸屏移植成功后,接下来还要移植一个称为tslib的应用程序,它用于给触摸屏进行误差修正及测试。tslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用提供了一个统一的接口。在Qt程序中一般都需要用到tslib提供的支持,所以在移植Qt前先要移植tslib。
tslib的官网为:http://www.tslib.org/,可到该网站上或其它镜像网站上去下载tslib。这里以1.6版本为例进行讨论,要下载文件为tslib-1.6.tar.bz2。下载完后把它解压到虚拟机Linux的根目录下,执行“tar -jxvf tslib-1.6.tar.bz2 -C /”,然后进入到该目录下。先执行“./autogen.sh”以生成配置文件,接着执行“echo "ac_cv_func_malloc_0_nonnull=yes">arm-linux.cache”(注:不包括最外层双引号),然后执行“./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=/usr/local/tslib”进行系统配置并生成Makefile文件。最后就可以进行交叉编译了,本例使用的交叉编译工具版本和前面编译内核的版本一样(4.4.3),但这里为了保证正常编译,需要对交叉编译工具进行一下修改。进入到交叉编译工具链所在的目录,然后找到头文件input.h(本例在“./arm-none-linux-guneabi/sys-root/usr/include/linux/”下),用vi打开它并找到“Absolute axes”部分(大约在第618行),在其中加入以下的宏定义:
#define ABS_MT_SLOT 0x2f
#define ABS_MT_PRESSURE 0x3a
#define ABS_MT_TOOL_X 0x3c
#define ABS_MT_TOOL_Y 0x3d
#define ABS_MT_DISTANCE 0x3b
完成上述修改后存盘退出,然后回到tslib-1.6目录下执行“make”命令进行交叉编译,编译完成后执行“make install”进行安装,安装完成后就可以在/usr/local/tslib目录看到编译好的tslib程序目录了,如下图所示。
把上述目录拷贝到开发板上的/usr目录下,然后配置一下/etc目录下的profile文件,以把tslib的路径导出到系统搜索路径。加入profile的内容如下。
export TS_ROOT=/usr
export TSLIB_TSDEVICE=/dev/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=$TS_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=$TS_ROOT/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
完成后存盘退出。重启一下开发板(也可执行“soucrce /etc/profile”),让搜索路径生效。接着在开发板上执行ts_calibrate命令,若tslib移植正常,则可启动触摸屏校准程序,此时LCD屏上会显示出校准屏幕,用触摸笔分别点击5次校准点就可完成触摸屏的校准。此外,还可以执行ts_test命令进行触摸屏测试,可进行拖曳和画图测试。
tslib移植成功后,就可以进行Qt的移植了。本例以最后一个qt-embedded-linux-opensource版本4.5.3为例进行讨论,其他版本可参考进行。把从官网上下载的文件qt-embedded-linux-opensource-src-4.5.3.tar.gz解压到系统根目录下,执行命令“tar -zxvf qt-embedded-linux-opensource-src-4.5.3.tar.gz -C /”,然后进入到该目录下。接着要进行配置,但由于配置命令较长,可先把配置命令全部写在一个脚本文件setup.sh中,然后再去执行这个脚本就方便多了。配置脚本setup.sh的内容如下。
#!bin/sh
./configure -prefix /usr/local/Trolltech/QtEmbedded-4.5.3-arm -embedded arm -release -shared -fast -no-largefile -qt-sql-sqlite -no-qt3support -no-xmlpatterns -no-mmx -no-3dnow -no-sse -no-sse2 -no-svg -no-webkit -qt-zlib -qt-gif -qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -make libs -nomake tools -nomake examples -nomake docs -nomake demo -no-nis -no-cups -no-iconv -no-dbus -no-openssl -xplatform qws/linux-arm-g++ -little-endian -qt-freetype -depths 16,18 -qt-gfx-linuxfb -no-gfx-transformed -no-gfx-multiscreen -no-gfx-vnc -no-gfx-qvfb -qt-kbd-usb -no-glib -qt-mouse-tslib -qt-gfx-qvfb -qt-kbd-qvfb -qt-mouse-qvfb -I/usr/local/tslib/include -L/usr/local/tslib/lib
由于内容较多,编写时一定要仔细,其中每项配置的具体信息可通过执行“./configure --help”来获取查看,这里就不赘述了。在上述配置中,注意第一项配置“-prefix /usr/local/Trolltech/QtEmbedded-4.5.3-arm”,其后面的路径是指在Qt编译完成后执行“make install”时的安装路径,即编译好的Qt程序会被安放到虚拟机上的/usr/local/Trolltech/QtEmbedded-4.5.3-arm目录下。由于Qt库中存在有链接文件,所以当把Qt移植到开发板上时,Qt库也要放在同样的目录下,否则链接会失效!所以应先根据开发板上存放Qt库的路径来确定prefix配置项的路径。另外,上述最后两项配置“-I/usr/local/tslib/include -L/usr/local/tslib/lib”中,其中的路径/usr/local/tslib也是前面编译好的tslib程序的存放路径,因为在编译Qt时也会用到tslib。
完成上述脚本文件后,就可以执行它了,输入命令“sh setup.sh”并回车即可执行配置。在配置时会询问你Qt是用作商业还是开源,这里选择开源,根据屏幕提示输入“o”,然后会再问你是否同意,输入“yes”并回车即可执行配置。配置需要一定的时间,配置完成时若没有错误提示表明配置成功,若有错误要依据提示去修改,一般都会是上述配置脚本中没有输入对引起的。配置成功后执行make命令进行编译,编译会经历较长的时间,编译成功后执行“make install”命令进行安装。安装结束后,就可以在/usr/local/Trolltech/QtEmbedded-4.5.3-arm目录下看到交叉编译好的Qt库目录了,如下图所示。
移植到开发板上时,只需要把lib目录拷贝过去就行了,但一定要放在同样的目录下。另外,在拷贝lib目录时,cp命令一定要加上参数“-d”,以确保链接文件的正确拷贝。拷贝完成后,再次配置profile文件,以导出Qt库的路径。在profile中加入下面的内容:
export QTDIR=/usr/local/Trolltech/QtEmbedded-4.5.3-arm
export QPEDIR=/usr/local/Trolltech/QtEmbedded-4.5.3-arm
export QWS_MOUSE_PROTO=Tslib:/dev/event0
export QWS_DISPLAY=LinuxFb:/dev/fb0
export QWS_SIZE=800x480
完成后存盘退出,重启一下开发板,Qt就可以使用了。为了测试Qt是否正常,可使用刚才在虚拟机中解压的qt-embedded-linux-opensource-src-4.5.3下的例子程序来进行测试,例子全部在example目录下面。本次选用digitalclock进行测试,进入到该目录下可看到工程需要的所有文件,为了编译工程,需要用到qmake命令,该命令程序位于刚才安装好的Qt目录下,即“/usr/local/Trolltech/QtEmbedded-4.5.3-arm/bin”目录下。为了后面方便,可把此目录添加进系统搜索路径(加入/root/.bash_profile文件中)。在digitalclock目录下,先执行“qmake -project”命令,再执行“qmake”命令,在生成Makefile文件后,就可执行“make”命令进行交叉编译了,成功后就会在该目录下生成digitalclock可执行文件,把它拷贝到开发板上,然后在开发板上输入“./digitalclock -qws”并回车,就可执行该程序了。程序执行后,在LCD屏上就会出现一个数字时钟的窗体,该窗体还可使用触摸屏进行拖曳和缩放。至此,触摸屏和Qt移植成功。