完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
摘要:在设计 USB 系统的过程中,固件程序的编写是非常重要的一个环节,它直接影响到开发产品的数据传输速度。以 Phillips 公司的 USB 控制芯片 PDIUSBD12 为例,介绍了在设计开发 USB 外设中。固件的作用以及固件程序的编写流程,并给出了相应程序。
关键词:USB 固件程序 PDIUSBD12 端点 单片机 USB(Universal Serial Bus)即通用串行总线,是现在非常流行的一种快速、双向、廉价、可以进行热插拨的接口,在现在的每一台 PC 机上都可以找到一对 USB 接口。在遵循 USB1.1 规范的基础上,USB接口最高传输速度可达 12Mb/s:而在最新的 USB2.0 规范下,更可以达到 480Mb/s.同时它可以连接127个USB设备,而且连接的方式也十分灵活,既可以使用串行连接,也可以使用集线器(Hub)把多个设 备连接在一起,再同 PC 机的 USB 接口相连.此外,它还可以从系统中直接汲取电流,无需单独的供电系统.USB 的这些特点使它获得了广泛的应用.但是使用上的方便则意味着开发上的复杂,主要是编程的复杂性大大的增加了. 在设计开发一个USB外设的时候,开发者主要需要编写三部分的程序: ①固件程序;②USB驱动程序;③客户应用程序.本文主要阐述固件程序的编写. 1 固件要完成的主要工作 固件是 FIREWARE 的对应中文词,它实际上是单片机的程序文件,其编写语言可以采用 C 语言或是汇编语言.它的操作方式与硬件联系紧密,包括 USB 设备的连接 USB协议、中断处理等,它不是单纯的软件,而是软件和硬件的结合,开发者需要对端口、中断和硬件结构非常熟悉。固件程序一般放入 MCU 中,当把设备连接到主机上(USB 连接线插入插孔)时,上位机可以发现新设备,然后建立连接。因此。编写固件 程序的一个最主要的目的就时让 Windows 可以检测和识别设备。 2 PDIUSBD12芯片特点 PDIUSBD12 是一个性能优化的 USB 器件,通常用于基于微控制器的系统,并通过高速通用并行接口与微控制器进行通信,而且支持本地 DMA 传输。该器件采用模块化的方法实现一个 USB 接口,允许在众多可用的微控制器中选择最合适的作为系统微控制器,允许使用现存的体系结构使固件投资减到最小。这种灵活性减少了开发时间、风险和成本。该器件使开发成本低且高效的 USB 外围设备的一种有效途径。 PDIUSDB12 完全符合 USB1.1 规范,也能适应大多数设备类规范的设计,如成像类、大容量存储类、通信类、打印类和人工输入设备等。因此,PDIUSBD12非常适合做很多外围设备,如打印机、扫描仪、外部大容量存储器(Zip 驱动器)和数码相机等。现在很多用 SCSI 实现的很多设备如果用 USB 来实现可以直接降低成本。 PDIUSBD12还集成了 SoftConnect、GoodLink、可编程时钟输出、低频晶振和终端电阻等特性。所有这些特性都能在系统实现时节省成本,同时在外围设备上很容易实现更高级的 USB 功能。 3 PDIUSBD12固件程序的编写 USB 设备启动流程如下: (1) USB设备接入 USB 口,发出连接 USB 命令; (2) 主机发出读设备描述符两次; (3) 主机根据设备描述符——厂商 ID、产品ID,启动相应设备驱动程序; (4) 设备驱动程序初始化 USB 设备; ①读设备描述符; ②读配置描述符; ③选择接口、端点(管道),确定传输方式。 图 1 PDIUSBD12测试电路连接图 图 1是PDIUSBD12的电路连接图。 USB 固件程序程序由三部分组成:①初始化单片机和所有的外围电路(包括 PDIUSBD12);②主循环部分,其任务是可以中断的;③中断服务程序,其任务是对时间敏感的,必须马上执行。根据 USB 协议,任何传输都是由主机(Host)开始的。单片机作它的前台工作,等待中断。主机首先要发令牌包给 USB设备(这里是 PDIUSBD12),PDIUSBD12 接收到令牌包后就给单片机发中断。单片机进入中断服务程 序,首先读 PDIUSBD12 的中断寄存器,判断 USB 令牌包的类型,然后执行相应的操作。在 USB 单片机程序中,要完成对各种令牌包的响应,其中比较难处理的是 SETUP包,主要是端口 0的编程。 单片机与 PDIUSBD12的通信主要是靠单片机给 PDIUSBD12发命令和数据来实现的。PDIUSBD12的命令字分为三种:初始化命令字、数据流命令字和通用命令字。PDIUSBD12数据手册给出了各种命令的代码和地址。单片机先给 PDIUSBD12 的命令地址发命令,根据不同命令的要求再发送或读出不同的数据。因此,可以将每种命令做成函数,用函数实现各个命令,以后直接调用函数即可。 下面的程序是处理主机的标准控制请求的一个模板: unsigned char ENDPOINT_A0_FIFO[8]; //判断输入的是 SETUP请求,并将其读入缓冲区 ENDPOINT_A0_FIFO … if((ENDPOINT_A0_FIFO[0] & 0b011000000)==0x00) { if(ENDPOINT_A0_FIFO[1]<=0C) { (*StandardFunctionTable[ENDPOINT_A0_FIFO[1]])(); return; } } … const void (*StandardFunctionTable[])(void)= { GetSatus,ClearFeature,USB_Reserved,SetFeature, USB_Reserved,SetAddress,GetDescriptor,SetDescriptor, GetConfiguration,SetConfiguration,GetInterface, SetInterface,SynchFrame }; USB 设备在正常使用以前,必须由主机配置设备。主机一般会从 USB设备获取配置信息后再确定此设备有哪些功能。 作为配置操作的一部分,主机会设备设备的配置值,如果必要的话会选择合适的接口备选设备。其初始化函数为: void D12_int() { XmtBuff.pNum=16; D12_COMMAND=0xf4;//读中断寄存器 ist=D12_DATA; ist=D12_DATA; if(ist & 0x01) //ENDP0_OUT {XmtBuff.out=0; XmtBuff.in=1; D12_COMMAND=0x40; //读 OUT 最后状态 ist=D12_DATA; if(ist & 0x20)//收到 SETUP 包 { Setup_read(); Setup_control(); } else { Setup_read(); } } else if(ist & 0x02)//ENDP0_IN { XmtBuff.in=1; D12_COMMAND=0x41;//读 in 最后状态 ist=D12_DATA; USB_submit(); } else if(ist & 0x04)//ENDP1_OUT { XmtBuff.out=2; XmtBuff.in=3; D12_COMMAND=0x42;//读 out 最后状态 ist=D12_DATA; read_out(); } else if(ist & 0x08)//ENDP1_IN { XmtBuff.in=3; D12_COMMAND=0x43;//读 in 最后状态 ist=D12_DATA; XmtBuff.b[0]=5; XmtBuff.wrLength=1; XmtBuff.p=XmtBuff.b; USB_submit(); } …… 在发出连接 USB 命令后,主机先读取设备描述符,然后发出设置 USB 地址 SETUP 包,设置 USB 地址后,进行主机客户驱动与设备初始化。其余端点(ENDPOINT)依此类推。 在其头文件里需定义 USB 规范中的各种描述符格式,包括设备描述表、配置描述表、接口描述表、端点描述表、字符串描述表以及描述表类型。这样,在发送配置[,接口(1),端点(1),接口(2),端点(2),…,类,厂商等]联合描述表时,主机 USBD可以根据描述类型标识区分各种分描述表。 下面是固件程序的主循环部分: #include //指向外部 D12访问地址 #define D12_COMMAND(*(unsigned char xdata *)0xff01) #define D12_DATA (*(unsigned char xdata *)0x7f02) extern void D12_int(); ***it D12_suspend=P1^0; ***it D12_int_n=P1^1; ***it D12_eot_n=P1^2; ***it D12_DMAck_n=P1^3; ***it D12_DMAreq=P1^4; void main(void) { unsigned char ist; P1=0xff; D12_COMMAND=0xf3; D12_DATA=0x06;//设置模式 0 D12_DATA=0x03;//初始化频率 12MHz D12_COMMAND=0xd0; { D12_int(); } } } 在编写 USB的固件程序时,需要注意: ①单片机的中断应设置为电平触发;中断后一定要读上次传输状态寄存器(命令 40~45H),以清除中断寄存器中的中断标志。这样,PDIUSBD12的中断输出才能变回高电平,这一点非常重要。 ②在接收到 Setup 包后,一定要调用 D8命令重新使能端口 0。 ③在向 IN 端写完数据后,一定调用命令 FAH,指明缓冲区中的数据有效,可以发送到主机。 ④读写数据后,一定调用命令 F2H,以保证可以接收新的包。 ⑤可以通过调用命令 FDH,检查 PDIUSBD12是否工作。该命令要读两个字节数据。 固件程序的编程是整个 USB 外设开发中非常重要的一环,它直接影响到设计开发的产品的数据传输速度。例如,采用不同的传输类型、设置不同的分组大小、是否采用 DMA 方式、传输缓冲区的大小等都会使得传输速率发生很大的变化。还有在高速情况下的超时处理等,也包含了很多的内容。 总之,在 USB 技术应用越来越广泛的今天,只有掌握了固件程序的编写,才可能开发出一个好的 USB 产品. 摘于电子开发网 |
|
相关推荐
|
|
学习一下,谢谢楼主分享,十分感谢
|
|
|
|
|
|
786 浏览 0 评论
4210 浏览 0 评论
如何使用python调起UDE STK5.2进行下载自动化下载呢?
2520 浏览 0 评论
开启全新AI时代 智能嵌入式系统快速发展——“第六届国产嵌入式操作系统技术与产业发展论坛”圆满结束
2926 浏览 0 评论
获奖公布!2024 RT-Thread全球巡回线下培训火热来袭!报名提问有奖!
31442 浏览 11 评论
72903 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 08:15 , Processed in 0.553273 second(s), Total 71, Slave 52 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号