1、长 春 大 学课 程 设 计 说 明 书题目名称 基于嵌入式系统的数字相框设计 院(系) 计算机科学技术学院 专业(班级) 软件 10407 学生姓名 王雅楠(03) 刘阳(19) 廖泉亮(15) 李凯(25) 王志廷(28) 刘福强(29) 尹双霞(02) 李铁成(23) 指导教师 李 念 峰 起止日期 2013-6-24至2013-7-14 装订线长 春 大 学 课程设计纸目录目 录错误!未定义书签。一 设计目的错误!未定义书签。二 设计内容错误!未定义书签。三 设计要求错误!未定义书签。四 设计过程错误!未定义书签。1 设计原理错误!未定义书签。2 程序结构分析错误!未定义书签。3 功能
2、实现错误!未定义书签。五 系统测试错误!未定义书签。1 测试目的错误!未定义书签。2 测试条件错误!未定义书签。3 测试方法 错误!未定义书签。六 设计心得错误!未定义书签。参考文献错误!未定义书签。附录错误!未定义书签。一、设计题目 基于嵌入式系统的数字相框设计二、设计目的开设本课程设计的目的是,通过本课程设计,提高学生的分析问题、解决问题的能力,巩固嵌入式系统的基本理论知识,进一步了解和掌握课程中所讲授的概念,方法。同时通过本课程设计,全面综合应用所学过的基础知识,建立一个完整的嵌入式系统的开发过程的概念,并掌握其中的主要原理和方法,对已学过的嵌入式开发知识进行综合运用。本课程设计的目的是
3、通过开发一个消费类电子产品数字相框,了解嵌入式产品开发的主要步骤,包括需求分析、系统结构设计、图形界面设计、驱动程序、功能优化、系统测试等,从而培养学生独立完成比较复杂的实际系统设计的能力。三、设计任务作为一个消费类电子产品,数码相框整个系统要完成的基本功能大致如下:1、用户界面友好,操作简便。由于该产品的使用者大多是非专业人士,用户界面是否清晰明了、操作是否简捷方便成为用户是否能迅速接受此产品的重要因素。2、数字相框的功能应包括以下方面:(1)在LCD屏上全屏循环显示多幅图像文件;(2)人机交互界面设定各个模式的播放形式、输入信息(2)支持触摸屏换页功能;(3)支持在浏览图片的同时播放背景音
4、乐 (4)支持JPEG格式的图片及wav格式的音乐 (5)支持图片特效切换功能四、设计过程1、设计原理数字相框,也称为数码相框,其基本原理:外观采用普通相框的造型,把原来相框中间的照片部分换成液晶显示屏,配上电源,存储介质等,可以直接播放数码照片,使得一个相框内可以循环播放照片,比普通相框的单一功能更有优势。性能方面,由于数字图像的解码算法比较复杂,而且大量图片需要从外部Flash存储器中读取,所以对嵌入式微处理器的性能要求比较高。外部接口方面,该芯片最好能在外围直接支持CF卡的Compact Flash接口,还应提供按钮、LCD显示屏、触摸屏、声音输出通道等。在本课程设计中,采用了Intel
5、的PXA270作为微处理器,完全能满足上述硬件平台的要求。数字相框软件系统功能可以划分为五个模块:(1)图片浏览模块,可以通过按键控制选定某个图像或更新图像页(上一页、下一页)。单击按钮时,主线程接收信号并传递给次线程,次线程根据信号给出相应的动作:显示上一页或下一页的内容。每一页中放置图片。当到达最后一页以后,不能立即返回到首页,在首页中,也不能立即到达最后一页。(2)播放模块,对浏览界面选定的图片进行循环播放。按钮区域创建进程运行预览模块,右击退出返回到主菜单,退出时将进程杀死,释放内存空间。(3)系统设置模块,可设置循环播放更换频率等。(4)音乐模块,播放,关闭,音量大小。右击并不退出音
6、乐,只有单击关闭按钮才会关闭音乐。2程序结构分析(1)整体结构设计:根据以上的功能要求,程序的模块划分和功能分析如下图所示:开始开机界面主菜单图片浏览扩展功能退出模块音乐模块主题更改显示时间 图1总体功能模块图(2) 图片浏览模块:主要有四个部分组成的,浏览上一张图片,下一张图片,扩放图片,以及缩小图片。此模块的功能是图片的显示。在此模块中建立显卡与内存的映射,实现图片显示,在显示的过程中还需要实现图片的预览,这就需要拥有图片的缩放功能。为了加强图片显示的美感,在此模块中,我们还设计了多种图片显示的特效。还要实现进程间的通信,获取其他进程发送来的信号,并执行相应操作。图片浏览模块扩放图片缩小图
7、片下一张图片上一张图片 图2图片浏览模块(3)音乐模块:在浏览优美的图片时,还可以听到动听的音乐。播放,暂停。这个模块的主要功能就是在整个程序运行的过程中进行音乐的播放。此模块对于我们来说比较陌生,具有一定的难度,不过我们会尽最大努力将它设计成功,让数码相框在图片显示的同时配上优美的音乐。音乐模块返回主界面播放列表右击播放所选歌曲选择下一首选择上一首 图3音乐播放流程图3功能实现(1)开发工具的选择:本课程设计采用嵌入式Linux作为软件开发平台。在Linux操作系统平台上有多种嵌入式图形界面开发工具可供使用,主要包括MicroWindows、MuniGUI、TinyX和Qt/Embedded
8、等几种。本课程设计将集中讨论在Qt/Embedded系统上数字相框的实现技术。操作系统:Ubuntu9.10 QT Creator.QT/Embeded界面介绍: 当前嵌入式Linux在手机、PAD等手持信息设备领域的应用十分广泛。各种手持设备是否拥有图形用户办(GUI)已经成为其人机交互技术的关键体现,所以一个十分友好的图形用户界面(GUI)是必不可少的。由于嵌入式系统硬件本身的多样性,嵌入式GUI应具备高度可移植性与可裁减性。(2)文件管理 共使用四个文件夹 image:用于存放所有要演示的图片 freetype-2.3.11:用于存放处理文字所需的工具 jpeg-8:用于存放处理图片所需
9、的工具 src:用于存放我们编写的各种函数。如:特效函数,主函数,Makefile函数等。(3)图片显示:设置图片不透明:effect.cppeffect:effect() setEffectType(opacity); setStartValue(1.0); setEndValue(1.0); setDuration(10); setDirection(QAbstractAnimation:Forward); m_easingCurve=QEasingCurve:Linear;设置图片预览的时间:int sequenceModel:duration()(4)WAV音乐: soundengin
10、e.cppvoid slideShowEngine:startSound() QSound bells(“G:/he.wav”);bells.play(); (5)图片的特效播放:直接画图,Int draw_jpeg0(fb_info fb_inf,u32_t *buf32, char *filename);百叶窗,int draw_jpeg4(fb_info fb_inf,u32_t *buf32, char *filename); 四周到中间,int draw_jpeg8(fb_info fb_inf,u32_t *buf32, char *filename);首先设置第一个图片的Ente
11、r Effect 的属性: rotation Forward OutInquad 开始坐标和结束坐标都为0。Display Effect 的属性: scale Forward OutInQuad Start Val的值为6。Duration的值为3000。Exit Effect的属性为:pos Forward InOutQuad 其中的所有坐标都为0;设置第二个图片的Enter Effect 的属性: rotation Forward OutInquad 开始坐标和结束坐标都为0,Duration 为500。Display Effect 的属性: rotation Forward OutInQ
12、uad End Val的值为360。Duration的值为4000。Exit Effect的属性为:pos Forward InOutQuad 其中的所有坐标都为0;设置第三张图片的属性值:pos Forward OutInQuad .End Point F 为600,600.End Val 值为650 Duration 值为3500。Display Effect 的值为:opacity Forward OutQuad 值都为0.Exit Effect 属性的值为:pos Forward OutQuad 值为0.设置第四张图片的属性值:Enter Effect 属性的值:pos Forward
13、 Linear Duiation的值为500.Display Effect的属性值为:pos Forward InCubic End Val的值为650.Duiation的值为3700.Exit Effect的属性值为:pos Forward OutQuad 值都为0。(6)停止图片的播放:void slideShowEngine:stop() m_currentState=Stopped; endOfSlideShow();(7)设置图片的属性: duration图片显示的时间:int sequenceModel:duration() node itemNode; int totalTime
14、=0; for(int i=0; irowCount();i+) itemNode=m_sequence.at(i); totalTime+=itemNode.enterEffect().duration(); totalTime+=itemNode.displayEffect().duration(); totalTime+=itemNode.exitEffect().duration(); return totalTime;插入图片:insertRowbool sequenceModel:insertRow (int row, const QModelIndex &parent) Q_UN
15、USED(parent); beginInsertRows(QModelIndex(), row, row +1); node item; m_sequence.append(item); setModified(true); endInsertRows(); return true; 图片的保存:void sequenceModel:save(const QString &filename) / queste sono operazioni lunghe. ci vuole una progress bar QFile file(filename); if(!file.open(QIODev
16、ice:WriteOnly) qDebug() tr(cannot open file for writing: ) qPrintable(file.errorString() endl; return;(8)U-boot的移植 建立工作目录 下载源码Uboot的源码:u-boot-2009.11.tar.bz2 #mkdir/root/build_uboot #cd/root/build_uboot把下载的源码拷贝到该目录,解压:并把解压后目录更名为u-boot#tar jxvf u-boot-2009.11.tar.bz2#mv u-boot-2009.11 u-boot创建主代码 复制b
17、oard/Samsung/smdk2410 目录为board/Samsung/gec2440#cp arf board/Samsung/smdk2410 board/Samsung/gec2440并修改目录下的Makefile将COBJS:=smdk2410.o.flash.o 修改为COBJS:=GEC2440.O.flash.o复制include/config/smdk2410.h为include/config/gec2440.h #cp include/config/smdk2410.h include/config/gec2440修改顶层Makefile: 创建目标板信息,在smdk2
18、410_config:unconfig$(MKCONFIG)$(:_config=)arm arm920tSmdk2410 samsung s3c24x0 后面添加gec2440_config:unconfig$(MKCONFIG)$(:_config=)arm arm920t gec2440 samsung s3c24x0 修改Makefile规则,将_LIBS:=$(subst$(obj),$(LIBS)$(subst$(obj),$(LIBBOARD)改为:_LIBS:=$(subst$(obj),$(LIBBOARD)$(subst$(obj),$(LIBS)进入目录配置编译配置#ma
19、ke gec2440_config#make编译结果生成u-boot.bin烧入开发板关于触摸板驱动移植 添加代码:将touchscreen驱动源码gec2440_ts.c(复制drivers/input/touchscreen目录下的s3c2410_ts.c)添加到linux-2.6.30源码目录drivers/input/touchscreen中。将ADC驱动源码gec2410_adc.c(复制drivers/char目录下的adc.c)及头文件s3c24xx-adc.h添加到linux-2.6.30源码目录drivers/char中。修改drivers/input/touchscreen
20、/Makefile文件。#vim drivers/input/touchscreen/MakefileObj-$(CONFIG_TOUCHSCREEN_GEC2440) +=gec2440_ts.修改drivers/input/touchscreen/Kconfig文件#vim drivers/input/touchscreen/Kconfig添加Config TOUCHSCREEN_GEC2440 Tristate”GEC2440 touchscreen input driver” Help Say Y here if you have the s3c2440 touchscreen.修改d
21、rivers/char/Makefile文件#vim drivers/char/Makefile添加Obj-$(CONFIG_GEC2440_ADC)+=gec2440_adc.o修改drivers/char/Kconfig文件#vi driver/char/Kconfig添加config GEC2440_ADC Tristate”GEC2440_ADC” -help-Say Y here if you have the s3c2440 ADC.修改arch/arm/plat-s3c/include/plat/devs.h文件#vim arch/arm/plat-s3c/include/pla
22、t/devs.添加:struct s3c2410_ts_mach_info int delay; 修改arch/arm/mach-s3c2410/mach-smdk2410.c文件#vim arch/arm/mach-s3c2410/mach-smdk2410.c添加Static struct s3c2410_ts_mach_info gec2410_ts_cfg_initdata= .delay = 10000, .presc = 49, .oversampling_shift=2,;在 static void_init smdk2410_map_io(void)函数中添加:s3c24xx_
23、init_ touchscreen(&gec2410_ts_cfg);修改arch/arm/mach-s3c2410/mach-smdk2410.c文件#vim arch/arm/mach-s3c2410/mach-smdk2410.c在 static struct platform_device*smdk2440_devices_initdata结构体中添加:&s3c_device_ts,编译配置内核 #make menuconfig配置菜单添加驱动到内核:Device Drivers- Input device support- * Touchscreens- GEC2440 touchs
24、creen input driver Character devices - GEC2440_ADC编译内核生成静态驱动模块#make修改arch/arm/plat-s3c/include/plat/devs.h文件#vim arch/arm/plat-s3c/include/plat/devs.h添加:struct s3c2410_ts_mach_info int delay; int presc; int oversampling_shift;void_init 3c24xx_init_touchscreen(struct s3c2410_ts_mach_info*hard_s3c2410
25、_ts_info);extern struct platform_device s3c_device_ts;修改arch/arm/plat-s3c24xx/ devs.c文件#vim arch/arm/plat-s3c24xx/ devs.c在文件后面添加/*Touchscreen*/static struct s3c2410_ts_mach_info s3c2410_ts _info;void_init s3c24xx_init_touchscreen(struct s3c2410_ts_mach_info*hard_s3c2410_ts_info);memcpy($s3c2410_ts_i
26、nfo, hard_s3c2410_ts_info,sizeof(struct s3c2410_ts_mach_info);EXPORT_SYMBOL(s3c24xx_init_touchscreen);struct platform_device s3c_device_ts= .name=” s3c2410_ts”, .id=-1, .num_resources=ARRAY_SIZE(s3c_adc_ resource), . resource = s3c_adc_ resource,.dev= .platform_data=$s3c2410_ts_info,EXPORT_SYMBOL(s3
27、c_device_ts);在根文件系统中建立相关设备节点:#mkdir /dev/input#mknod/dev/input event0 c 13 64 #mknod /dev/input/mouse0 c 13 32提示“Read-only file system”,或者”mkdir:cannot create directory /dev/input:File exists”.解决方法如下: #chmod 777/dev/ #mount o remount rw/基于qt3平台的应用程序(9)驱动的移植 关于USB驱动移植 修改arch/arm/mach-s3c2410/mach-smd
28、k2410.c文件#include#include#include#includeStatic struct s3c2410_hcd_info usb_gec2410_info= .port0= .flags=S3C2410_HCDFLG_USED,;Int usb_gec2410_init(void) Unsigned long upllvalue=(0x7812)|0xo24)|(0x03);Prink(“USB Control,(c)gec2410n”);s3c_device_usb.dev.platform_data=&usb_gec2410_info;while(upllvalue!
29、=_raw_readl(S3C2410_UPLLCON) _raw_write(upllvalue,S3C2410_UPLLCON); mdelay(1);return 0;在static void_init smdk2410_map_io()函数中添加usb_sbc2410_init()函数usb_getc2410_init();内核配置 支持热插拔 General setup- *Configure standard kernel features(for small systems)- Support for hot-pluggable devices让内核支持USB设备Device d
30、rivers Block devices - Low Performance USB Block driver SCSI device support- SCSI generic support Probe all LUNs on each SCSI device USB support- Support for Host-side USB *USB device filesystem USB Mass Storage support USB Monitor加入 MSDOS文件系统和VFAT文件系统支持(为适应挂载U盘)File systems- DOS/FAT/NT Filesystems-
31、 MSDOS fs support VFAT (Windows-95) fs support (936) Default codepage for FAT (cp936) Default iocharset for FAT使能(DOS分区) CONFIG_MSDOS_PARTITIONFile systems-Partition Types- *PC BIOS (MSDOS partition tables) support添加对中文字体库的支持File systems-*- Native language support- Simplified Chinese charset(CP936,G
32、B2312) NLS UTF8 编译 #make五、系统测试1测试目的软件测试是软件开发的最后一个阶段,测试的目的不是证明所开发的软件没有错误,而是尽可能的多发现软件设计开发全周期中各个阶段的错误, 以便分析错误的性质与位置而加以纠正,纠正过程涉及到更正或重新设计相关的文档活动。从而避免用户在使用时出现不可预测的异常而导致整个系统崩溃。2、测试条件(1)系统条件Linux操作系统(2)人员选择单元测试: 每个模块的设计人员系统测试: 设计小组的全体成员验收测试:测试:在我们设计小组成员的指导下,进行测试测试:完全由不是本小组的人员进行测试3、测试方法采用黑盒测试和白盒测试兼并的测试方法,每当完
33、成一项事件的处理时,便执行程序,进行测试,每完成一个模块的代码,也进行相关的测试,最后,全部代码完成时,进行全面的测试。4测试过程(1)文件路径加载问题: QPixmap pixmap;/全局变量 QFileInfoList list;/全局变量 QString dir=”/home/akaedu/”;QDir picdir(dir);QStringList filters;Filters”*.jpeg”;Picdir.setNameFilters(filters);List=picdir.entryInfoList();QFileInfo fileInfolist.at(i);QString
34、 path=fileInfo.filePath();Pixmap.load(path);问题:当图片显示最后一张图片继续点下一张图片按扭的时候,图片路径是正确的,但窗口不正确。分析原因:因为QPixmap pixmap 为全局变量,在图片浏览功能时pixmap.load(path)将所有的图片都加载进去,虽然指针i QFileInfo fileInfo=list.at(i) 控制图片的路径,用qDebug打印路径是正确的,但QPixmap pixmap一直取的是所有图片中的最后一张图片的。解决的方案是:将QPixmap pixmap设置为局部变量,位置位于void RenderArea:pai
35、ntEvent(QPaintEvent *)画图函数的作用域。Void RenderArea:paintEvent(QPaintEvent *) QPainter painter(this); QFileInfo fileInfo =list.at(i); QString path=fileInfo.filePath(); QPixmap pixmap;Pixmap.load(path);(2)循环控制播放的问题:当图片循环时指针i一直处于递加的,但图片的显示是循环结束图片第一个到最后一张。QPixmap pixmap是通过触发调用void RenderArea:paintEvent(QPai
36、ntEvent *)来将图片显示的,其中有2个函数方法可以:一个是update()、另一个是repaint();我们用的是前者。分析原因:update()函数在循环控制的时候不管次数的多少,只在最后一次调用paintEvent显示最后一张。解决方案:在循环控制的时候repaint()有多少次调用多少次,所以用repaint()代替update()(3) 运行程序时,总会出现qmake的错误,后来发现是因为保存的路径中有中文的原因。将路径改为G:/Images之后可成功启动。(4)在添加歌曲时,开始时我们添加的是MP3格式的音乐,可是始终听不到音乐:将音乐格式改为WAV格式的音乐,就可以正常播放
37、了。 (5)对添加进来的图片进行特效制作:opacity:设置图片不透明 Forward:设置图片向后转 rotation:设置图片循环旋转六、设计心得本次课程设计,在QT的环境下编写程序,然后把程序向试验箱进行移植,比起以往的单一编程,还是有些难度的。设计中我们遇到很多的难题,很多东西都是第一次接触,很多用到的技术网上根本没有资料,完全凭借自己去摸索尝试。其中的困难可想而知。实现模块中是问题最多的,文件解析,文件读取,特效制作等等。还有许多的细节问题,如内存释放、软硬编码、信号传输、环境变量。 通过这次数码相框的设计,让我们了解了这是一个团队的工作,团队需要个人,个人也离不开团队,必须发扬团
38、结协作的精神。每一个人都必须紧密的融入到团队之中,这样才能让这个团队更高效。设计过程中只有一个人知道原理是远远不够的,必须让每个人都知道,否则一个人的错误,就有可能导致整个工作的失败。团结协作是我们设计成功的一项非常重要的保证。而这次设计也正好锻炼我们这一点,这是非常宝贵的经验。此次项目设计,巩固了以往学过的知识点,得到了很多新的项目设计的宝贵经验,比如独立思考解决问题,出现差错的随机应变,与他人的协作等等。这都让我们受益匪浅,会让我们今后的项目设计更加轻松,让我们能够更加优秀的完成今后的项目设计工作。在设计的过程中,我们才发现知识仅仅“学过”是不够的,还要会用。这样那些知识才能真正的算作你自
39、己的知识,也就是理论与实际相结合。只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才是真正的学以致用,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到的问题也很多,有一些也让我们大伤脑筋,这毕竟是第一次以一个团队的形式来完成一个项目的设计,难免会遇到各种各样的问题,同时在设计的过程中发现了我们本身的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。在此,感谢老师的细心指导,感谢其他各组同学的无私帮助,并且再次对我们小组所有组员在项目设计过程中所付出的辛劳与努力表示感谢。参考文献1、石秀民,魏洪兴主编。嵌入式系统原理与应用基于XScale
40、与Linux.北京航空天大学出版社,2007.2、陈虎,吴涛等著。嵌入式系统课程设计。机械工业出版社,20083、北京博创兴业科技有限公司。UP-TECHPXA270-S_LINUX实验指导M.20074.王天苗,嵌入式系统设计与实例开发M. 北京:清华大学出版社,2010附录共 页 第 11 页1、 Main.cpp#include #include mainwindow.hint main(int argc, char *argv) QApplication a(argc, argv); MainWindow w; /a.setStyle(plastique); w.show(); ret
41、urn a.exec();2、soundengine.cpp#include slideshowengine.hvoid slideShowEngine:startSound()QString command; command=/usr/bin/mplayer -slave ; for(int i=0; isoundtracks().count();i+) command.append(m_sequence-soundtracks().at(i); command.append( ); qDebug() command; m_mplayerProcess.start(command); /m_mplayerProcess.write(command.toUtf8();void slideShowEngine:pauseSound() QString command; command=pausen; m_mplayerProcess.write(command.toUtf8();void slideShowEngine:resumeSound() QStr