IRP Setup 事务 中断传送 IRP 事务 事务 数据 事务 Status 事务 额外的 控制传送 事务 事务 事务 所有的传送都是由一个或多个事务组成。一个IRP又可由一个或多个传送组成。 控制传送首先是一个OUT方向的Setup事务,然后是多个IN方向或OUT方向的数据事务,最后是一个与数据反向的Status事务。 一个中断传送是一个或多个IN/OUT方向的数据事务。 同步传送 IRP 批传送 IRP 事务 事务 事务 事务 事务 事务 一个同步传送是一个或多个IN/OUT方向的数据事务。 一个批传送是一个或多个IN/OUT方向的数据事务。 图2-7 USB 数据传输
3 数据采集系统的固件设计
3.1 固件的开发环境
Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级语言的优势。
Keil C51的工具包中,uVision是C51 for Windows的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。然后分别由C51及A51编译器编译生成目标文件(.OBJ)。目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
3.2 采用PDIUSBD12的固件设计 3.2.1 固件编程的主要工作
固件是FIREWARE的对应中文词,它实际上是单片机的程序文件,其编写语言可以采用C语言或是汇编语言.它的操作方式与硬件联系紧密,包括USB设备的连接USB协议、中断处理等,它不是单纯的软件,而是软件和硬件的结合,开发者需要对端口、中断和硬件结构非常熟悉。固件程序一般放入MCU中,当把设备连接到主机上时,上位机可以发现新设备,然后建立连接。因此,编写固件程序的一个最主要的目的就时让Windows可以检测和识别设备。
USB固件程序程序由三部分组成:
①初始化单片机和所有的外围电路(包括PDIUSBD12); ②主循环部分,其任务是可以中断的;
③中断服务程序,其任务是对时间敏感的,必须马上执行。
根据USB协议,任何传输都是由主机开始的。单片机作它的前台工作,等待中断。主机首先要发令牌包给USB设备(这里是PDIUSBD12),PDIUSBD12接收到令牌包后就给单片机发中断。单片机进入中断服务程序,首先读PDIUSBD12的中断寄存器,判断USB令牌包的类型,然后执行相应的操作。在USB单片机程序中,要完成对各种令牌包的响应,其中比较难处理的是SETUP包,主要是端口0的编程。
单片机与PDIUSBD12的通信主要是靠单片机给PDIUSBD12发命令和数据来实现的。PDIUSBD12的命令字分为三种:初始化命令字、数据流命令字和通用命令字。PDIUSBD12数据手册给出了各种命令的代码和地址。单片机先给PDIUSBD12的命令地址发命令,根据不同命令的要求再发送或读出不同的数据。因此,可以将每种命令做成函数,用函数实现各个命令,以后直接调用函数即可。
3.2.2 PDIUSBD12芯片特点
PDIUSBD12是一个性能优化的USB器件,通常用于基于微控制器的系统,并通过高速通用并行接口与微控制器进行通信,而且支持本地DMA传输。该器件采用模块化的方法实现一个USB接口,允许在众多可用的微控制器中选择最合适的作为系统微控制器,允许使用现存的体系结构使固件投资减到最小。这种灵活性减少了开发时间、风险和成本。该器件使开发成本低且高效的USB外围设备的一种有效途径。PDIUSDB12完全符合USB1.1规范,也能适应大多数设备类规范的设计,如成像类、大容量存储类、通信类、打印类和人工输入设备等。因此,PDIUSBD12非常适合做很多外围设备。现在很多用SCSI实现的很多设备如果用USB来实现可以直接降低成本。PDIUSBD12还集成了SoftConnect、GoodLink、可编程时钟输出、低频晶振和终端电阻等特性。所有这些特性都能在系统实现时节省成本,同时在外围设备上很容易实现更高级的USB功能。
3.2.3 PDIUSBD12固件程序的编写
USB设备启动流程如下:
1. USB设备接入USB口,发出连接USB命令; 2. 主机发出读设备描述符两次;
3. 主机根据设备描述符—厂商ID、产品ID,启动相应设备驱动程序; 4. 设备驱动程序初始化USB设备; ①读设备描述符; ②读配置描述符;
③选择接口、端点(管道),确定传输方式。
USB设备在正常使用以前,必须由主机配置设备。主机一般会从USB设备获取配置信息后再确定此设备有哪些功能。作为配置操作的一部分,主机会设备设备的配置值,如果必要的话会选择合适的接口备选设备。在发出连接USB命令后,主机先读取设备描述符,然后发出设置USB地址SETUP包,设置USB地址后,进行主机客户驱动与设备初始化。其余端点依此类推。在其头文件里需定义USB规范中的各种描述符格式,包括设备描述表、配置描述表、接口描述表、端点描述表、字符串描述表以及描述表类型。这样,在发送配置联合描述表时,主机USBD可以根据描述类型标识区分各种分描述表。
3.3 固件的文件结构
本数据采集系统的固件有着如下的积木式结构:
主循环:发送USB请求、读入数据、控制采集通道和处理USB总线事件等等 MAINLOOP.C 标准请求 CHAP_9.C 厂商请求 PROTODMA.C 中断服务程序 ISR.C PDIUSBD12 命令接口 D12CI.C 硬件提取层 EPPHAL.C 图3-1 数据采集系统固件的文件结构
固件设计的目标就是使PDIUSBD12在USB上达到最大的传输速率。外围设备可使用PDIUSBD12 在USB上传输数据,这些设备的CPU要忙于处理许多设备控制和数据处理等任务。PDIUSBD12 的固件设计成完全的中断驱动,当CPU处理前台任务时,USB的传输可在后台进行,这就确保了最佳的传输速率和更好的软件结构,同时简化了编程和调试。
后台ISR中断服务程序和前台主程序循环之间的数据交换通过事件标志和数据缓冲区来实现,例如PDIUSBD12的批量输出端点可使用循环的数据缓冲区,当PDIUSBD12从USB收到一个数据包,那么就对CPU产生一个中断请求,CPU立即响应中断在ISR中固件将数据包从PDIUSBD12内部缓冲区移到循环数据缓冲区,并在随后清零PDIUSBD12的内部缓冲区,以使能接收新的数据包CPU可以继续它当前的前台任务直到完成然后返回到主循环检查循环缓冲区内是否有新的数据并开始其它的前台任务。
图3-2 数据采集系统的固件结构
由于这种结构,主循环不关心数据是来自USB串口还是并口,它只检查循环缓冲区内需要处理的新数据。这样主循环程序专注于数据的处理,而ISR能够以最大可能的速度进行数据的传输。相似的控制端点在数据包处理时采用了同样的概念。ISR接收和保存数据缓冲区中的控制传输并设置相应的标志寄存器。主循环向协议处理程序发出请求。由于所有的标准器件级别和厂商请求都是在协议处理程序中进行处理,ISR得以保持它的效率。
硬件提取层EPPHAL.C:这是固件中的最底层代码,它执行对D12和硬件I/O相关访问。
PDIUSBD12命令接口D12CI.C:为了进一步简化PDIUSBD12的编程,固件定义了一套压缩了所有访问PDIUSBD12功能的命令接口,以对PDIUSBD12芯片进行操作。
中断服务程序ISR.C:这部分代码的处理由PDIUSBD12产生的中断,在中断服务程序中,它将数据从PDIUSBD12的内部FIFO取回到CPU存储器并建立正确的事件标志,以通知主循环程序进行处理。ISR通过设定事件标志“EPPFLAGS”和Setup包数据缓冲区“CONROL_XFER”与主循环进行通信。
主循环MAINLOOP.C:主循环在初始化完单片机CPU和PDIUSBD12芯片后,检查事件标志,并进入对应的子程序进行进一步的处理,在开发套件中,它还包含人机接口的代码。
协议层CHAP_9.C和PROTODMA.C:协议层处理标准的USB器件请求和特殊的厂商请求。
3.4 固件的编程实现 3.4.1 底层函数
最底层为两个面向硬件电路的函数:outportb( ),inportb( ),用以完成CPU和D12之间的数据传输,这是所有其它函数的基础。具体代码如下:
void outportb(unsigned char port, unsigned char val) {
unsigned char xdata *ext_address; ext_address=0xff00 + port; *ext_address = val; }
unsigned char inportb(unsigned char port) {
unsigned char c;
unsigned char xdata *ext_address; ext_address=0xff00 + port; c = *ext_address ; return c; }
3.4.2 命令接口
在D12的数据手册中定义了一套压缩了所有访问PDIUSBD12