基于USB的数据采集系统的研究与设计--总结

2024-08-31

基于USB的数据采集系统的研究与设计--总结(精选7篇)

基于USB的数据采集系统的研究与设计--总结 篇1

基于 USB 的数据采集系统的研究与设计

目前,市场上有几百种 USB 设备,包括 USB 集线器、打印机、扫描仪器、存储器、数码相机和调制解调设备等。在数据采集系统中应用 USB2.0 接口总线,首先计算机系统要支持 USB2.0 协议。目前计算机几乎都支持 USB1.1 协议,如果支持 USB2.0 协议,那么系统的 USB 主机就必须包含USB2.0 根集线器,用于给系统提供一个或多个设备端口;同时,系统还必须安装相应的驱动程序。

USB总线的物理连接和电气特性

USB数据传输采用四根电缆,其中两根(D+、D-)是用来传送数据的串行通道,另两根(VBUS、GND)是符合标准的电源线,为下游的USB设备提供电源。其中,D+、D-是串行数据通信线,它支持两种数据传输速率,对于高速外设,USB以全速 12Mbps或高速 480Mbps传输数据;对于低速外设,USB则以 1.5Mbps的传输速率传输数据。USB总线会根据外设情况在不同的传输模式中自动地转换。VBUS通常是+5V电源,GND是地线。

USB 的电源

USB 的电源主要包括两方面:

电源分配:即 USB 的设备如何通过 USB 总线获得主机提供的电源; 电源管理:即通过电源管理系统,USB 的系统软件和设备如何与主机协调工作。

(1)电源分配

每段 USB 都在电缆上提供了数量有限的电源。主机向与它直接相连的 USB 设备提供电源,并且每个 USB 设备都有自己的电源。那些完全依靠电缆提供能源的设备称作“总线功能”设备。相反,那些有

另外电源的设备称作“自供电”设备。而且,集线器也可为连接在它上面的 USB 设备提供电源。

(2)电源管理

USB 主机与 USB 系统有相互独立的电源管理系统。USB 的系统软件和主机的电源管理系统相互作用,处理系统的电源事件,如挂起和恢复等。另外,USB 设备还有额外的功耗管理特性,允许软件对他们进行功耗管理。USB 总线拓扑结构

USB将USB设备和USB主机连接在一起。USB的物理互连是一个分层的星形拓扑结构,集线器在每个星形的中心。每段线路都是主机与集线器或功能设备之间,或者集线器与另一个集线器或功能设备之间的点对点连接 USB通信流

USB 在主机的软件和 USB 功能设备之间提供了通信服务。功能设备根据不同的客户软件与功能设备的相互作用对通信流有不同的要求。通过将 USB 功能设备的各种通信流分离,USB 能更好地全面利用总线。通信流利用总线访问来完成主机和功能设备之间的通信。通信流在设备的端点中止,设备的端点可以

识别所有通信流。

USB 逻辑设备对 USB 系统来说是一个端点的集合。接口是端点聚集而成的端点集,是功能设备的体现。USB 系统软件用默认的控制管道管理设备。客户软件用管道束(与端点集相关)来管理接口。客户软件要求数据通过USB在主机上的缓冲区和USB设备上的端点之间移动。而在 USB 上移动之前,由主机控制器(或者 USB 设备,由传输方向决定)将数据进行封装。当总线访问是在 USB 上移动数据包时,主机控制器也协同操作。

设备端点(Device Endpoint)

端点是 USB 设备唯一可识别的部分,是主机和设备间通信流的终点,每个 USB 逻辑设备都由独立端点集(这个集合就是接口)组成。当设备连接时,系统为每个逻辑设备分配了唯一的地址,设备的每个端点在设计时就给定了一个由设备决定的唯一的标识符—端点号。每个端点都有由设备决定的数据流方向。设备地址、端点号和方向的组合允许唯一指定一个端点,每个端点都单一的连接,支持一个方向的数据流输入(从设备到主机)或输出(从主机到设备)。

管道

USB管道是设备端点和主机软件之间的联系。管道可以通过存储器的缓冲区在主机软件与设备端点

之间传输数据。有两种相互独立的管道通信模式:

1.流:在管道中传输的数据没有 USB 定义的结构。

2.消息:在管道中传输的数据有某些 USB 定义的结构,只能用于控制传输。

帧和微帧(Frames and Microframes)

USB 工作在全速/低速状态时,主机控制器每隔 1 毫秒发送一帧数据;而工作在高速状态时,主机控制器每隔 125 微秒就发送一帧数据。一帧(或微帧)数据可包含几种事务。USB 数据传输类型是从 USB 系统软件的管理角度来描述的。传输(Transfer)是指在客户软件和它的功能模块之间的一个或多个信息传输的总线事务。传输类型决定于客户软件和它的功能模块之间的数据流特性。USB 定义了 4 种传输类型,以满足在总线上进行不同类型的数据的传输需要。

USB数据传输类型

批量传输用于传输突发的大量的数据,全速模式时以 8,16,32 或 64 字节(高速模式时是 512 字节)的信息包传送。由于对出错的数据自动的进行重发,批量数据可确保无误发送。

控制传输至少有两个阶段:建立阶段和状态阶段。控制传输也可以根据不同的情况选择是否需要在建立阶段和状态阶段包含一个数据阶段。

中断传输主要用于定时查询设备是否有中断数据要传输,是一种主机定时侦听设备。设备的端点

模式器的结构决定了它的查询频率,在 1-255ms 之间。中断传输在高速时的数据载荷可达 1023 字节,在全速时的载荷量小于 64 字节。中断传输主要应用于键盘、操纵杆和鼠。

同步传输用于保证时间优先的数据流,如音频和视频数据流,传输的时间对于数据来说是非常必要的条件,在全速模式时,一个同步包包含 1023 字节;在高速模式时,一个同步包包含 1024 字节。

数据采集系统的硬件

数据采集系统在总体上分为硬件和软件两大部分。数据采集系统的硬件部分

主要包括芯片的选择、数据采集和传输电路以及电源转换电路等。数据采集系统的软件部分主要由三部分组成:USB 固件程序(Firmware)、USB 设备驱动程序以及应用程序;三部分程序之间相互协作来完成整个采集系统的功能。

USB芯片选择

目前 USB 芯片大致分为 5 大类型:

1)单独运作的 USB 接口芯片;

2)内含 USB 单元的微处理器(MPU);

3)特定的接口转芯片,如 USB 转 RS-232 或 USB 转 ATA/ATAPI 等;

4)PC 端或主机端的 USB 控制器;

模数转换芯片的选择

目前,随着数据采集应用的日益普遍,为了满足不同场合和分辨率的要求,模数转换芯片也是种类繁多。选择 A/D 转换芯片需要考虑器件本身的性能和具体的应用要求。选择 A/D 转换芯片要考虑一些参数指标,如芯片精度、芯片的转换速度和芯片的转换量程等。

1)精度:与系统测量的信号范围有关,但估算时要考虑到其他因素,转换器位数应该比总精度要求的最低分辩率高一位。常见的 AD 器件有 8 位,10 位,12 位,14 位,16 位等。

2)速度:应根据输入信号的最高频率来确定,保证转换器的转换速率要高于系统要求的采样频率。

3)模拟信号类型:通常 AD 器件的模拟输入信号都是电压信号,而 DA 器件输出的模拟信号有电压和电流两种。

为了匹配 USB2.0 的高速传输特性,满足广泛的实际需要,本设计选用的是采样速度快、分辨率高的 A/D 转换器 MAX125。

数据采集系统的固件程序设计

固件程序主要负责完成两项任务:一是作为驻留在设备中的内部应用程序,响应主机的列举请求,实现配置设备并将设备的配置信息(如支持哪些传输类型和端点)告知主机,进而为主机和设备之间进行数据通信做好准备工作:二是作为整个设备的控制中心,根据用户应用系统的特定要求,实现对外围设备的具体控制。USB控制器芯片借助CPU执行固件程序来控制芯片的活动,以实现数据传输功能。固件的设计就是使在USB总线上的传输能获得快速的、有效的数据传输速度。它的操作方式与硬件联系紧密,包括USB设备的连接、列举、重列举、USB协议和中断处理等。

列举和重列举

列举和重列举是 USB 设备的一个非常重要的机制。是在初始阶段必须经历的阶段,只有这两个过程成功的完成,USB 设备才可能实现系统中设计的功能,否则,设备只能是一个主机不能识别的最原始的设备,或者是功能不完全的设备。

设备端点的配置

端点配置是在TD_Init()函数中实现的。USB数据通过端点缓冲区进入FX2 和从FX2 中取出。为了保证 480Mb/s高速的传输速率,外部逻辑经常在没有FX2 内嵌的CPU参与的情况下,直接与端点FIFO交换数据。USB设备启动时,要配置端点使它获得足够的带宽和FIFO深度,使数据传输更加平稳和高速。

当应用程序要求CPU处理外部逻辑和USB之间的数据流时(或者根本就没有连接外部逻辑时),固件可以将端点缓冲区作为RAM块或(使用特定的自动增量指针)FIFO访问。

设备驱动程序的组成驱动程序是一些例程的集合,它们被动的存在,等待主机系统软件(PnP管理器、I/O管理器、电源管理器等)来调用或激活它们。WDM驱动程序的功能模块基本由五个部分组成:入口例程,即插即用例程,分发例程,电源管理例程和卸载例程。

1.入口例程:处理驱动程序的初始化;

2.即插即用例程:处理 PnP 设备的添加,删除和停止;

3.分发例程:处理用户应用程序发出的各种 I/O 请求;

4.电源管理例程:处理电源管理请求;

5.卸载例程:处理驱动程序的卸载。

USB 设备驱动程序的开发

目前,用于开发设备驱动程序的工具大概有以下几种:

1.直接使用Windows DDK:这种方法开发难度大,而且有很多烦琐的工作要作,大部分都是通用的基础性的工作,但是,使用这种方法,需要对WDM驱动程序的整体结构有一个很好的认识和把握。

2.使用Driver studio:工具难度会低一些,工具软件己经作了很多基础性的工作。也封装了一些细节,使用者只需要专心去执行需要的操作。但由于封装的问题,可能会带来一些bug,有可能导致项目的失败。

3.使用Win Driver:几乎没有难度(从开发驱动的角度)。很容易,但只能开发硬件相关的驱动,事实上所写的只是定制和调用了它提供的通用驱动而已,工作效率不是很高。但开发花费的时间很少。

基于USB的数据采集系统的研究与设计--总结 篇2

传统用于电子测量的数据采集系统大都基于PC平台,存在成本高、携带不方便等缺点。随着移动互联网的高速发展,智能手机和平板电脑日益普及,特别是基于Andriod智能终端的应用已是大势所趋。本文结合CH9343和STM32F407VET6设计开发一款基于Android平台的数据采集系统。相较于传统数据采集系统,利用Andriod设备方便携带的特点,能够轻松应用于许多场合。而CH9343提供了Andriod通信的接口,降低了应用程序开发的难度,缩短了开发周期。

1 系统总体结构

如图1所示,整个系统由Andriod平台的应用软件和硬件采集器两部分组成。数据采集器主要由CH9343和组成,CH9343通过主端SPI接口与STM32F407VET6从端SPI接口相连,实现数据采集功能;Android设备端通过搭建JDK+Eclipse+ADT开发环境,通过调用USB接口的API,实现与数据采集器的通信,最终把数据采集器传来的数据信息,采用Open GL ES图形化之后,以APK软件界面的形式呈现给用户。

2 硬件设计

2.1 系统电源设计

考虑到CH9343是HOST主控端芯片,需要单独供电,同时可给整个数据采集系统和Andriod终端供电。电源电路如图2所示。

2.2 USB接口

CH9343是一款高度集成、低功耗USB Android Host接口控制芯片,支持全速USB传输(12 Mbps),兼容USB2.0。该芯片通过SPI主机模式,实现用户自己设计的应用电路与Andriod智能设备的桥接通信。采用SOP16封装。接口电路见图3所示。

2.3 数据采集单元设计

数据采集单元主要由STM32F407VET6处理器来完成。该处理器是基于高性能的CortexTM-M4的32位RISC内核,工作频率高达168 MHz。提供3个12位ADC,转换速度高达0.42 us。通过其他一些辅助电路构成一个优异的数据采集部分[2]。

2.3.1 参考电压源设计

ADC转换器参考电压电路如图4所示,ADC电源电压从VDDA引脚输入,ADC参考电压从VREF+引脚输入。为了提高转换精度,ADC配有独立电源,可以单独滤波并屏蔽PCB上的噪声。为了确保测量低电压时具有更高的精度,用户可以在VREF+上连接单独的ADC外部参考电压输入。VREF电压介于1.8 V到VDDA之间。

2.3.2 电压信号采样电路

利用STM32F407VET6内部集成的高速ADC实现数据采集。12位ADC是逐次趋近型模数转换器,多达24个复用通道。这些通道的A/D转换可在单次、连续、扫描或不连续采样模式下进行。ADC的结果存储在一个左对齐或右对齐的16位数据寄存器中。数据采集器,具有标准的电压、电流以及开关量输入信号采样接口。输入的电压信号经过电压信号调理电路对信号进行滤波、隔离和限幅后送入STM32F407VET6 VET6的AD采样通道。

2.3.3 SPI通信电路

STM32F407VET6具有3个SPI,速度高达37.5 Mbps,该接口须配置为从模式,在这种情况下,它与具有SPI主端的CH9343通信。如图5所示。

3 应用程序设计

3.1 数据采集器软件设计

数据采集器软件设计主要采用模块化程序设计,主程序流程图主要包括关中断、各功能模块初始化、开中断、开关量输入采集、采样处理等,程序流程如图6所示。

3.2 Android程序设计

Android系统是一个基于Linux的开源的软件系统,从低层到高层分别是Linux内核层、系统运行库层、应用程序框架层和应用程序层。Linux内核层提供了设备驱动和核心系统服务[1,2]。Android系统具有很多优点,它具有人性化的界面,使用体验更佳;Android系统比较稳定和完善,系统运行比较快捷;Android系统具有极大的开放性,它能够接纳各种应用程序,为程序的开发者和使用者提供了广阔的平台[3,4]。

3.2.1 设计框架

Android应用程序的开发是在Java框架和Java应用之间的接口之上开发出来的。直接使用CH9343芯片厂商接口函数,使得应用程序的开发比较容易。设计中选用SPI Master接口模式,将WCHSPIMaster Interface.java文件包含到Android工程,针对SPI Master的操作使用了Set Config、Send Data、Read Data和Reset等方法,并实现与CH9343芯片的通信。

基于CH9343开发的Android应用程序主要分为两个部分,如图7所示。

User Layout:主要由用户根据自己的需求完成相关代码,通过调用CH9343 Interface Layout提供SPI Master接口函数实现。

CH9343 Interface Layout:实现了SPI Master接口模式下的Interface类,提供给User Layout调用。此外还实现了Android Device和CH9343芯片之间的USB通信。

运用上述接口,根据不同采样类型,采样深度等需求设计软件功能界面,要求能够对增益、采样率、类型、通道数进行设置,功能简单实用,界面简洁、易懂,操作简便。

3.2.2 界面设计

界面设计包括设备控制部分,参数设置部分,数据采集部分以及图形显示部分。如图8所示。

3.2.3 功能设计

函数功能需实现增益、采样率、类型、通道数、采样深度功能的设置,如表1所示。

数据采集主要代码如下:

3.2.4 图形显示

软件图形显示部分采用了Open GL ES。首先Open GL是与硬件无关的软件接口,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、Mac OS、OS/2之间进行移植。因此,支持Open GL的软件具有很好的移植性,可以获得非常广泛的应用[6]。而Open GL ES是Khronos公司对标准的Open GL系统进行了维护和改动,形成一套为手持和嵌入式系统设计的3D引擎API。Open GL ES继承了许多Open GL的特色,其具有开放性的优点,让开发者能够更轻松地在行动平台上开发内容。使用Open GL ES能够极大满足用户对复杂数据图形化的多样需求[7,8]。

显示模块采用Open GL ES2.0版,通过调用其所提供的API,获取Display,初始化EGL,选择Config,构造Surface,创建Context,最后将采集到的数据以图形的方式显示给用户[9]。

Open GL ES简化了模型描述,取消了通过在gl Begin/gl End之间使用大量gl Vertex之类的调用来逐点描述模型[10],统一使用Vertex Array(顶点数组)来绘图。采集到的电压数据通过转换后,只需要创建一个Draw Line Activity,使用一个数组用于指定顶点数据(即电压值),之后在Draw Scene中通过GL_LINE_STRIP模式,将图形绘制出来。主要代码如下:

3.2.5 模拟运行效果

软件设计完毕,在Eclipse菜单中执行Run As→Android Application,将程序装入安卓模拟器当中,其运行结果如图9所示。

4 实物测试

根据电路原理设计出该采集系统的硬件电路并进行测试,测试采用纽曼M11平板电脑,搭载Android4.1.3和Linux3.4内核,在采样率10 kbps前提下,对外部0~3 V电压信号实际测试,8路测试数据见表2所示,并成功将采集到的数据转化为图形显示界面,如图10所示。

实验数据表明,本系统设计合理,运行可靠,数据测量准确、精度高且实时性较好。

5 结语

本文设计了一种Andriod USB高速数据采集系统。其中CH9343芯片是专门用于Android设备USB接口开发,结合ST公司的ARM芯片STM32F103ZE,该芯片包含丰富的功能模块,系统无需外扩芯片即可实现A/D转换、数据通信等功能,高速数据采集的特点,且大大简化了硬件设计,节约了投资。随着Android智能终端的普及,其应用快速地从传统的电话通信功能延伸到与嵌入式系统结合,可用于电力、铁路、航天、军事等诸多领域。本系统具有功耗低、可靠性高等优点,软硬件系统稍加变动,可以实现不同功能的应用。相信未来基于Android平台的应用会越来越丰富,应用领域会越来越广阔。

参考文献

[1]Shabtai A,Fledel Y,Kanonov U,et al.Google Android:a comprehensive security assessment[J].IEEE Security and Privacy,2010,8(2):35-44.

[2]Enck W,Ongtang M,Mc Daniel P.Understanding Android security[J].IEEE Security and Privacy,2009,7(1):50-57.

[3]范锋.Android的架构与应用开发研究[J].信息与电脑,2012(5):55-56.

[4]李林涛,石庆民.Android智能手机操作系统的研究[J].科技信息,2011(25):80,12.

[5]刘志骋,杨博.基于STM32的无线局域网数据采集系统[J].电子制作,2015(13):57-59.

[6]刘琪,迟贤书.Open GL与Open GL ES在开发过程中的异同[J].辽宁工程技术大学学报(自然科学版),2008,27(2):261-262.

[7]黄小凤,宋瑾钰,俞成海.基于Open GL ES的移动平台的三维模型绘制[J].工业控制计算机,2013,26(1):60-62.

[8]甘岚,李金标.Open GL ES及Qt/E在嵌入式系统中的研究与应用[J].微计算机信息,2009,25(12-2):68-70.

[9]谭熠帆.基于Open GL ES的嵌入式数控三维图形仿真系统的设计与实现[D].上海:上海交通大学,2012.

基于USB的数据采集系统的研究与设计--总结 篇3

关键词:USB接口;AT89S52微处理器;数据采集

数据采集技术是以传感器、信号测量与处理、微型计算机等技术为基础形成的一门综合应用技术,主要研究信息数据的采集、存储、处理以及控制等涉及模拟信号调理、模拟信号数字化、数字信号处理等方面,并具有很强的实用性。早期常见的数据采集系统一般通过传统接口如RS232串口、并口或PCI总线与PC机进行通信。串口连接方式简单,但传输速度有限;并口传输方式据线连接复杂,传输距离较近,而且在Windows环境下开发消息驱动方式麻烦;PCI总线已无法满足PC机发展的速度,过多的拍接口也会增加芯片成本,并且PCI扩展槽在PC机的内部,使用非常不方便。本论文所设计的基于USB接口的数据采集系统,引入了USB这种新型的通信接口,使得整个系统不再那么庞大,且连接方便支持即插即用,其数据传输速度远远高于普通的串口和并口,它的应用对采集系统的设计增添了亮点,也为USB外围设备的开发增加了经验。

1 USB协议介绍

USB(Universal Serial Bus,通用串行总线)是一种标准的连接接口,在把外围设备与计算机连接时,不必重新配置规划系统,也不必打开机壳和调整接口卡的指拨开关,会自动识别这些接口设备,并且配置适当的驱动程序,无需用户再重新配置。USB接口,实现了热插拔的特性,用户可迅速方便地连接PC主机的各种接口设备。另外,在连接PC机时,对所有USB接口设备,提供了一种“全球通用”的标准连接器(A型与B型),取代了各种传统外围端口,如串行端口、并行端口以及游戏接口等。同时USB接口还允许将多达127个外围设备同时串接到PC的一个外部的USB接口上。

2 系统设计

采用USB接口的数据采集系统由终端数据采集装置和上位机应用系统组成。其中数据采集装置以AT89S52微处理器组成。向前由A/D电路组成,向后采用USB接口电路与PC机连接。信号通过A/D转换单元转换成数据流,在单片机的控制下,通过USB接口向PC机传送数据。在PC机中运行数据处理程序,显示信号波形,且单片机也可受PC机的控制。其系统结构框图如图1所示。

3 USB接口电路设计

3.1 PDIUSBD12芯片简介

PDIUSBD12是一款性价比很高的USB器件。通常用在基于微控制器的系统,通过高速通用并行接口与微控制器进行通信,并且支持本地的DMA传输。该器件采用模块化的方法实现一个USB接口在众多可用的微控制器中选择最合适的作为系统微控制器,允许现存的体系结构并使固件投资减到最小。这种灵活性减少了开发时间、风险和成本,是开发低成本且高效的USB外围设备解决方案的一种最快途径。PDIUSBD12完全符合USBI.1规范,也能适应大多数设备类规范的设计:如成像类、大容量存储类、通信类、打印类和人工输入设备类等。因此,PDIUSBD12非常适合做很多外围设备,如打印机、扫描仪、外部大容量存储器和数据码相机等。

PDIUSBD12所具有的低挂起功耗连同Lazy Clock输出,可以满足使用ACPI、OnNOW和USB电源管理的要求,其低的操作功耗可以应用于使用总线供电的外设。此外,PDIUSBD12还集成了许多特性,包括SoftConnetTM、GoodLinkTM、可编程时钟输出、低频晶振和终止寄存器集合。所有这些特性都为系统节约了大量的成本,同时使USB功能在外设上的应用变得容易。

3.2 PDIUSBD12接口芯片与单片机AT89S52的连接

PDIUSBD12与单片机AT89S52的连接如上图2所示。AT89S52的8位数据通过并行方式发送到PDIUSBD12的8位数据线上,P2.3连接到CS_N,作为片选信号,中断请求信号由INT_N送出到INT1/P3.3引脚,由单片机AT89S52响应中断请求。其它引脚按照一般设置。

4 结束语

随着电子技术和计算机技术的高速发展,嵌入式系统的应用越来越广泛,较之各种传统接口速度比较慢、没有统一的标准、成本较高、占用空间的局限性,USB接口凭借其成本低,使用方便,支持即插即用,易于扩展,传输速率高等优点,势必在PC外围设备的应用中发挥越来越重要的作用。

参考文献

[1] 中国专利技术博览会..http://www.sinofint.com.cn .2004.

[2] MAX146,MAX147芯片手册.http://www.maxim-ic.com/quick_view2.cfm/qv_pk/1591,1997.

[3] 王朔,李刚.USB接口器件PDIUSBD12的接口应用设计.单片机与嵌入式应用,2002. (4):56-57.

基于USB的数据采集系统的研究与设计--总结 篇4

对于广大用户而言,与系统的交互是通过应用程序实现,而且整个实时采集系统的主要数据处理都是在这里完成的。因此,运行效率高、界面友好、具有强大数据分析和处理的应用程序的设计,也是系统设计上一个不容忽视的关键因素。应用程序的主要功能有:启动/关闭USB设备,检测USB设备,设置USB数据传输管道/端口,设置A/D,采集数据,显示/分析数据。这里,我们采用VisualC++6.0作为程序的开发环境,并且充分运用了多线程的编程思想。

在这个设备中,设置4个线程:首先是1个主线程,负责用户界面,并保持中枢地位。它的生存周期也就是整个用户程序的主存期,用户的动作(例如鼠标事件、键盘事件)都会触发主线程的消息机制,从而完成对用户的响应;而3个分离的辅助线程分别负责数据的采集、数据的分析处理以及数据的显示这3个不同的任务。辅助线程是在主线程运行过程中产生的,它的生命就是线程函数本身,函数一旦return,线程就结束了。因此,辅助线程的生存周期只是整个程序生存期的`一部分。

MFC程序只会有一个CwinApp对象,而CwinApp派生自CwinThread,即产生了应用程序的主线程。每当需要一个额外的线程时,应先产生一个CwinThread对象,再调用全局函数AfxBeginThread,将线程产生出来。

对于辅助线程(workerthread),要为它准备一个线程函数,然后调用AfxBeginThread。例如:CWinThread*pThread=AfxBeginThread(ThreadFunc,¶m);

UINTThreadFunc(LPVOIDpParam);//线程函数

对于用户界面线程(UIthread),不能够光由一个线程函数来代表,因为它要处理消息,它需要一个消息循环。应该先从CWinThread派生一个自己的类,再调用AfxBeginThread()产生一个CWinThread对象。网站

结语

基于USB的数据采集系统的研究与设计--总结 篇5

摘要

本文根据家庭视频采集系统的要求,提出一种基于ARM的网络视频采集方案。方案要求视频的实时传输、实时监控。本系统以Intel Xscale 芯片和嵌入式Linux系统为平台,在平台中搭建网络视频服务器,并以它为中介,负责将USB摄像头采集到得视频数据传输到网络服务器中,最后发送到申请监控的远程PC机中,远程PC只需在网页中便能实时的看到监控端的视频图像。

论文首先阐述了嵌入式网络视频采集技术的发展、现状和前景,然后介绍了嵌入式硬件系统结构和嵌入式Linux操作系统的特点,阐述了嵌入式硬件整体结构,使大家大体的完整的对系统硬件有详细的了解,实际记录了嵌入式操作系统内核的编译和移植,介绍了Bootloader的基本原理和启动过程,实现了视频采集程序的编译和移植,研究了嵌入式一般驱动程序的使用。随后,本文详细描述了视频采集程序的整体结构框图和具体功能代码块、网络通信编程技术、图像编解码、嵌入式视频服。

关键词:ARM;嵌入式;Linux;视频采集

I

目录

摘 要.............................................................................................................................I 第1章 引言.................................................................................................................1

1.1 课题的背景和来源..........................................................................................1 1.2本文的内容及主要工作..................................................................................1 第2章 嵌入式ARM系统硬件结构简介..................................................................3

2.1 视频监控系统结构简介..................................................................................3 2.2 ARM处理器简介.............................................................................................3 2.3 XSCALE体系结构............................................................................................4 2.4 主要硬件电路说明..........................................................................................7 第3章 嵌入式ARM系统软件结构..........................................................................9

3.1 LINUX操作系统简介.......................................................................................9 3.2 交叉编译环境的建立....................................................................................10 3.3 嵌入式LINUX操作系统移植........................................................................11 3.3.1 BootLorder移植...................................................................................11 3.3.2 Linux 内核移植...................................................................................12 3.3.3 嵌入式文件系统.................................................................................13 3.4 LINUX下的程序调试.....................................................................................14 第4章 USB设备驱动程序设计...............................................................................15 4.1 设备驱动程序简介........................................................................................15 4.2 LINUX下驱动程序的实现.............................................................................18 4.3 USB摄像头驱动程序设计............................................................................20 第5章 视频采集功能的设计...................................................................................23 5.1 基于V4L的编程...........................................................................................24 5.1.1 摄像头相关数据结构.........................................................................24 5.1.2 摄像头基本功能实现.........................................................................25 5.1.3 视频数据采集.....................................................................................29 5.2 图像编解码....................................................................................................32 5.2.1 编解码介绍.........................................................................................32 5.2.2 系统压缩技术.....................................................................................33

第1章引言

1.1课题的背景和来源

二十一世纪的网络化、数字化让人们的生活每天都发生着翻天覆地的变化,获取信息的方便和快捷可以使人们在信息化的今天领先一步创造出巨大的利益,而获取信息的重要途径就是眼睛。据统计,人类采集信息的80%来自视觉。图像和视频是对客观事物生动、形象的描述,是一种最直观的表现方式。而视频监控技术因为它方便快捷、生动形象、信息丰富等特点日益受到人们的青睐,并在各行各业得到广泛的应用。与此同时,现代网络和数字技术的快速发展也为视频监控技术的发展奠定了坚实的基础。

二十一世纪,嵌入式技术、多媒体处理技术进一步发展,为视频监控系统的发展提供了新的出路——嵌入式视频监控系统。嵌入式系统是以应用为中心,软硬件可以剪裁,具有高稳定、低成本、功耗低、速度快、实时好的专用计算机系统,它由嵌入式微处理器,配以周边硬件设备,接口电路组成。嵌入式系统内部使用嵌入式操作系统,安装专用的功能软件。嵌入式技术把硬件和软件集于一体,独立工作。嵌入式视频监控系统比其他视频采集系统在布局区域范围上要广泛;由于使用IP技术,嵌入式视频监控技术比其他视频采集系统更具紧密的结合度,能够充分利用现代网络技术的成果,并能构成复杂的视频监控网络;性能上,嵌入式视频采集系统继承了嵌入式技术的优点,非常适合自动化的环境。

因此,嵌入式视频采集技术正在我国快速的发展,积极的研究会加强我们在这方面技术的学习,也会为视频监控技术的发展贡献力量。

1.2本文的内容及主要工作

根据毕业设计的初衷,我们需要设计基于ARM的网络视频采集系统。在监控系统中,视频采集、传输、播放的功能不是由专门视频处理芯片完成,而是由软件实现。

论文首先介绍了嵌入式ARM系统的硬件结构和软件结构,方便大家熟悉ARM和Linux系统,包括嵌入式设备的硬件结构,逻辑框图和Linux的基本操作、安装方法;第二,研究了嵌入式的一些驱动程序,主要是摄像头驱动程序

V4L,系统中选用的摄像头芯片——中星微301;第三,研究了视频监控的具体流程和实现方式,让大家在总体上对整个系统有一个大概的认知。

本次设计的目的只有一个,就是实现视频的实时监控。围绕它,不管是硬件结构还是软件流程,都需要学习和研究,不断调试,决不放弃。

总之,论文的内容都是围绕如何建立一个视频采集系统。无论是从哪个方面,我们都是为这个目标而努力。2

第2章嵌入式ARM系统硬件结构简介

2.1视频监控系统结构简介

网络视频监控系统是基于嵌入式技术设计的。嵌入式并没有统一的定义,但目前有一个广泛而又被认可的规范:将软件产品固化到硬件平台上,完成应有的功能既是嵌入式。

基于嵌入式ARM技术的视频监控系统服务器端采用摄像头不断的采集图像,压缩成视频流,然后通过网络发送到申请监控的客户端。监控系统的使用者可以在远程实现网页上的实时监控和一些简单的功能操作。系统整体结构如图2.1所示[1]。

LCDJTAG摄像头ZC301CPU单元Intel Xscale以太网控制器远程PC客户端SDRAMFLASH

图2.1 系统整体结构图

该系统中CPU采用基于ARM的PXA270微处理器,通过在其上运行Linux操作系统,执行Boa视频服务器,接受并处理来自摄像头的图像信号,通过以太网控制器发送至远端,实现视频数据的远程传输和接受,达到视频监控的目的[2]。

2.2ARM处理器简介

ARM,既是一个公司的名字,也是对一类微处理器的通称。ARM嵌入式微处理器是全球领先的16/32位RISK处理器芯片知识产权设计供应商ARM(AdvancedRISKMachines)公司的产品。ARM公司本身不直接从事芯片生产,而是依靠转让设计许可,由合作公司生产各具特色的芯片。

ARM处理器以其完整的体系结构,极小的体积、极低的功耗、极低的成本、极高的性能,及时根据嵌入对象的不同进行功能上的扩展的优势,在众多种类的嵌入式微处理器中脱颖而出。基于ARM技术的微处理器应用占据了32位RISC微处理器75%以上的市场份额,ARM技术正在逐步渗入到我们生活的各个方面。

采用RISC架构的ARM微处理器一般具有如下特点:

(1)采用固定长度的指令格式,指令规整、简单、基本寻址方式有2~3种;(2)使用单周期指令,便于流水线操作执行;

(3)大量使用寄存器,数据处理指令只对寄存器进行操作,以提高指令的执行效率;

(4)所有的指令都可根据前面的执行结果决定是否被执行,从而提高指令的执行效率;

(5)可用加载/存储指令批量传输数据,以提高数据的传输效率;(6)可在一条数据处理指令中同时完成逻辑处理和移位处理;(7)在循环处理中使用地址的自动增减来提高运行效率。

目前,ARM处理器有ARM7、ARM9、ARM9E、ARM10、ARM10E、SecurCore、StrongARM和XScale等系列。每个系列除了具有ARM体系结构的共同特点以外,都有各自的特点和应用领域。

2.3XScale体系结构

Xscale核是采用ARM V5TE架构的处理器,是Intel公司的StrongARM的升级换代产品,它具有高性能、低功耗等特点,并在流水线设计、DSP处理和指令设计中有很大改进[3]。ARM的体系结构是基于RISK的,XScale是ARM处理器的一种,所以XScale具有RISK的基本特性。而且针对嵌入式系统,XScale构架还引入了Pentium处理器工艺和系统结构技术,实现了Pentium微处理器体系结构的一系列高性能技术,达到了高性能、低功耗和小体积等嵌入式系统要求的特性。它的特点有:超流水线、高主频、存储体系、分支预测和指令集体系结构。本设计采用的就是基于英特尔Xscale构架的一种32位嵌入式处理器,它除了应用于掌上电脑之中外,还可以应用于智能手机、网络存储设备、骨干网路由器等电子设备。

PXA27x系列处理器是英特尔当前最新推出的嵌入式处理器。它的时钟频率从312到624MHz不等,并内建64MB的堆栈型Intel StrataFlash内存。内置了英特尔的无线MMX技术,能够显著提升多媒体性能。

OURS-PXA270-EP是一款基于INTEL XSCALE PXA270处理器,针对高效

嵌入式系统教学和实验科研的平台。这款设备主要包括核心板与底版两个部分,核心板主要集成了高速的PXA270 CPU,配套的存储器,网卡等设备;底版主要是各种类型的接口与扩展口。

核心板(8层PCB电路)系统包括:

CPU: INTEL PXA270(520M),支持GDB调试; SDRAM: 64M 工作在104M外频上; FLASH: 32M INTEL Nor FLASH;Net: 10/100M Ethernet controller(LAN91C111);SUPERIO: WINBOND 83977;CPLD: XILINX 95144(117USER IO);总线驱动器: 若干;核心板正面如图2.2所示,核心板背面如图2.3所示。

SDRAMCPUdrvdrvCPLDdrvFLASHdrvdrvFLASHLDOdrv 图2.2 核心板正面图

SDRAMdrvEthernetdrvdrvdrv100PIN CONNECTORSuperIOLDO 图2.3 核心板背面图

底版(4层PCB电路)如图2.4所示。包括: Ethernet: 10/100接口1个

UART: 6个(包括RS232,RS485,IRDA,全功能串口)USB1.1:2个(1个host 一个device)PS2:2个(KEYBOARD&MOUSE)标准并口:1个 PCMCIA: 1个 IDE:1个 SD/MMC: 1个 SMC:1个 CAMERA:1个 96PIN功能扩展口:2个 4X5 小键盘

CPU_JTAG CPLD_JTAG LED SHARP LQ080V3DG01 8寸真彩LCD

640X480 VGA 640X480 LED 8X8点阵

一组7段LED数码管

4个

串口irda串口串口串口LCD接口LCD接口并口VGALED点阵音频1音频2音频3PCMCIA 卡LED数码管SMC 卡核心板SDPSPSUSBUSB485NET键盘 图2.4 底版图

2.4主要硬件电路说明

嵌入式设备除了以ARM芯片为主要控制单元,也有很多周边电路和外围设备,它们有的帮助ARM处理信号、有的负责存储数据、有的进行网络连接、有的用来数据通信,这些周边设备缺一不可,不能替代。

首先介绍CPU核心总线[4],总线是CPU和其他设备的桥梁。CPU是通过总线信号来控制SDRAM ,FLASH,网卡,SUPERIO等外部设备的,无论是低速还是高速,只要是与总线相关的芯片,都要和CPU总线信号有关。其次,研究嵌入式系统内存——SDRAM。SDRAM是嵌入式系统的内存,具有单位空间存储容量大和价格便宜的优点,已广泛应用在各种嵌入式系统中。当系统启动时,CPU首先从复位地址0x0处读取启动代码,在完成系统的初始化后,程序代码一般应调入SDRAM中运行,以提高系统的运行速度。同时,系统及用户堆栈、运行数据也都放在SDRAM中。SDRAM的存储单元可以理解为一个电容,总是倾向于放电,为避免数据丢失,必须定时刷新(充电)。因此,要在系统中使用SDRAM,就要求微处理器具有刷新控制逻辑,或在系统中另外加入刷新控制逻辑电路。PXA270芯片在片内具有独立的SDRAM刷新控制逻辑,可方便地与SDRAM接口。除了SDRAM,FLASH也是一种存储媒介。FLASH一般具有NOR型和NAND型。NAND型FLASH单元密度高,写入和擦除速度非常快,而且一般NAND型FLASH的存储容量很大。NOR型FLASH的优点是芯片内执行命令,这样应用程序可以直接在FLASH内运行,不用进入内存,使得它的传输效率很高。嵌入式设备最大的优点就是网络功能强大,它能像PC一样方便地连接到互联网上,这些功能都是网络控制器的作用。也就是Ethernet Controller,本系统采用SMSC公司的单芯片的网络控制器,LAN91C111。它可以工作在两种速度下,10M以太网或者100M以太网。LAN91C111的工作流程是,驱动程序将要发送的数据包按指定格式写入芯片并启动发送命令,LAN91C111会自动把数据包转换成物理帧格式在物理信道上传输;反之芯片收到物理信号后自动将其还原成数据,并按指定格式存放在芯片RAM中以便主机程序取用。就是LAN91C111完成数据包和电信号之间的相互转换。最后,说明一下串口电路,在嵌入式视频监控系统中,串口起到了很重要地作用,嵌入式系统启动的信息都可以通过串口传到PC上,极大地方便了系统的移植和软件的调试。大多数情况下,嵌入式CPU的串口0会作为CPU的一个终端,为用户与CPU交互提供基本的输出输入信息。当CPU运行BOOT代码时,通常只有这个终端 ;运行LINUX内核时,如果有LCD显示,串口0与LCD终端会同时有效。串口0终端的交互

方式是命令行的模式,在BOOT阶段,支持简单的BOOT命令。8

第3章嵌入式ARM系统软件结构

3.1Linux操作系统简介

Linux是一个类似Unix的操作系统,它起源于芬兰一个名为LinusTorvaldS的业余爱好者,现已成为最流行的一款开放源代码的操作系统。Linux从问世至今,短短时间内已发展成为一个功能强大、设计完善的操作系统。Linux系统不仅能够运行于PC平台,还在嵌入式系统方面大放光芒。由于Linux的源码开放,内核精简且性能强悍,不依赖于具体厂商,能广泛适用于各种硬件设备,系统二次开发成本极低,因此在IT业界已经达成共识,即采用嵌入式Linux作为嵌入式操作系统是大势所趋[5]。

嵌入式Linux是目前嵌入式系统领域中发展势头非常迅猛的系统。嵌入式Linux是指对Linux经过小型化裁剪后,能够固化在容量只有几百K字节或几M字节的存储器芯片或单片机中,应用于特定嵌入式场合的专用操作系统。目前正在开发的嵌入式系统中,49%的项目选择嵌入式Linux作为操作系统。嵌入式Linux现已成为嵌入式操作系统的理想选择[6]。目前基于嵌入式Linux的应用已经遍布很多领域,比如移动多媒体设备、手持设备、车载导航系统、机械控制等。嵌入式Linux分为两种类型:在没有使用MMU的平台上(无内存虚实地址转换和映射)的一般为uCLinux;而在有MMU平台上,则使用原本地嵌入式Linux版本。由于在目前的主流嵌入式ARM中大多不具有MMU,因此只用IM左右的内核就能实现网络功能和任务调度的Linux系统就可以适用于从高端服务器到嵌入式应用的各级平台。ARM技术和Linux成功地结合,应用于数以千计的商业产品中。从便携式消费品、网络和无线设备,到自动化设备、医疗设备和存储产品,这一应用列表与日俱增。ARM和Linux的结合充分满足了各类应用对嵌入式平台高性能、低功耗和低价格的要求,通过开发环境、开源社区和ARM的商业伙伴的优势为嵌入式开发提供了更灵活的选择。

本次设计的开发环境为redhat9.0系统,在Windows XP 下安装虚拟机,在虚拟机中安装Linux系统,这样可以屏蔽底层差别,避免硬件驱动带来的麻烦,而且还能方便的使用串口、并口、USB接口,快速的进入实验环境。图3.1为虚拟机下Linux系统启动后的情况。

图3.1 虚拟机下Linux操作系统

3.2交叉编译环境的建立

通常嵌入式系统的软件编译和执行是在两个不同平台上进行的。编译是在宿主机,一般为装有Linux的pc;执行是在目标机,即嵌入式系统的硬件平台。一般是在宿主机上通过跨平台交叉编译器把源文件编译成目标平台上可执行的文件,再通过串口、并口或者网络下载至目标平台上的FLASH或者其它存储介质,然后由目标机来运行这些软件。这里所说的跨平台编译器和一般的编译器功能类似,都是把源代码通过编译器编译成目标文件,然后通过链接器、可重定位器程序和定位器把目标文件重新定位成可执行文件。和通用的编译器之间最大的差别就在于跨平台编译器编译出来的可执行程序通常只能在特定CPU所属平台上运行。所以一般来说每种CPU都对应有不同的跨平台编译器。

本系统采用基于XScale的PXA270,可以使用常用的ARM-LINUX-GCC交叉编译器。要成功构建完整的交叉编译环境需要在宿主机上创建一系列的工具包括C/C++编译器、汇编器、链接器、嵌入式系统的标准C库和GDB代码级调试器。成功建立好开发环境后便可以运用这些工具进行嵌入式系统开发[7]。

3.3嵌入式Linux操作系统移植 3.3.1BootLorder移植

BootLoader是系统加电后运行的第一段代码。一般只是在启动时运行很短的时间,然而对一个嵌入式系统来说,这一部分却是整个系统的一个无比重要的组成部分,不可缺少。在一般嵌入式系统中,系统复位或者加电后通常从地址0x00000000处开始执行,而这个地址一般正是存放的BootLoader启动代码。通过这段程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终加载操作系统内核准备好正确的环境。

BootLoader一般情况下需要包含以下几个必备的功能 :(l)初始化处理器。这个动作都是用汇编语言完成的,称为重置码(resetcode)或者称为bootcode,而且对于每个CPU都不一样的,当电源接通后就会执行这个动作,通常只有两三个汇编指令,目的是将CPU的控制权转给硬件初始化的程序。

(2)初始化一些必要的硬件。这个动作也大都由汇编语言来完成,主要是初始化CPU、SDRAM等,其他的硬件,例如串口,可以由c语言等比较高级的程序语言来完成后续动作。

(3)设置处理器的寄存器以及内存,关掉所有的输入管脚(包括中断管脚),以防止突然有信号进入妨碍接下来的硬件初始化动作。然后初始化串口,以便后续运行的程序能够同HOST端进行通信,便于调试。

(4)从特定的位置把操作系统和文件系统调入内存,并设置一些操作系统所必需的参数,然后把CPU控制权交给操作系统。有的BootLoader会先从串口或者网络等其他途径得到内核的映像文件,然后把这些文件写入目标系统的FLASH或者其它存储介质,最后再把内核载入RAM执行,交出控制权。

一般BootLoader都包含两种不同的操作模式:“启动加载”模式和“下载”模式,这种区别仅对于开发人员才有意义。从最终用户的角度看,BootLoader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载模式的区别。

(l)启动加载(Bootloading)模式:这种模式也称为“自主”(Autonomous)模式,即BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时候,BootLoader显然必须工作在这种模式下。

(2)下载(Downloading)模式:在这种模式下,目标机上的BootLoader将通过串

口连接或者网络连接等通信手段从主机(HOST)下载文件,比如下载内核映像和根文件系统映像等。从主机下载的文件通常首先被BootL0ader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用,此外,以后的系统更新也会使用BootLoader的这种工作模式。工作于这种模式下的BootLoader通常都会向它的终端用户提供一个简单的命令行接口。

BootLoader的实现依赖于CPU的体系结构,一般来说启动过程分为两个阶段。

第一阶段依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在第一阶段中,而且通常都用汇编语言来实现,运行效率比较高。这个阶段完成的任务一般如下:(l)硬件设备初始化(屏蔽所有的中断、关闭处理器内部的指令/数据cache);(2)为第二阶段准备RA.M空间;(3)复制BootLoader的第二阶段代码到RAM空间中;(4)设置好堆栈并跳转到第二阶段的C程序入口点。

第二阶段则通常用C语言来实现,这样可以实现复杂的功能,而且代码会具有更好的可读性和可移植性。这个阶段主要任务有:(l)初始化本阶段要使用的硬件设备;(2)检测系统内存映射;(3)将内核映像和根文件系统从FLASH读到RAM中;(4)为内核设置启动参数;(5)调用内核文件运行。

本设计中的Bootloader采用Blob,Blob是Boot Loader Object的缩写,是一款功能强大的Bootloader。Blob最初是由Jan-Derk Bakker和Erik Mouw两人为一块名为LART(Linux Advanced Radio Terminal)的开发板写的,该板使用的处理器是StrongARM SA-1100,现在Blob已经被成功移植到许多基于ARM的CPU上了。本设计中的Intel Xcale就是采用Blob作为Bootloader[8]。

3.3.2Linux 内核移植

选用嵌入式Linux作为目标机操作系统,一方面由于Linux是一款免费的操作系统,能很好的降低成本,同时Linux的开发应用现在已经成为热门,有大量的资源可用于学习与重复应用,并且Linux系统具有良好的可移植性和可裁剪性,能自动支持多任务管理。一般常用的GUI如QT/E,MiniGUI等都支持Linux。

Linux的开发工具也都可以很方便的免费获得。

系统采用的嵌入式Linux内核为随实验平台光盘中的Linux内核,它是针对这套实验平台所配置的Linux内核,内核版本为Linux2.4.20[9]。在实验过程中,只需要在这个内核的基础上进行添加和删减所需要和不需要的功能,编译后就可以使用了。

在编译内核之前,需要对内核进行必要的配置,通过虚拟机进入/pxa270_linux/linux/目录后在终端执行make menuconfig[10]命令,就可以可视化的配置内核需要的功能和要求,本次试验,主要是针对视频方面,选择了对V4L的静态加载、对spca5xx摄像头驱动的动态加载,这样就结束了对内核的配置。编译内核需要创建内核依赖关系、创建内核镜像文件和创建内核模块。首先执行makedep命令,读取配置过程生成的配置文件,来创建对应于配置的依赖关系树,从而决定哪些需要编译而哪些不需要;接着需要makeclean删除前面步骤留下的文件,以避免出现一些错误;然后便可以生成所需要的内核文件了,用make zlmage来实现得到可移植的内核。内核文件通过并口下载线烧写入开发板中,便可以通过BootLoader加载运行。

3.3.3嵌入式文件系统

嵌入式Linux操作系统一般采用FLASH作为存储介质。FLASH具有独特的物理特性,所以必须使用专门的嵌入式文件系统。嵌入式系统对文件的操作是通过层次结构实现的。对于用户程序来说,文件是有结构的文件,用户程序通过对文件IO函数操作文件。嵌入式文件系统是嵌入式操作系统的一部分,它的任务是对逻辑文件进行管理,其工作包括提供对逻辑文件的操作(复制、删除、修改等)接口,方便用户操作文件和目录。在文件系统内部,根据存储设备的特点,使用不同的文件组织模式来实现文件的逻辑结构。此外,文件系统要对管理文件的安全性负责。文件系统不能直接控制物理设备,它是通过FLASH驱动实现控制的[11]。

目前FLASH支持的文件系统技术主要有JFFS2,YAFFS2,TrueFFS,FTL/NTFL,RAMFS,CRAMFS和ROMFS等等。本系统采用的是JFFS2文件系统。

JFFS2文件系统是专门为NAND闪存设计的嵌入式文件系统,根据NAND闪存以页面为单位存取的特点,将文件组织成固定大小的数据段。利用NAND闪存提供的每个页面16B的备用空间来存放ECC(ErrorCorrectionCode)和文件系统的组织信息、,不仅能够实现错误检测和坏块处理,也能够提高文件系统的加

载速度。JFFS2采用一种多策略混合的垃圾回收算法,结合了贪心策略的高效性和随机选择的平均性,达到了兼顾损耗平均和系统开销的目的。它是日志结构的文件系统,提供了损耗平衡和掉电保护,可以有效地避免意外掉电对文件系统一致性和完整性的影响。JFFS2文件系统是按层次结构设计的,分为文件系统管理层接口、JFFS2内部实现层和NAND接口层,这样就简化了其与系统的接口设计,可以方便地集成到系统中去。与YAFFS相比,它增加了一些功能,因此功能更强。

3.4Linux下的程序调试

调试是程序开发过程中必不可少的一个重要环节,通用PC机的程序调试与嵌入式操作系统的调试环境上有着明显的区别,前者调试器和被调试的程序往往是运行在同一台机器上,是相同操作系统下的两个不同的进程,调试器通过操作系统专用调用接口控制被调试进程,后者通常为远程调试,调试器一般运行于桌面操作系统上,而被调试的程序则运行在嵌入式系统之上,因此需要协调这两个程序之间的通信。Linux下的调试工具非常的少,gdb是Linux下最著名的调试工具,它是GNUC自带的调试工具,它可以使开发人员了解程序运行的详细细节,从而消除程序的错误,达到调试的目的,gdb还具有远程调试功能,可以满足嵌入式系统调试的要求,在调试过程中PC机也称为宿主机和嵌入式系统通过串口协议或者TCP/IP协议连接起来,远程主机上运行被gdb规范断点改造过的内核,当条件成立时,断点被激活,然后等待本地宿主机的连接命令,一旦连接成功,宿主机就可以向远程嵌入式系统发送调试命令了。在调试过程中gdb通过调试stub来完成通信功能,调试stub是嵌入式操作系统中的一小段代码,它提供了运行gdb的宿主机和嵌入式系统进程之间交互的一个媒介。

除了使用调试器外还可以直接在程序中使用printf()或printk打印函数,这种方法功能比较弱,效率低下,但在内核模块调试时这是唯一的方法。14

第4章USB设备驱动程序设计

4.1设备驱动程序简介

Linux系统中,设备驱动程序扮演着特殊的角色。它就像一个独立的黑盒子一样,使某个特定的硬件可以相应一个定义良好的内部编程接口并且完成隐藏设备的作用。用户只需调用一组标准化的函数完成操作,而且这些操作与特定的驱动程序无关。驱动程序的任务就是将这些函数映射到作用硬件的具体操作上。这样的模块化的驱动程序结构使得Linux系统中的驱动程序可以独立于内核的其他部分,可以在需要使用的时候将驱动“插入”内核。

从系统运行顺序来看,硬件平台启动运行Linux后,启用了MMU单元即内存管理单元,在这种模式下系统不能直接对物理地址进行访问。若要对某一硬件外设进行读写,需要通过内核调用该硬件的驱动来实现。

上面已经说过,驱动程序的作用在于向应用程序提供访问硬件设备的接口,驱动程序屏蔽了硬件实现上的细节操作,于是应用程序可以像操作普通文件一样对硬件设备进行操作。Linux以模块的形式加载设备类型,通常是一个模块对应实现一个设备驱动。模块是内核的一部分,它们没有被编译到内核中,而是分别被编译并链接成一组目标文件。可以根据用户的需要在不需要对内核进行重新编译的情况下动态载入正在运行的内核,或从正在运行的内核中卸载。利用这种机制,内核尺寸可以保持在最小,并具有最大的灵活性,也便于检验新的内核代码,而不需要重新编译内核并重新引导。设备驱动程序一般需要完成以下功能:(l)对设备初始化和释放;(2)把数据从内核传送到硬件和从硬件读取数据;(3)读取应用程序传送给设备文件的数据和回送应用程序的请求数据;(4)检测和处理设备出现的错误。

在Linux操作系统下有两类主要设备文件类型:块设备、字符设备。用户进程正是通过设备文件来与硬件打交道。每个设备文件都有其文件属性,表示是字符设备还是块设备。另外每个文件都有2个设备号,第一个是主设备号,标识驱动程序;第二个是从设备号,标识使用同一个设备驱动程序的不同硬件设备。设备文件的主设备号必须与设备驱动程序在登记时申请的设备号一致,否则用户进程将无法访问驱动程序。

Linux驱动程序可以分为三个主要部分: 15

(l)自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和能否正常工作。如果该设备正常,则对这个设备及其他必需的条件位口中断、DMA通道)进行申一请并初始化。这部分驱动程序仅在初始化时被调用一次。

(2)服务于I/O请求的子程序,又称为驱动程序的上半部分。调用这部分程序是由于系统调用的结果。这部分程序在执行时,系统仍认为是与进行调用的进程属于同一个进程,只是由用户态变成了核心态,但仍具有进行此系统调用的用户程序的运行环境,因而可以在其中调用与进程运行环境相关的函数。

(3)中断服务子程序,又称为驱动程序的下半部分。在Linux操作系统中,并不是直接从中断向量表中调用设备驱动程序的中断服务子程序,而是由Linux系统来接收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个进程运行时产生,因而在中断服务子程序被调用时,不能依赖于任何进程的状态,也就不能调用任何与进程运行环境有关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务子程序时,都带有一个或多个参数,以唯一标识请求服务的设备。

在系统内部,I/O设备的存取通过设备驱动程序提供的一组固定的入口点来进行,这组入口点在驱动程序初始化时向系统进行登记,以便在系统适当的时候调用。一般来说,字符型设备驱动程序能够提供如下几个入口点:(1)open入口点:打开设备准备I/O操作,对字符特别设备进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备的状态。

(2)close入口点:关闭一个设备,当最后一次使用设备结束后,调用dose子程序。独占设备必须标记设备可再次使用。

(3)read入口点:读取设备,对于有缓冲区的I/0操作,一般从缓冲区里读取设备数据。

(4)write入口点:向设备写数据,对于有缓冲区的I/O操作,一般向缓冲区里写入数据。

(5)ioctl入口点:执行读写之外的操作。

USB(Universal Serial Bus)即“通用串行外部总线”,用途广泛,可以外接硬盘、键盘、鼠标、打印机等多种设备,USB能够使用尽可能少的接口支持尽可能多的外设,尤为适合在嵌入式设备中使用,是嵌入式接口标准的一个很好的选择。

USB总线规范有1.1版和2.0版。USB1.1支持两种传输速率:低速1.5Mbit/s、全速12Mbit/s,这样的速率完全满足鼠标、键盘、CD-ROM等设备,但是在嵌入式视频监控系统中,这样的速度还是很慢。所以,USB2.0提供了一种更好的传输速率:高速,它可以达到480Mbit/s。USB2.0向下兼容USB1.1,可以将遵循USB1.1规范的设备连接到USB2.0控制器上,也可以把USB2.0的设备链接到USB1.1控制器上。

USB总线的硬件拓扑结构[12]如图4.1所示。

USB主机控制器USB设备根集线器USB设备USB设备集线器USB设备集线器USB设备集线器USB设备USB设备USB设备USB设备 图4.1 USB总线硬件拓扑图

USB主机控制器通过根集线器与其他USB设备相连。集线器也属于USB设备,通过它可以在一个USB接口上扩展出多个接口。除根集线器外,最多可以层叠5个集线器,每条USB电缆的最大长度是5m,所以USB总线的最大距离为30m。一条USB总线上可以外接127个设备,包括根集线器和其他集线器。整个结构图是一个星状结构,一条USB总线上所有设备共享一条通往主机的数据通道,同一时刻只能有一个设备与主机通信。

通过USB主机控制器来管理外接的USB设备,USB主机控制器共分3种:UHCI、OHCI和EHCI。在配置Linux内核的时候,看到的“HCD”字样表示“Host Controller Drivers”,即主机控制器驱动程序。

USB驱动程序分为两类:USB主机控制器驱动程序(Host Controller Drivers)、USB设备驱动程序(USB device drivers)。它们在内核中的层次如图4.2所示。

UserUSB Device DriversUSB Host Controller DriversHardware 图4.2 USB驱动程序层次结构

在试验中,教学平台上的Linux嵌入式内核已经配置了USB主机控制器驱动程序,只需要添加需要的USB设备驱动程序,就能实现USB设备的正常使用。

4.2Linux下驱动程序的实现

Linux操作系统下对硬件设备进行驱动开发的一般步骤如下:(l)注册设备

在系统启动时或者在模块加载的时候需要将设备和重要的数据结构登记到内核的设备数组中,并确定该设备的主次设备号。在Linux系统中,对于字符设备一般通过调用register_chrdev向系统注册设备驱动程序,register_chrdev在fs/deviees.c文件中的定义如下:int register_chrdev(unsigned int major,const char*name,struct file_operations fops)定义中的major是设备驱动程序向系统申请的主设备号,如果major为O,则系统为该驱动程序动态的分配一个主设备号,不过此设备号是临时的;name是设备名:fops是各个调用入口点的说明。函数返回O表示注册成功,返回-INVAL表示申请的主设备号非法,返回-EBUSY表示申请的主设备号正在被其它设备驱动程序使用。

以后对设备驱动程序的file_operations的操作都可以通过该主设备号的索引来完成。register_chrdev函数操作成功后,设备名便出现在/proc/devices文件目录中,使用命令cat/proc/devices可以查看设备的工作状态。

(2)定义操作集

驱动程序中要通过一系列函数完成对设备的不同操作,这些操作在面向对象编程术语中也称为方法,该操作集通过数据结构file_operations实现。内核内部通过file结构识别设备,通过file_operations数据结构提供的文件系统的入口点函数访问设备。

file_operations定义在中的函数指针表: struct file_operations { struct module*owner;loff_t(*llseek)(struct file*, loff_t, int);ssize_t(*read)(struct file*, size_t, loff_t*);ssize_t(*write)(struct file*, const char*, size_t, loff_t*);int(*readdir)(struct file*, void*, filldir_t*);unsigned int(*poll)(struct file*, struct poll_table_struct*);int(*ioctl)(struct inode*, struct file*, unsigned int, unsigned long);int(*mmap)(struct file*, struct vm_area_struct*);int(*open)(struct inode*, struct file*);int(*flush)(struct file*);

int(*release)(struct inode*, struct file*);int(*fsync)(struct file*, struct dentry*, int datasync);int(*fsyne)(int, struct file*, int);int(*lock)(struct file*,int, struct file_lock*);ssize_t(*readv)(struct file*, const struct iovec*, unsigned long, loff_t*);ssize_t(*writev)(struct file*, const struct iovec*, unsigned long, loff_t*);ssize_t(*sendpage)(struct file*, struct page*, int, size_t, loff_t*, int);unsigned long(*get_unmapped_area)(struct file*, unsigned long, unsigned long,unsigned long, unsigned long);}

这个结构的每一个成员的名字对应一个系统调用,在用户程序利用系统调用对设备文件进行诸如读/写操作时,系统调用会通过设备文件的主设备号找到相应的驱动程序,然后读取这个数据结构的相应函数指针,把控制权交给该函数。对于具体的设备驱动并不需要实现结构中所有的例程,只要完成设备功能就可以了。例如对于一个常见的字符设备驱动来说,可能只有操作open(),write(),read(),ioctl()和close(),当用户程序通过系统调用访问设备时,最终要通过这些操作集来完成。

(3)卸载模块

当不再需要使用一个模块或设备时,需要将其从内核中卸载下来,这时会动态调用模块中的module_exit()函数,并需要在该函数中调用modul_unregister_chrdev()或module_unregister_blkdev()释放挂入内核的数据结构同时释放该设备号。

4.3USB摄像头驱动程序设计

摄像头属于视频设备,在Linux内核中,VideoforLinux(简称V4L)是关于视频设备的驱动标准。这个标准为应用程序定义了一系列的接口函数,内核、驱动和应用程序都是依靠这个标准来进行交流。本系统所使用的USB摄像头正是基于该标准来编写驱动和应用程序的。

Linux内核是依据设备号来操作设备文件的,在内核中,摄像头对应的设备文件名为/dev/video0,主设备号是81,次设备号根据摄像头数目来确定,本系统中仅使用一个摄像头,所以可以通过mknod/dev/video0 c 81 0来创建节点。USB摄像头驱动程序实现原理如图4.3所示。

USB摄像头的驱动和通用设备的驱动准则一样,但需要与内核提供的视频驱动挂钩。即首先在驱动中声明一个 video_device结构,并为其指定文件操作函数指针数组fops,向系统注册。在应用程序发出文件操作的相关命令时,核心根据这些指针调用相应函数,并将该结构作为参数传递给它们。这样,就完成了驱动和核心之间的通信。

例如: Static struct video_devie vdev_template={……};

声明 video_deviee,指出挂接驱动

用户进程系统调用摄像头驱动文件操作接口接收缓冲区发送缓冲区中断服务程序摄像头 图4.3 摄像头驱动实现框图

Static Struct file_operation spcasxx_fops= {……};

声明本驱动的文件操作函数指针 Struct video_device*vdev=video_devdata(file);从文件指针中提取出 video_deviee结构

在video_deviee结构中,有一个私有指针priv,可以将它指向一块保留内存。在这块内存中,保存着本驱动、本设备的相关初始化信息。这块内存的申请、初始化、指针指向等工作都是在USB驱动的枚举函数probe中完成。这样,在枚举函数将控制权返还给系统后,因为内核不销毁保留内存,所以驱动仍然保留着自己的信息。在驱动卸载函数中需要将申请的各块内存全部释放。

Linux系统中任何USB传输都通过URB实现。为提高速度,可以考虑扩大URB的缓冲,这样可以降低每个USB事务中握手信息所占比例,提高有效数据的输速度。但是受限于总线带宽和具体的USB设备芯片,单纯扩大URB的缓冲不能无限制地解决问题。USB在操作系统中每次传输都要包括URB的建立、发出、回收、数据整理等阶段,这些时间不产生有效数据。因此可以建立两个URB,在等待一个URB被回收时,也就是图像正在被传感器采集时,处理、初始化另一个URB,并在回收后立刻将其发出。两个URB交替使用,大大减少了额外时间。

由于嵌入式平台上运行的Linux2.4.20内核,内部已经集成了对USB2.0的支持,所以无需移植相应的USB驱动。

在设计中,摄像头芯片采用中星微的Z301系列芯片,Linux2.4内核并不支持这种芯片,所以我们通过移植芯片驱动程序来达到目的。芯片的驱动程序是spca5**系列,如果不重新编译内核的话,将驱动程序动态加载就可以正常使用。设计中动态加载的命令使用insmod命令,它和modprobe命令在使用上有所不同,modprobe在加载模块时不用指定模块文件的绝对路径,也不用带模块文件的后缀.o或.ko;而insmod需要的是模块的所在目录的绝对路径,并且一定要带有模块文件名后缀的.o或者.ko。但是在功能上,它们所达到的效果基本相同[13]。22

第5章视频采集功能的设计

视频采集程序是基于V4L开发的,包括摄像头的初始化、打开/关闭、参数设置和数据读取等操作,视频采集程序流程图如图5.1所示[14]。

开始初始化摄像头init_videoIn()打开摄像头open_v4l()获取摄像头参数icotl(int->vd,int cmd,..)设置摄像头参数ioctl()获取一帧图像N一帧是否截取完毕Y存储并准备传输N是否终止视频采集Y关闭摄像头终止 图5.1 视频采集程序流程图

5.1基于V4L的编程 5.1.1摄像头相关数据结构

摄像头的组成部分是传感器、DSP、镜头、外壳、USB连线、电路板和周边电路构成,其中最重要的是传感器和DSP(数字信号处理器)。本系统选用的摄像头采用了CMOS传感器和中星微301处理器。

V4L[15]提供了一系列的接口应用程序,可以利用这些程序实现对摄像头的调用,其中有read、open、ioctl等。V4l同时将这些函数和参数封装成一个数据结构vdIn。struct vdIn {

int fd;char *videodevice;struct video_mmap vmmap;struct video_capability videocap;int mmapsize;struct video_mbuf videombuf;struct video_picture videopict;struct video_window videowin;struct video_channel videochan;struct video_param videoparam;

int cameratype;char *cameraname;char bridge[9];int sizenative;int sizeothers;int palette;int norme;int channel;int grabMethod;unsigned char *pFramebuffer;unsigned char *ptframe [4];

};int framelock [4];pthread_mutex_t grabmutex;int framesizeIn;volatile int frame_cour;int bppIn;int hdrwidth;int hdrheight;int formatIn;int signalquit;

int fd :打开摄像头时,open函数返回的文件描述符,其他函数使用这个描述符对摄像头进行操作。

struct video_mmap vmmap: 用于内存映射的结构体。

struct video_capability videocap :描述摄像头基本信息,如设备名称、支持的最大分辨率、信号源信息、信道数等。

struct video_mbuf videombuf :在进行内存映射时读取帧的信息,实际上是输入到摄像头存储缓存中的帧信息。

struct video_picture videopict :摄像头采集图像的属性,如亮度、色调、对比度、色度、深度等。

struct video_window videowin :表示采集窗口参数,如分辨率等。struct video_channal videochan :关于信号源的属性。

5.1.2摄像头基本功能实现

(1)初始化摄像头参数

在对摄像头进行操作之前,要对摄像头进行初始化,即对vdIn这个结构进行初始化。使用init_videoIn 函数。

int init_videoIn(struct vdIn *vd, char *device, int width, int height, int format, int grabmethod){

int err =-1;int i;if(vd == NULL || device == NULL)return-1;

} if(width == 0 || height == 0)return-1;grabmethod = 1;//read by default;if(grab method < 0 || grabmethod > 1)// check format

vd->videodevice = NULL;vd->cameraname = NULL;vd->videodevice = NULL;vd->videodevice =(char *)realloc(vd->videodevice, 16);vd->cameraname =(char *)realloc(vd->cameraname, 32);snprintf(vd->videodevice, 12, “%s”, device);if(debug)printf(“video %s n”,vd->videodevice);memset(vd->cameraname, 0, sizeof(vd->cameraname));memset(vd->bridge, 0, sizeof(vd->bridge));vd->signalquit = 1;vd->hdrwidth = width;vd->hdrheight = height;vd->formatIn = format;

vd->bppIn = GetDepth(vd->formatIn);vd->grabMethod = grabmethod;vd->pFramebuffer = NULL;err = init_v4l(vd);for(i = 0;i < OUTFRMNUMB;i++){

} vd->frame_cour = 0;pthread_mutex_init(&vd->grabmutex, NULL);return err;vd->ptframe[i] = NULL;(unsigned char *)realloc(vd->ptframe[i], sizeof(struct frame_t)+(size_t)vd->framelock[i] = 0;vd->framesizeIn);

(2)打开摄像头

在Linux中,类似摄像头的设备是作为文件来看待的,叫做设备文件。我们可以使用open函数来对设备进行打开操作,open带有两个参数,第一个为设备文件名称,本实验的摄像头设备名称是/dev/video0,第二个则是打开的类型。

在使用open函数打开摄像头之前,要判断是否有摄像头设备,即检查参数videodevice是否为空。Open函数执行结束后会返回摄像头的文件描述符,如果返回值为-1,则说明打开设备出错。

int open_v4l(char *vd->videodevice){

if(!vd->videodevice){

printf(“No device file, ERROR opening V4L interface”);

return-1;}

if((vd->fd=open(vd->videodevice, O_RDWR))==-1){

printf(“ERROR opening V4L interface”);

return-1;} return vd->fd;}(3)获取摄像头参数

成功打开摄像头后,需要获取摄像头的一些参数,利用ioctl函数控制I/O通道来实现。Ioctl函数的使用是ioctl(int->fd, int cmd,……),fd代表文件描述符,cmd表示用户对设备的控制命令,第三个参数是一个其他的参数。其中,cmd包括VIDIOCGCAP(获得video_capbility中有关摄像头的信息)、VIDIOCGPICT(获取图像信息)、VIDIOCSPICT(改变图像信息)、VIDIOCGMBUF(获取摄像头存储缓冲区帧信息)、VIDIOCAMCAPTURE(获取视频图像)、VIDIOSYNC(判断摄像头是否截取成功)等。

读取video_capability中有关摄像头的信息

if(ioctl(vd->fd, VIDIOCGCAP, &(vd->videocap))==-1){ printf(“Fail to get video_capability!/n”);return-1;} 读取video_picture中的图像信息 printf(“Fail to get video_picture!/n”);return-1;} if(ioctl(vd->fd, VIDIOCGPICT, &(vd->videopict))==-1){

读取video_window信息

if(ioctl(vd->fd,VIDIOCGWIN,&(vd->videowin))==-1){

printf(“Fail to get video_window!/n”);

return-1;}(4)设置摄像头参数

在对摄像头参数进行设置的时候,应该按照以下步骤:比如更改图像信息,首先,先给video_picture结构中所要修改的变量赋值,如vd->videopict.palette=vd->formaIn;vd->videopict.depth=GetDepth(vd->formatIn);然后通过ioctl函数的VIDIOCSPICT来设置,如if(ioctl(vd->fd,VIDIOCSPICT,&(vd->videopict))<0){ printf(Fail to set videopict params with VIDIOCSPICT!/n“);return-1;} 在设置好了之后可以通过VIDIOCGPICT命令来查询图像信息设置是否成功。(5)关闭摄像头

在Linux编程过程中,必须养成一个好的编程习惯,就是在开启一个设备后一定要关闭它,这样可以避免很多诸如内存泄露等严重的问题。

本系统支持两种读取方式来获得视频流,它们是内存映射和直接读取,所以首先需要判断视频采集的方式,如果是内存映射,则在系统任务完成后关闭内存映射,然后关闭摄像头设备。同样道理,如果采用的是直接读取,则在任务完成后关闭直接读取,然后在关闭摄像头设备。在代码中,采用了一个判断语句,判断vd->grabMethod的值来判断系统采用哪种读取方式。int close_v4l(struct vdIn *vd){

int i;if(vd->grabMethod){

} else { free(vd->pFramebuffer);vd->pFramebuffer = NULL;if(debug)printf(“unmapping frame buffern”);munmap(vd->pFramebuffer, vd->mmapsize);

} } if(debug)printf(“close video_devicen”);close(vd->fd);/* dealloc the whole buffers */ if(vd->videodevice){

} if(vd->cameraname){

} for(i = 0;i < OUTFRMNUMB;i++){

} pthread_mutex_destroy(&vd->grabmutex);if(vd->ptframe[i]){

} free(vd->ptframe[i]);vd->ptframe[i] = NULL;vd->framelock[i] = 0;if(debug)printf(“freeing output buffer %dn”, i);

free(vd->cameraname);vd->cameraname = NULL;free(vd->videodevice);vd->videodevice = NULL;5.1.3视频数据采集

视频数据的采集是系统实现的第一步,是所有工作的前提。嵌入式Linux系统支持两种视频数据采集的方式:内存映射、直接读取视频。

(1)内存映射

内存映射方式是通过mmap系统调用函数来实现的。mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间

后,进程可以像访问普通内存一样对文件进行访问,不必再调用read()、write()等操作。

首先,使用ioctl系统调用的VIDIOCSFBUF命令获得摄像头存储缓冲区的帧信息,之后初始化video_mbuf,修改video_mmap中的设置,重新设置图像信息,如帧的垂直及水平分辨率、彩色显示格式等。为了防止缓冲区的内容与有用信息叠加产生干扰,在初始化之前可以先调用memset(&(vd->videombuf),0,sizeof(vd->videombuf)来清零缓冲区。然后使用函数vd->map=(unsigned char*)mmap(O,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,ff_t offset)使设备内容映射到内存区,其中第一个参数为共享内存的起始地址,一般设为0,表示由系统分配;第二个参数为映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起;第三个参数指定共享内存的访问权限(PROT_READ(可读),PROT_WRITE(可写),PROT_EXEC(可执行));第四个参数可以是MAP_SHARED或者MAP_PRIVATE;第五个参数为设备描述符。mmap()成功调用后返回系统实际分配的起始地址。

内存映射方式下真正进行视频截取的是ioctl系统调用的VIDIOCMCAPTURE命令,若函数成功调用,再用VIDIOCSYNC命令来判断图像截取是否己经完毕,若该函数调用成功,则表明一帧图像的截取已完成,便开始下一帧图像数据的截取,并将当前截取的帧号按缓冲区总帧数的模加上l。

vd->vmmap.height=vd->hdrheight;vd->vmmap.width=vd->hdrwidth;vd->vmmap.format=vd->formatln;/*判断图像截取是否完成*/ if(ioctl(vd->fd,VIDIOCSYNC,&vd->vmmap.frame)<0){ perror(„‟cvsync errn);erreur=-I;} while((vd->framelock [vd->frame_cour]!=0)&&vd->signalquit)usleep(1000);temps=ms_time();

pthread_mutex_lock(&vd->grabmutex);jpegsize=convertframe(vd->ptframe[vd->frame_cour]+sizeof(struct frame_t),vd->pFramebuffer+vd->videombuf.offsets[vd->vmmap.frame],vd->hdrwidth,vd->hdrheight,vd->formatln,vd->framesizeIn);headerframe=(struct frame_t*)vd->ptframe [vd->frame_cour];

snprintf(headerframe->header, 5,”%s”.”SPCA”);

headerframe->seqtimes=ms_time();headerframe->w=vd->hdrwidth;headerframe->h=vd->hdrheight;headerframe->size=((jpegsize<0)? 0: jpegsize);headerframe->format=vd->formatln;headerframe->nbframe=frame++;pthread_mutex_unlock(&vd->grabmutex);/*截取视频帧*/ if((ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->vmmap)))<0){ perror(“cmcapture”);

if(debug)printf(“>>cmcapture err n”);erreur=-l;} vd->vmmap.frame=(vd->vmmap.frame+1)%vd->videombuf.frames;vd->frame_cour=(vd->frame_cour+l)%OUT FRMNUMB;(2)直接读取方式

直接读取视频数据是通过read系统调用函数来实现。read是一个用来从指定的文件或设备中读取数据的系统调用。参数表为read(fd,(void*)pFramebuff,(size_t)framesizeln)。其中fd为文件描述符,pFramebuffer为指向存放数据的内存的指针,framesizeln为需要读取的数据的长度。对于摄像头设备的读取,需要先分配内存空间,用来存储从摄像头读取过来的视频数据,然后直接调用read系统调用读取视频数据,返回值为实际读取的视频帧大小,也正是在视频传输过程中发送的视频数据大小。

size=vd->framesizeln;vd->pFramebuffer=(unsigned char*)realloc(vd->pFramebuffer,(size_t)size);Len=read(vd->fd, vd->pFramebuffer, size);if(len<0){ if(debug)printf(“v41 read errorn”);

if(debug)printf(“len %d asked %dn”, len, size);return 0;}

/*是否有其他进程正在使用该视频帧*/ while((vd->framelock [vd->frame_cour]!=0)&&vd->signalquit)

headerframe->deltatimes=(int)(headerframe->seqtimes-timecourant);

usleep(1000);temps=ms_time();

pthread_mutex_lock(&vd->grabmutex);jpegsize=convertframe(vd->ptframe[vd->frame_cour]+sizeof(structframe_t),vd->pFramebuffer,vd->hdrwidth,vd->hdrheight,vd->formatln,vd->framesizeln);headerframe=(struct frame_t*)vd->ptframe [vd->frame_cour];snprintf(headerframe->header, 5,”%s”,”SPCA”);headerframe->seqtimes=ms_time();headerframe->deltatimes=(int)(headerframe->seqtimes-timecourant);headerframe->w=vd->hdrwidth;headerframe->h=vd->hdrheight;headerframe->size=((jpegsize<0)? 0: jpegsize);headerframe->format=vd->formatln;headerframe->nbframe=frame++;vd->frame_cour=(vd->frame_cour+1)%OUTFRMNUMB;pthread_mutex_unlock(&vd->grabmutex);5.2图像编解码 5.2.1编解码介绍

通过摄像头采集到数据后,还并不能把它们直接通过网卡传输,因为这样的数据很大,网络不能承担如此庞大的数据传输。所以,必须将采集到得数据进行编码,压缩数据大小。通过这样的操作,我们采集到得数据就会变得很小,然后再把这些数据通过网络传输。同样的道理,在输出端我们还要把接收到的已经压缩的数据还原回来,这就涉及到解码的内容。通过这一系列的操作,图像和视频数据就实现的远程的传输。如果没有编解码,远程传输就是实际上不可能的事情,所以图像的编解码是非常重要的。

现在普遍使用的编解码技术。对于静态图像,普遍使用静态压缩JPEG标准;对于动态视频,普遍使用动态压缩MPEG标准。

JPEG是由ISO和CCITT为静态图像压缩所建立的国际上第一个静态图像压缩标准,JPEG有着较高的压缩比,复杂度适中,既可以用硬件实现,也可以用软件实现,实用性强,被广泛使用于计算机和通信行业。

MPEG中文译名为动态图像专家组。到目前为止,MPEG标准主要有五个,32

MPEG-

1、MPEG-

2、MPEG-

4、MPEG-7和MPEG-21。它是由ISO/IEC1172压缩编码标准得出的视频压缩格式,MPEG的出现使视听传播进入数码化时代。MPEG标准的视频压缩编码技术主要利用了具有运动补偿的帧间压缩编码技术以减少时间冗余度,利用DCT技术以减少图像的空间冗余度,利用熵编码技术在信息表示方面减少了统计冗余度。通过一系列技术,极大的体现了压缩性能[16]。

5.2.2系统压缩技术

由于本系统要求实现远程视频传输,为了达到预计的设计要求,设计采用基于MJPEG算法的压缩技术进行视频压缩。MJPEG和MPEG的不同点在于MJPEG不使用帧间编码。可是MJPEG与MPEG仍然是一脉相承的,它对MEPG进行了一些改进和发展,功能更加强大,能发送高质图片、清晰视频,编码容易实现。但MJPEG也有一些缺点,由于功能的提升,MJPEG对带宽的要求很高,编码效率低。

参考文献

1.张永强,赵勇勇,李崇德.嵌入式远程视频采集系统的设计与实现[J].现代电子技术,2006,05(02):57-60.2.Jing Li, Weidong Hao.Research and Design of Embedded Network Video Monitoring System Based on Linux[C].The 2008 International Conference on Embedded Software and Systems Symposia, 2008, 1310-1313.3.陈章龙,唐志强,涂时亮.嵌入式技术与系统——Intel Xscale 结构与开发[M].北 京:北京航空航天大学出版社,2004,143.4.奥尔博公司.PXA270嵌入式实验开发系统——Linux实验指导[M],2007.5.Seon Gyu Kim and Sung Ho Cho.Implementation of an Embedded Software Modem Platform[J].Division of Electrical & Computer Engineering,2006,04(2):5-9 6.杜春雷.ARM体系结构与编程[M].北京:清华大学出版社,2003.7.朱珍民,隋雪青.嵌入式实时操作系统及其应用开发[M].北京:北京邮电大学出版社,2006.8.李亚峰 欧文盛.ARM嵌入式Linux系统开发从入门到精通[M].北京:清华大学 33

基于USB的数据采集系统的研究与设计--总结 篇6

基于AutoCAD的全站仪数据导入系统设计与实现

为了满足测量内业数据传输的需要,本文详细介绍了基于AutoCAD的全站仪数据导入系统的设计与实现.该系统是利用Visual Basic 6.0中的`串行通讯控件MScomm,并以Visual Basic for Application(以下简称VBA)为开发平台,编写了通讯程序,实现了计算机与全站仪的数据通讯.本文以徕卡GSI系列全站仪为例,使用提取算法,从原始数据提取有用数据,将数据格式转换成成图软件所需要的格式,并在AutoCAD下通过二次开发平台VBA展绘成图.

作 者:蔡菲 史同广 马东岭 单宝艳 CAI Fei SHI Tong-guang MA Dong-ling SHAN Bao-yan 作者单位:山东建筑大学土木工程学院,济南,250101刊 名:测绘科学 ISTIC PKU英文刊名:SCIENCE OF SURVEYING AND MAPPING年,卷(期):200934(5)分类号:P241.3关键词:串口通信 数据传输 数据转换 AutoCAD二次开发

基于USB的数据采集系统的研究与设计--总结 篇7

MSP430F5529单片机集成了AD转换器和USB2.0接口, 硬件电路简单, 减少了信号干扰, 易于实现。传统的USB驱动程序开发难度大。而NI公司的NI-VISA driver wizard软件可帮助用户快速生成USB驱动文件, 开发者无须花费大量精力学习USB协议的细节, 便能实现单片机与PC的通信。不过更简单的方法是直接安装TI公司提供的USB_CDC通信驱动文件MSP430_CDC.inf, 利用虚拟串口实现USB通信。

1 系统硬件组成

系统整个架构如图1所示。

MSP430F5529芯片是数据采集模块的核心, 该单片机是一种超低功耗的16位混合模拟控制器, 内置12位SAR内核的AD转换模块, 在没有CPU干预下, 该缓冲器允许对16路独立采集而来的ADC信号进行转化和存储。最高采样速度可达200kbps。转换基准电压均可软件选择内部或外部电压源。该单片机内部的基准电压可设置为1.5V或2.5V。信号调理电路应将信号控制在转换基准电压范围内。同时该单片机还集成USB2.0接口模块, 其内部SRAM为8K, 在使用USB通信时占用2K的SRAM。这样的高度集成使得一个最小单片机系统就构成一个采集卡。用户需注意ADC接地和干扰防范, 具体硬件电路参考用户手册即可。

2 系统软件组成

系统软件设计主要包括USB固件程序设计, USB驱动程序设计以及Lab VIEW软件程序设计三个部分。

USB固件程序从功能上分为USB通信和AD数据采集两部分。从最底层开发USB通信程序对不熟悉USB协议的人来讲是不可能完成的任务。参考TI公司官方网站USB开发资源包使问题变得简单, 它包含了开发一个基于USB的MSP430项目所需的所有源代码和示例应用程序。开发者可直接套用其框架和USB API库函数完成, 如果用户使用的是CCS集成开发环境, 通过Help-->Welcome to CCS打开欢迎界面, 展开MSP430ware, 在这里可导入相关例程。

固件开发的另一部分就是AD采集程序的编写。MSP430的AD采集模块功能强大, 有四种转化模式:单通道模式, 重复单通道模式, 序列模式和重复序列模式。本文用6.6端口实现单通道多次转换采集端口, 其相关控制寄存器设置语句如下:

传统USB驱动开发对于非计算机专业的用户来讲难度很大。但是利用NI-VISA提供的USB驱动程序生成软件使得问题简化。首先打开NI-VISA Driver Wizard开发向导, 根据提示输入USB设备相关信息, 主要是VID (USB Manufacturer ID) 和PID (USB Model Code) 的正确填写 (MSP430F5529的VID为“0x2047”, PID为“0x0400”) 。然后将配置好的INF文件安装在Windows环境下, 再将USB设备插入主机完成驱动程序的安装。完成后可用NI MAX软件做通信测试, 打开NI MAX设备和接口项, 发现MSP430F5529支持三种常见设备分别是通信设备类 (CDC) , 人机接口设备类 (HID) , 大容量存储类 (MSC) , 并显示为USB RAW设备。对于USB RAW设备, 每个设备可能使用它们自己的通信协议, 用户须了解相关USB通信协议, 若程序中USB相关参数设置不正确会导致通信错误。还有没有更简单的方法?

事实上, 对于MSP430F5529的CDC通信, 无须用VISA驱动向导生成USB驱动程序。TI公司提供了USB_CDC通信驱动程序文件MSP430_CDC.inf, 用户直接安装就可以快速稳定的实现单片机与Lab VIEW间的通信。安装完毕, 打开windows系统的设备管理器, 在端口项目下显示MSP430_F5529_UE_CDC (COMxx) , 其中xx为串口号。这样的虚拟串口使得用户不需去了解USB协议, 而数据的传输却是通过USB接口完成的。

上位机Lab VIEW软件程序的编写利用NI-VISA函数按串口通信编写, 采用顺序结构:首先添加VISA资源名称控件, 配置串口函数, 添加VISA打开函数。这样通过串口资源选择和相关参数设置, 如波特率、数据位、停止位等, 完成初始化VISA设备的过程。然后调用VISA写入函数, 向单片机写入控制信息。单片机响应后采集数据并发送。再调用VISA读取函数读入采集的数据。要注意, VISA读取函数前需通过使用VISA Bytes at Serial Port节点查询当前串口接收缓冲区中的数据字节数。最后使用VISA关闭函数结束会话。图2为Lab VIEW读取程序框图。

下位机是12位ADC转换模块, 每发送两位数据为一个采集点, 上位机Lab VIEW中需对数据进行变换, 才能正确显示。

3 结束语

用信号发生器产生一个2V的正弦信号, Lab VIEW显示结果正确。该数据采集系统硬件上简单可靠。软件上, 利用TI公司提供的USB_CDC通信驱动文件和USB_API库函数, 使得不了解USB通信协议的用户也能快速实现与上位机Lab VIEW的通信, 极大的缩短开发时间。

摘要:基于低成本, 可靠性的思想设计了本数据采集系统。MSP430F5529单片机自身集成12位AD转换器和USB接口, 硬件电路简单可靠。上位机用Lab VIEW显示采集的数据波形。传统USB驱动开发复杂, 利用NI公司的NI-VISA driver wizard软件可快速生成USB驱动, 但若USB相关参数设置不正确, 容易出错。事实上, 直接利用TI公司提供的USBCDC虚拟串口通信驱动文件MSP430CDC.inf和USBCDCAPI库函数, 可以快速稳定的实现上下位机间的通信。

关键词:MSP430F5529,数据采集,USB,LabVIEW,NI-VISA

参考文献

[1]沈建华, 杨艳琴.MSP430系列16位超低功耗单片机原理与实践[M].北京:北京航空航天大学出版社, 2008.

[2]张桐, 陈国顺.精通Lab VIEW程序设计[M].北京:电子工业出版社, 2008.

[3]余志荣, 杨莉.基于NI-VISA与Lab VIEW的USB接口应用设计[J].单片机与嵌入式系统应用, 2007 (01) .

上一篇:在政府第一次全体会议上的讲话下一篇:怎样在网上给员工申报社保