基于Cortex处理芯片+Linux操作系统设计数码照相机系统_第1页
基于Cortex处理芯片+Linux操作系统设计数码照相机系统_第2页
基于Cortex处理芯片+Linux操作系统设计数码照相机系统_第3页
基于Cortex处理芯片+Linux操作系统设计数码照相机系统_第4页
基于Cortex处理芯片+Linux操作系统设计数码照相机系统_第5页
已阅读5页,还剩38页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

绪论1.1背景随着数码相机的盛行,传统相机逐渐退出历史的舞台。对于数码相片的欣赏和摆设,人们一般只能通过PC机,极其不方便。数码相框正是迎合这种需求,它体积小,能随时更换相片,并具有USB主机功能,能够即插即用,拥有较大的存储空间。1.2数码相框的特点1.3系统开发目标本设计结合了使用Cortex处理芯片的开发板和源代码开放的嵌入式Linux操作系统共同建立的平台设计了数码照相机系统,主要实现的功能有对多种格式相片在800×480触摸LCD上显示、USB主机读取功能、对摄像头采集的视频流进行截图(拍照)等功能。1.4设计路线及开发工具1.4.1设计路线本系统将按照软件工程管理思想对软件的研究、可行性分析、需求分析、概念结构设计、逻辑结构设计、功能设计、详细设计、编码、实施、维护各阶段进行严格的控制。保证系统开发质量。根据数码相框系统所需要的硬件配置和开发目标,查阅相关的资料,深入研究开发本系统所需要的相关理论知识和所需的硬件环境,通过需求分析来确定该系统的总体设计方案。1.4.2开发工具硬件配置名称说明CPUs5pv210,DDR2-800数据传输频率800MHz,外部时钟频率200MHz,内部时钟频率100MHz,nandfalsh外部时钟频率133MHz内核ARMCortex-A8FLASH256MBSLCNANDFLASH内存512MBDDR2USB4个USBHost2.0接口,1个USBOTG2.0接口网口1个串口2串口调试接口20-pin,2.54mm标准JTAG接口摄像头接口两个,支持最大12M(8192x8192)接口8-bitITU601/656和MPDI/CSISD接口4MATAinterface标准CAMERA接口2个,独立I/O8路I/OLCD7寸TFT-LCD屏触摸屏LCD电容屏A/D转换器10bit电压0-3V蜂鸣器1个led灯2个用户,一个电源显示JTAG接口标准用户扩展接口2路SPI接口,2路IIC接口,3路PWM,4路UART,6路ADC,1路SDIO接口和其它用户扩展IOPCB板层8层userkey8个电源供电+5/2A工作温度-20~+70度软件配置名称说明操作系统Linux-2.6.14ubuntu12.04LTS内核版本linux-3.0.8开发工具GNU工具启动代码u-boot-2010.03驱动程序所有硬件驱动文件系统根文件系统采用cramfs,用户文件系统采用yaffs2,nfs文件系统协议栈TCP/IPPPP,tftp,nfs1.5嵌入式系统环境搭建1.5.1arm-gcc交叉编译工具链的安装和使用在官网下载arm-gcc的源码解压工具链的压缩包cd~tarxvfarm-cortex_a8-linux-gnueabi.tar.bz2环境变量的添加 修改文件/etc/bash.bashrc添加如下内容 exportPATH=$PATH:/home/linux/arm-cortex_a8/bin 重启配置文件 $source/etc/bash.bashrc工具链的测试arm-cortex_a8-linux-gnueabi-gcc–v1.5.2u-boot的烧写及使用SD启动盘制作将第一天/SD卡启动制作工具/sd_fusing拷贝到Linux下将SD卡插入电脑并识别进入sd_fusing执行如下操作$make$chmod777sd_fusing.sh$sudo./sd_fusing.sh/dev/sdb(sdb为sd卡在ubuntu的设备节点)u-boot的烧写运行串口通信程序(putty)关闭开发板电源,将拨码开关SW2调至0110(SD启动模式)后打开电源将刚才做好的SD启动盘插入SD卡插槽重新打开开发板能够看到如下界面设置板子环境变量#setenvserverip00//和ubuntuip一直#setenvipaddr00 //板子的ip不要和windows和Ubuntu冲突将第一天/镜像文件/u-boot.bin拷贝到ubuntu的/tftpboot目录下烧写#tftp20008000u-boot.bin#nanderase0100000#nandwrite200080000100000关闭开发板电源,将拨码开关SW2调至1000(NAND启动模式)后打开电源可以看到如下界面表示烧写成功通过网络加载内核和文件系统将第一天/镜像文件/zImage拷贝到ubuntu的/tftpboot下将第一天/镜像文件/rootfs.tar.bz2拷贝到ubuntu的/source下并解压修改虚拟机nfs配置文件/etc/exports,添加如下内容并重启nfs服务source/rootfs*(rw,sync,no_subtree_check,no_root_squash)重新驱动nfs服务$sudo/etc/init.d/nfs-kernel-serverrestart设置启动参数#setenvbootcmdtftp20008000zImage\;go20008000#setenvbootargsroot=nfsnfsroot=00:/source/rootfsip=00init=/linuxrcconsole=ttySAC0,115200#saveenv启动开发板看到如下现象表示成功通过网络挂载:1.5.3内核的配置和编译 解压内核将linux-3.0.8.tar.bz2拷贝到/home/linux下并解压$tarxvflinux-3.2.tar.bz2$cdlinux-3.0.8修改内核顶层目录下的Makefile$vimMakefile修改:ARCH ?=$(SUBARCH)CROSS_COMPILE ?=$(CONFIG_CROSS_COMPILE:"%"=%)为:ARCH ?=armCROSS_COMPILE ?=arm-cortex_a8-linux-gnueabi-拷贝标准板配置文件$makes5pv210_defconfig配置内核$makemenuconfig SystemType---> (0)S3CUARTtouseforlow-levelmessages该命令执行时会弹出一个菜单,我们可以对内核进行详细的配置。这里我们先查看一下,内核都提供了那些功能!编译内核$makezImage通过上述操作我们能够在arch/arm/boot目录下生成一个zImage文件,这就是经过压缩的内核镜像。1.5.4嵌入式文件系统的移植一、根文件系统制作 源码下载我们选择的版本是busybox-1.17.3.tar.bz2下载路径为:/downloads/解压源码$tarxvfbusybox-1.17.3.tar.bz2进入源码目录$cdbusybox-1.17.3配置源码$makemenuconfigBusyboxSettings---> BuildOptions---> [*]BuildBusyBoxasastaticbinary(nosharedlibs) []ForceNOMMUbuild []BuildwithLargeFileSupport(foraccessingfiles>2GB) (arm-cortex_a8-linux-gnueabi-)CrossCompilerprefix ()AdditionalCFLAGS编译$make安装busybox默认安装路径为源码目录下的_install$makeinstall进入安装目录下$cd_install$lsbinlinuxrcsbinusr创建其他需要的目录$mkdirdevetcmntprocvartmpsysroot添加库将工具链中的库拷贝到_install目录下$cp/home/linux/arm-cortex_a8-linux-gnueabi/lib/sysroot/lib./-a删除静态库和共享库文件中的符号表$rmlib/*.a$rmlib/*.la$arm-cortex_a8-linux-gnueabi-striplib/*删除不需要的库,确保所有库大小不超过4M$du-mhlib/添加系统启动文件在etc下添加文件inittab,文件内容如下:#thisisrunfirstexceptwhenbootinginsingle-usermode.::sysinit:/etc/init.d/rcS#/bin/shinvocationsonselectedttys#startan"askfirst"shellontheconsole(whateverthatmaybe)::askfirst:-/bin/sh#stufftodowhenrestartingtheinitprocess::restart:/sbin/init#stufftodobeforerebooting::ctrlaltdel:/sbin/reboot在etc下添加文件fstab,文件内容如下:#devicemount-point type optionsdumpfsckorderproc /proc proc defaults 0 0tmpfs /tmp tmpfs defaults 0 0sysfs /sys sysfs defaults 0 0tmpfs /dev tmpfs defaults 0 0 这里我们挂载的文件系统有三个proc、sysfs和tmpfs。在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持修改内核配置:Filesystems---> Pseudofilesystems---> [*]Virtualmemoryfilesystemsupport(formershmfs) [*]TmpfsPOSIXAccessControlLists重新编译内核 在etc下创建init.d目录,并在init.d下创建rcS文件,rcS文件内容为:#!/bin/sh#Thisisthefirstscriptcalledbyinitprocess/bin/mount-aecho/sbin/mdev>/proc/sys/kernel/hotplug/sbin/mdev-s 为rcS添加可执行权限: $chmod+xinit.d/rcS 在etc下添加profile文件,文件内容为:#!/bin/shexportHOSTNAME=farsightexportUSER=rootexportHOME=rootexportPS1="[$USER@$HOSTNAME\W]\#"PATH=/bin:/sbin:/usr/bin:/usr/sbinLD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATHexportPATHLD_LIBRARY_PATH重要:新制作的文件系统尺寸若超出8M,删除不需要的库文件 二、NFS测试 1、删除原先的/source/rootfs $sudorm-rf/source/rootfs 2、将我们新建的根文件系统拷贝到/source/rootfs目录下$sudomkdir/source/rootfs $sudocp_install/*/source/rootfs–a 3、设置uboot环境变量#setenvbootcmdtftp20008000zImage\;go20008000#setenvbootargsroot=nfsnfsroot=00:/source/rootfsinit=/linuxrcconsole=ttySAC0,115200ip=00#saveenv重新启动开发板,查看是否能够正常挂载,功能是否正常1.6论文结构绪论本章主要是对数码相框系统进行一个背景和设计思路的一个总体阐述。相关技术介绍本章主要是对数码相框系统所需要的一些技术性的点进行一个统一的阐述。系统需求分析系统可行性分析系统概要设计系统详细设计系统测试结语相关技术介绍2.1基于CortexA8的嵌入式系统介绍嵌入式系统是以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。主要有系统内核小,专用性强,系统精简,高实时性的系统软件(OS)等特点。2.2图像处理技术介绍我们都知道,一个图片是由一个一个像素组成的,而一个个的像素都是由红,绿,蓝三种颜色组合而成。常用的图片格式处理如下:BMP是位图的存储格式,JPG是照片的存储格式,GIF是闪图的存储格式,PNG是一种无损压缩图片的格式。JPG格式是最常用的图像文件格式,是一种有损压缩格式,能把图像压缩在很小的存储空间,图像中重复或不重要的资料会被丢失。JPEG格式压缩的主要是高频信息,对色彩的信息保留较好,适合应用于互联网,减少图片传输时间,可以支持24bit真彩色,也普遍应用于需要连续色调的图像。PNG是网景公司开发的支持新一代WWW标准而制定的较为新型的图形格式,它综合了JPG和GIF格式的优点,支持24bit色彩(256*256*256),压缩不失真并支持透明背景和渐显图像的制作,所以称它为传统GIF的替代格式。在Web页面中,浏览器支持的格式有JPG、GIF和PNG。2.3Framebuffer设备驱动技术介绍在多媒体应用的推动下,彩色LCD越来越多地应用到了嵌入式系统中,掌上电脑(PDA)、手机等多采用TFT显示器件,支持彩色图形界面,能显示图片并进行视频媒体播放。帧缓冲(Framebuffer)是Linux为显示设备提供的一个接口,它允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。帧缓冲(framebuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。对于帧缓冲设备而言,只要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示,2.4USB设备驱动技术介绍2.5进程间通信技术介绍进程是操作系统中一个非常重要的概念,程序的运行是通过进程来完成的,在本系统中,我们用到了进程间通信技术的异步通知。异步通知的意思就是一旦系统设备准备好以后就主动的通知应用程序,这样,应用程序就不用查询系统设备的状态了。异步通知意味着设备通知应用程序自身可访问。一个用户在用户空间处理一个设备释放的信号,需要以下三个步骤:(1)通过F_SETOWN控制指令设置设备文件的拥有者为本进程,这样从设备驱动中发出的信号才能被本进程收到。(2)通过F_SETFLIO控制命令设置设备文件支持FASYNC,即异步通知模式。(3)通过signal()链接信号和信号处理函数。系统需求分析3.1业务描述随着PC时代数码技术的发展,数码相机以其低廉的价格,方便的操作成为摄影器材未来的发展方向。目前,很多家庭都持有数码相机,一次拍摄下来的照片往往会有上百张,使用PC机来查看拍摄下来的图片,操作繁琐,而且依赖于PC机。作为数码相机的一种附属产品,数码相框不仅具有传统相框的特点,而且可以直接从数码相机中选择心仪的照片,定时更新照片。数码相框是展示数码照片而非纸质照片的相框。众多的数码摄影产生的相片保存起来后,查看过程繁琐不方便,大量打印出来又非常浪费,如果用数码相框直接插上相机的存储卡展示照片,就非常简单。3.2系统目标(1)工作模式:团队设计的系统采用实时视频模式,在这种模式下系统通过摄像头获取视屏流,在用户下达指令后可以将(4)操作性:用户接口采用直接触摸LCD显示屏实现。(5)界面简洁,美观,直观易操作,友好,富于人性化,更加适合家居实用。3.3系统功能描述系统可以通过摄像头获取视频数据;用户可以通过LCD获取图像;用户可以通过摁下按键拍摄和查看图像;3.4系统性能需求摄像头精度要求:摄像头获取的视频流实时显示兼容性:数码相框应能识别和处理当前数码相机主要的图像格式,能访问主流的外部存储卡稳定性:系统稳定可靠3.5数据保存需求由于嵌入式设备上存储空间容量有限,所以系统采集的图片信息需要转存到相应的存储设备上,比如SD卡等设备上,这样用户可以很方便查看事件的记录,系统应该提供相应的接口,来实现相应的数据保存功能3.6流程图系统可行性分析4.1可行性研究的前提4.1.1系统基本需求当用户插入U盘时,系统会自动识别U盘里的图片,并将U盘里bmp和jpng格式的图片以800x480的大小在LCD液晶屏上显示出来。摄像头采集的视频流通过LCD液晶屏显示出来,并实现拍照的功能。4.1.2数据保存需求系统采集的图片信息需要转存到相应的存储设备上,用户可以查看之前的图片信息记录。4.1.3条件、假定和限制(1)用户接口屏幕的要求:直观性好,友好,富于人性化。(2)硬件接口摄像头硬件需求:支持设备的种类:ARM系列,并支持嵌入式linux操作系统。支持设备的方式:移植嵌入式linux系统和上层的用户的应用程序。(3)软件接口应用软件的需求:驱动程序:基于linux-3.0.8内核版本的驱动程序。4.2所建议技术可行性分析4.2.1对系统的简要描述当用户插入U盘时,系统会自动识别U盘里的图片,并将U盘里bmp和jpng格式的图片以800x480的大小在LCD液晶屏上显示出来。摄像头采集的视频流通过LCD液晶屏显示出来,并实现拍照的功能。4.2.2处理流程和数据流程4.2.3系统技术分析(1)对USB设备驱动的技术可行性分析USB设备类驱动可以包含多个,不同的功能接口对应不同的驱动程序,它们不直接与USB设备硬件打交道,而是通过协议软件的抽象处理来完成与设备的不同功能接口之间的通信。在Linux系统中,支持两种类型的USB驱动程序:USB主机端驱动程序和USB设备端驱动程序。其中,USB设备驱动程序是操作内核和机器硬件之间进行交互的接口,它为用用程序屏蔽了底层硬件的具体细节,我们开发的各种应用程序会把所有的硬件设备当做普通文件进行处理和相关操作。(2)对Framebuffer设备驱动的技术可行性分析 Framebuffer是一种驱动程序接口。Linux是工作保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的。(3)对MTD设备驱动的技术可行性分析在Linux系统中,提供了MTD系统来建立flash针对Linux的统一、抽象的接口。MTD将文件系统与底层的flash存储器进行了隔离,使flash驱动工程师无需关心flash作为字符设备和块设备与Linux内核的接口。在引入MTD后,Linux系统中的flash设备驱动及接口可分为4层,从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。底层flash驱动直接与MTD原始设备层进行交互,利用其提供的接口注册设备和分区。用于描述MTD原始设备的数据结构是mtd_info,这其中定义了大量关于MTD的数据和操作函数。drivers/mtd/mtdchar.c文件实现了MTD字符设备接口,通过它,用户可以直接操作flash设备。(4)对图像解码的技术可行性分析对于图像解码技术,本系统主要是对JPG格式的图片进行解码,使用libjpeg库对JPG格式的图片进行解码比较简单方便,libjpeg是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码、JPEG编码和其他的JPEG功能的实现。通过调用jpeglib库即可对图片进行解码,这样就可以将JPEG格式的文件解析出来。4.3所建议系统经济可行性分析序号功能数量单价1开发板1个8002U盘1个205摄像头模块1个30小计850系统概要设计5.1体系架构5.1.1系统架构系统的物理架构如图所示:5.1.2软件架构系统的软件架构如下所示:数码相框->|->驱动层代码->|->framebuffer驱动代码||->按键驱动代码|||->应用层代码->|->main.c->|->src(showjpegcamera)|->include(showjpegcamera)|->lib(jpeglib)5.2系统各模块概要设计5.2.1Framebuffer模块设计设计流程:Framebuffer->|->内核层代码->|->注册platformdevice||->注册platformdriver|||->用户层代码->|->打开fb设备,对其进行操作驱动层主要的结构体:fb_info结构体包括了对frambuffer设备驱动的属性和操作完整的描述fb_var_screeninfo

记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_fix_screeninfo中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址、长度。5.2.2图像处理模块设计设计流程解析常用图片->|->解析bmp图片(直接解析)|||->解析png图片(通过pnglib解析)||->解析jpeg图片(通过jpeglib解析)主要结构体Color结构体里面存放了描述像素的三种颜色 struct{ char blue; char green; char red; }color;5.2.3.按键模块设计设计流程Framebuffer->|->内核层代码->|->module_init(s5pv210_key_init);||->module_exit(s5pv210_key_exit);|||->用户层代码->|->通过异步通知来对按键事件进行处理主要结构体及函数文件操作结构体structfile_operationss5pv210_key_fops={ .owner=THIS_MODULE, .open=s5pv210_key_open, .release=s5pv210_key_release, .read=s5pv210_key_read, .fasync=s5pv210_key_fasync,};注册中断ret=register_chrdev_region(devno,number_of_device,"key");初始化中断cdev_init(&cdev,&s5pv210_key_fops);添加ret=cdev_add(&cdev,devno,number_of_device);注销 unregister_chrdev_region(devno,number_of_device);5.2.4拍照模块设计拍照模块->|->初始化摄像头->|->video_enable()||->摄像头获取数据->|->ret=ioctl(fd,VIDIOC_DQBUF,&buf);||->将YUV数据转化为jpeg数据->|->compress_yuyv_to_jpeg();||->将数据写到文件中->|->fwrite(dest,ret,1,fp);主要数据结构体typedefstructVideoBuffer{char*start;size_tlength;}VideoBuffer;typedefstruct{structjpeg_destination_mgrpub;/*publicfields*/JOCTET*buffer;/*startofbuffer*/unsignedchar*outbuffer;intoutbuffer_size;unsignedchar*outbuffer_cursor;int*written;}mjpg_destination_mgr;5.3主程序概要设计系统详细设计6.1Framebuffer模块详细设计6.1.1数据描述6.1.2函数描述6.2图像处理模块详细设计6.2.1数据流程6.2.2函数描述intread_jpeg_file(constchar*input_filename){structjpeg_decompress_structcinfo;//这个结构体对象包含了JPEG解压缩参数和一些工作函数的指针,JPEG库的API需要它。structjpeg_error_mgrjerr;//定义了一个错误处理的结构体FILE*input_file;//FILE*output_file;JSAMPARRAYbuffer;introw_width;unsignedchar*output_buffer;unsignedchar*tmp=NULL; initfb0();cinfo.err=jpeg_std_error(&jerr);//将错误处理结构对象绑定在JPEG对象上if((input_file=fopen(input_filename,"rb"))==NULL) {fprintf(stderr,"can'topen%s\n",input_filename);return-1;} //打开一个用于读取的二进制文件//初始化cinfo结构体。jpeg_create_decompress(&cinfo);//指定解压缩数据源jpeg_stdio_src(&cinfo,input_file);/*1.设置读取jpg文件头部,Readfileheader,setdefaultdecompressionparameters*/(void)jpeg_read_header(&cinfo,TRUE);/**在读取文件头后,开始解压缩之前可以对解压缩的参数进行设定*也就是对cinfo结构的成员赋值*//*2.开始解码数据Startdecompressor*/(void)jpeg_start_decompress(&cinfo);row_width=cinfo.output_width*cinfo.output_components;/*3.跳过读取的头文件字节,为缓冲区分配空间 *,JPOOL_IMAGE表示分配的空间将在调用finish后被释放 *row_width表示每行数据的实际大小 *1表示此处只分配了一行的数据*/buffer=(*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo,JPOOL_IMAGE,row_width,1); output_buffer=(unsignedchar*)malloc(row_width*cinfo.output_height); memset(output_buffer,0,row_width*cinfo.output_height);tmp=output_buffer;/*4.Processdata由左上角从上到下行行扫描 *output_scanline表示当前已经读取的行数,如此即可依次读出图像的所有数据 *并填充到缓冲区去,参数1表示的是每次读取的行数*/while(cinfo.output_scanline<cinfo.output_height) {(void)jpeg_read_scanlines(&cinfo,buffer,1);memcpy(tmp,*buffer,row_width);tmp+=row_width;} longintlocation=0; unsignedintx,y; struct{ char blue; char green; char red; }color; for(y=0;y<cinfo.output_height;y++) { for(x=0;x<cinfo.output_width;x++) { memcpy(&color,output_buffer,3); output_buffer=output_buffer+3; location=(x+vinfo.xoffset)*(vinfo.bits_per_pixel/8)+\ (y+vinfo.yoffset)*finfo.line_length; *((unsignedlong*)(fbp+location))=color.red|color.green<<8|color.blue<<16; } }(void)jpeg_finish_decompress(&cinfo);//解压缩完毕jpeg_destroy_decompress(&cinfo);//释放资源/*Closefiles,ifweopenedthem*/fclose(input_file); munmap(fbp,screensize); close(fbfd);return0;}6.3按键模块详细设计6.3.1数据流程6.3.2函数描述irqreturn_tkey_interrupt(intirqno,void*devid){ //printk("irqno=%d\n",irqno); switch(irqno) { caseIRQ_EINT(0):key=1;break; caseIRQ_EINT(1):key=2;break; caseIRQ_EINT(2):key=3;break; caseIRQ_EINT(3):key=4;break; caseIRQ_EINT(4):key=5;break; caseIRQ_EINT(5):key=6;break; caseIRQ_EINT(22):key=7;break; caseIRQ_EINT(23):key=8;break; } wake_up_interruptible(&readq); if(key_struct!=NULL) kill_fasync(&key_struct,SIGIO,POLL_IN); returnIRQ_HANDLED;}staticints5pv210_key_fasync(intfd,structfile*file,inton){ returnfasync_helper(fd,file,on,&key_struct);}staticints5pv210_key_open(structinode*inode,structfile*file){ intret; ret=request_irq(IRQ_EINT(0),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key1",NULL); if(ret<0) gotoerr1; ret=request_irq(IRQ_EINT(1),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key2",NULL); if(ret<0) gotoerr2; ret=request_irq(IRQ_EINT(2),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key3",NULL); if(ret<0) gotoerr3; ret=request_irq(IRQ_EINT(3),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key4",NULL); if(ret<0) gotoerr4; ret=request_irq(IRQ_EINT(4),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key5",NULL); if(ret<0) gotoerr5; ret=request_irq(IRQ_EINT(5),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key6",NULL); if(ret<0) gotoerr6; ret=request_irq(IRQ_EINT(22),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key7",NULL); if(ret<0) gotoerr7; ret=request_irq(IRQ_EINT(23),key_interrupt,IRQF_DISABLED|IRQF_TRIGGER_FALLING,"key8",NULL); if(ret<0) gotoerr8; return0;err8: free_irq(IRQ_EINT(23),NULL);err7: free_irq(IRQ_EINT(22),NULL);err6: free_irq(IRQ_EINT(4),NULL);err5: free_irq(IRQ_EINT(3),NULL);err4: free_irq(IRQ_EINT(2),NULL);err3: free_irq(IRQ_EINT(1),NULL);err2: free_irq(IRQ_EINT(0),NULL);err1: returnret;}staticints5pv210_key_release(structinode*inode,structfile*file){ free_irq(IRQ_EINT(0),NULL); free_irq(IRQ_EINT(1),NULL); free_irq(IRQ_EINT(2),NULL); free_irq(IRQ_EINT(3),NULL); free_irq(IRQ_EINT(4),NULL); free_irq(IRQ_EINT(5),NULL);free_irq(IRQ_EINT(22),NULL);free_irq(IRQ_EINT(23),NULL);s5pv210_key_fasync(-1,file,0); return0;}staticssize_ts5pv210_key_read(structfile*file,char__user*buf,size_tcount,loff_t*loff){ if(key==0xff) { if(file->f_flags&O_NONBLOCK) return-EAGAIN; } wait_event_interruptible(readq,key!=0xff); if(copy_to_user(buf,(char*)&key,sizeof(int))) return-EINVAL; key=0xff; returnsizeof(int);}structfile_operationss5pv210_key_fops={ .owner=THIS_MODULE, .open=s5pv210_key_open, .release=s5pv210_key_release, .read=s5pv210_key_read, .fasync=s5pv210_key_fasync,};staticints5pv210_key_init(void){ intret; devno=MKDEV(key_major,key_minor); ret=register_chrdev_region(devno,number_of_device,"key"); if(ret<0) returnret; cdev_init(&cdev,&s5pv210_key_fops); cdev.owner=THIS_MODULE; ret=cdev_add(&cdev,devno,number_of_device); if(ret<0) gotoerr1; init_waitqueue_head(&readq); return0;err1: unregister_chrdev_region(devno,number_of_device); returnret;}6.4拍照模块详细设计6.4.1数据流程6.4.2函数描述intgetjpeg(){FILE*fp;intret=0;char*videodevice="/dev/video3";intfd;intdev_fd;dev_fd=open("/dev/lig",O_RDWR|O_NONBLOCK);if(dev_fd<0){ perror("open"); exit(1);}ioctl(dev_fd,LIG_ON); structv4l2_capabilitycap;structv4l2_formatfmt;structv4l2_requestbuffersrb;if((fd=open(videodevice,O_RDWR))==-1){perror("ERRORopeningV4Linterface");return-1;}memset(&cap,0,sizeof(structv4l2_capability));ret=ioctl(fd,VIDIOC_QUERYCAP,&cap);//查询视频设备功能//printf("DriverName:%s\nCardName:%s\nBusInfo:%s\nDriverVersion:%u.%u.%u\n",cap.driver,cap.card,cap.bus_info,(cap.version)>>16&0xff,(cap.version)>>8&0xff,(cap.version)&0xff);if(ret<0){fprintf(stderr,"Erroropeningdevice%s:unabletoquerydevice.\n",videodevice);return-1;}if((cap.capabilities&V4L2_CAP_VIDEO_CAPTURE)==0){//是否支持capturefprintf(stderr,"Erroropeningdevice%s:videocapturenotsupported.\n",videodevice);return-1;}if(!(cap.capabilities&V4L2_CAP_STREAMING)){fprintf(stderr,"%sdoesnotsupportstreamingi/o\n",videodevice);return-1;}/*if(!(cap.capabilities&V4L2_CAP_VIDEO_OVERLAY)){fprintf(stderr,"%sdoesnotsupportOVERLAY\n",videodevice);return-1;}*/intinput=0;ret=ioctl(fd,VIDIOC_S_INPUT,&input);if(ret<0){perror("Unabletosetinput\n");return-1;}//显示设备支持的格式structv4l2_fmtdescfmtdesc;fmtdesc.index=0;fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//printf("Supportformat:\n");while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1){//printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);fmtdesc.index++;if(fmtdesc.index>14)break;}/**setformatin*/memset(&fmt,0,sizeof(structv4l2_format));fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.width=WIDTH;fmt.fmt.pix.height=HEIGTH;fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;//vd->formatIn;fmt.fmt.pix.field=V4L2_FIELD_ANY;ret=ioctl(fd,VIDIOC_S_FMT,&fmt);//设置视频数据格式,如长/宽/图像格式(yuyv/jpeg)if(ret<0){perror("Unabletosetformat");return-1;}if(ioctl(fd,VIDIOC_G_FMT,&fmt)==-1){printf("Unabletogetformat\n");exit(-1);}//printf("fmt.type:\t\t%d\n",fmt.type);//printf("pix.pixelformat:\t%c%c%c%c\n",(fmt.fmt.pix.pixelformat)&0xff,(fmt.fmt.pix.pixelformat>>8)&0xff,(fmt.fmt.pix.pixelformat>>16)&0xff,(fmt.fmt.pix.pixelformat>>24)&0xff);if((fmt.fmt.pix.width!=WIDTH)||//如果设置不成功,会自己修改,所以应再次检查(fmt.fmt.pix.height!=HEIGTH)){fprintf(stderr,"formataskedunavailablegetwidth%dheight%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height); }/**requestbuffers*/intn_buffers=0;memset(&rb,0,sizeof(structv4l2_requestbuffers));rb.count=COUNT;rb.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;rb.memory=V4L2_MEMORY_MMAP;ret=ioctl(fd,VIDIOC_REQBUFS,&rb);//请求v4l2驱动分配视频缓冲区,申请的内存位于内核空间,所以通过mmap映射到用户空间if(ret<0){ //v4l2是视频设备的驱动层perror("Unabletoallocatebuffers");return-1;}/*if(rb.count<2){printf("insufficientbuffsmemory");printf("Numberofbuffersallocate=%d\n",rb.count);}*//**mapthebuffers*/structv4l2_bufferbuf;structVideoBuffer*buffers=calloc(rb.count,sizeof(*buffers));//(width*height)*2(<<1));for(n_buffers=0;n_buffers<rb.count;n_buffers++){memset(&buf,0,sizeof(buf));buf.index=n_buffers;buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory=V4L2_MEMORY_MMAP;ret=ioctl(fd,VIDIOC_QUERYBUF,&buf);//readtobuf查询已经分配的v4L2的视频缓冲区的相关信息,通过QUERYbuf来获取获取内核空间中的视频缓冲区信息buffers[n_buffers].length=buf.length;//printf("buf.length=%d",buf.length);if(ret<0){perror("Unabletoquerybuffer");return-1;}//开始映射到用户空间buffers[n_buffers].start=(char*)mmap(NULL/*startanywhere*/,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);if(buffers[n_buffers].start==MAP_FAILED){perror("Unabletomapbuffer");}ret=ioctl(fd,VIDIOC_QBUF,&buf);if(ret<0){printf("VIDIOC_QBUF(%d)failed(%d)\n",n_buffers,ret);return-1;}}//执行成功时,函数指针返回0,执行成功后,指令的视频缓冲去进入输入队列,在启动视频拍摄图像时,相应的视频数据被保存到视频输入队列相应视频的视频缓冲区中video_enable(fd);//获得图像ret=ioctl(fd,VIDIOC_DQBUF,&buf);if(ret<0){printf("failedVIDIOC_DQBUFerror");return-1;}//保存图片charstr[50];charfilename[50]; structtm*timeinfo; time_trawtime; time(&rawtime); timeinfo=localtime(&rawtime); sprintf(str,"%d%d%d%d%d%d",(1900+timeinfo->tm_year),(1+timeinfo->tm_mon),timeinfo->tm_mday,timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec); sprintf(filename,"%s.jpg",str);if((fp=fopen(filename,"wb+"))==NULL)//打开文件 { perror("Cannotopenorcreatefile!"); }unsignedcharsrc[buf.length+1];unsignedchardest[buf.length+1];if(buf.index>=COUNT){printf("buf.index!<COUNT");return-1;}memcpy(src,buffers[buf.index].start,buf.length);ret=compress_yuyv_to_jpeg(src,dest,(WIDTH*HEIGTH),80);fwrite(dest,ret,1,fp);//写入文件inti=0;for(i=0;i<COUNT;i++){munmap(buffers[i].start,buffers[i].length);}ioctl(dev_fd,LIG_OFF);system("chmod777*.jpg");printf("picturenameis:%s\n",filename);close(dev_fd);fclose(fp);close(fd);read_jpeg_file(filename);return0;}6.5主程序详细设计6.5.1数据流程6.5.2函数描述#include"main.h"#include"showjpeg.h"#include"camera.h"voidhandler(intsigno){ intkey; read(keyfd,&key,sizeof(key)); if(key==3) { initfb0(); munmap(fbp,screensize);//清屏 close(fbfd); charaddr1[]="/"; //跳转工作目录 chdir(addr1); selectjpg(); jpgnum=0;//每次挑选后从第一张开始 }

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论