USB设备驱动程序的设计

发布者:cwm6269310最新更新时间:2011-07-08 关键字:USB设备  驱动程序 手机看文章 扫描二维码
随时随地手机看文章
  引言   
 
  USB总线是1995年微软、IBM等公司推出的一种新型通信标准总线,特点是速度快、价格低、独立供电、支持热插拔等,其版本从早期的1.0、1.1已经发展到目前的2.0版本,2.0版本的最高数据传输速度达到480Mbit/s,能满足包括视频在内的多种高速外部设备的数据传输要求,由于其众多的优点,USB总线越来越多的被应用到计算机与外设的接口中,芯片厂家也提供了多种USB接口芯片供设计者使用,为了开发出功能强大的USB设备,设计者往往需要自己开发USB设备驱动程序,驱动程序开发一直是WINDOWS开发中较难的一个方面,但是通过使用专门的驱动程序开发包能减小开发的难度,提高工作效率,本文使用Compuware PHILIPS公司USB2.0控制芯片ISP1581的USB设备驱动程序。

图1 USB驱动程序模型   

USB设备驱动程序是一种典型的WDM(Windows Driver Model)驱动程序,其程序模型如图1所示。用户应用程序工作在Windows操作系统的用户模式层,它不能直接访问USB设备,当需要访问时,通过调用操作系统的API(Application programming interface)函数生成I/O请求信息包(IRP),IRP被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与UBS外设通信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程序一方面通过IRP及API函数与应用程序通信,另一方面调用相应的总线驱动程序,总线驱动程序完成和外设硬件通信。USB总线驱动程序已经由操作系统提供,驱动程序开发的重点是函数驱动程序。

USB设备驱动程序的设计   

使用DriverStudio3.2开发USB设备驱动程序   

该驱动程序的主要功能包括:从控制端点0读取规定个数的数据、向端点0发出控制命令、从端点2批量读数据、向端点2批量写数据,驱动程序的开发采用DriverStudio3.2驱动程序开发包及VC++6.0,使用开发包中的向导程序DriverWizard就可以方便的生成驱动程序框架、模块及部分程序源代码,开发者只需要在功能模块中加入自己的实现程序就能完成复杂的USB设备驱动程序设计,下面介绍使用DriverWizard生成ISP1581驱动程序的过程:   

1)启动DriverWizard,选择DriverWorks Project创造一个名为USBDIO的VC++项目;   

2)在驱动程序类型中选择WDM Driver,WDM Function Driver,在硬件设备所支持的总线类型中选择USB(WDM Only),在USB Vendor ID(厂商识别码)中填写0741,在USB Product ID(产品识别码)中填写0821;   

3)增加USB设备端点,设置端点2为批量输入/输出传输方式;   

4)在驱动程序支持的功能项中选择Read、Write、Device Control、Cleanup;   

5)选择自动产生批量读及批量写程序代码;   

6)在I/O请求IRP处理方式中选择None,即IRP不排队;   

7)在接口的打开方式中选择Symbolic link:UsbdioDevice,即应用程序以符号链接名打开设备;   

8)定义应用程序调用DeviceIoControl函数对WDM驱动程序通信的控制命令,结果如图2所示。

图2 定义控制代码   

9)最后选择完成并确认生成新的项目信息,向导程序就会在usbdio目录中生成一个名为USBDIO的项目文件,其中包括了ISP1581驱动程序框架、模块及部分源代码。

USB设备驱动程序的编程   

在使用DriverWizard生成驱动程序框架、模块及部分程序源代码后,开发者只需完成图2中三个控制代码所对应的三个功能模块的编程:模块USBDIO_IOCTL_ID_CODE_Handler的功能是从控制端点0读取数据,模块USBDIO_IOCTL_TEST_COMMAND_Handler的功能是向控制端点0发送一个控制命令,模块USBDIO_IOCTL_DMA_COMMAND_Handler的功能是向控制端点0发送一个要求USB设备进行DMA传输的控制命令,下面是第一个模块的编程实例。

NTSTATUS USBDIODevice::USBDIO_IOCTL_ID_CODE_Handler(KIrp I)   {   NTSTATUS status = STATUS_SUCCESS;   t << Entering USBDIODevice::USBDIO_IOCTL_ID_CODE_Handler, << I << EOL;   PURB pUrb;   ULONG numData;   numData=(PUCHAR)I.IoctlBuffer();//设置读取的数据个数   pUrb=m_Lower.BuildVendorRequest(   (PUCHAR)I.IoctlBuffer(),//驱动程序存放读取的数据的内存区   numData,//wLength,读取的数据个数   0,   0x0c,//bRequest   0,//wValue   TRUE,//input   TRUE,   NULL,   0x0472,//wIndex,传输到固件程序的读数命令码   URB_FUNCTION_VENDOR_ENDPOINT,   NULL   );   if(pUrb==NULL)   {   I.Information() =0;   status=STATUS_INSUFFICIENT_RESOURCES;   }   else   {   I.Information() =numData;   status=m_Lower.SubmitUrb(pUrb,NULL,NULL,0);   delete pUrb;   }   return status;   }   

对象I包含了应用程序下传的IRP内容,包括命令或数据等参数,函数BuildVendorRequest用来分配并初始化一个用于厂商请求的URB(USB Request Block),该URB将作为下传IRP的一个参数,通过函数SubmitUrb发送给总线驱动程序,以便完成与硬件的通信。

在初始化URB时需要了解USB的传输方式及传输协议,该功能使用了USB的控制传输方式,该方式包括三个阶段:设置阶段、数据阶段和状态阶段,其中数据阶段可选,开发者主要关注设置阶段中的8个关键字节的定义,8字节分成了5个字段,定义了传输请求及相关信息,这8个字节的格式如图3所示。

  bmRequestType   bRequest   wValue   wIndex   wLength

图3 USB设置数据格式   

BmRequestType:1字节,用来指定数据流动的方向,请求的类型,以及接收者。

bRequest:1字节,用来指定请求。

wValue:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。

wIndex:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。

wLength:2字节,包含数据阶段中接下来要传输的数据字节数目。

以上字段的应用已经在程序注释中标出,在此不再赘述。

USB设备驱动程序的安装及调用   

USB设备驱动程序的安装   

驱动程序编译完成后会生成一个名为USBDIO.SYS的文件,即USB设备驱动程序,另外在使用向导程序WizardDriver生成驱动程序时会产生一个名为USBDIO.INF的驱动程序安装程序,对此程序只需稍做修改就能正常使用,具体是将类改为USB,即Class=USB,由于本驱动程序使用符号链接名打开设备,所以删除ClassGUID选项,注意设备标识符必需为:%DeviceDesc%=USBDIO_DDI, USBVID_0471&PID_0821,其中0471是USB控制芯片的厂商识别码,0821是USB设备标识码。

驱动程序安装过程是:将USB设备加电,连入计算机的USB接口,这时候会看到Windows操作系统提示发现新硬件,提问是否安装驱动程序,选择是,然后选择驱动程序所在文件夹,选择文件USBDIO.INF即可完成安装。

USB设备驱动程序的调用   

为了完成对驱动程序的调用,笔者使用VC++6.0编写了USB应用程序包,程序包共由五个功能模块组成,用户通过调用这些模块即可方便的完成对USB外设的控制及读写,这些模块如下:   

1)int CTRLReadData(unsigned char usbSelect,unsigned char rbuffer,unsigned char numData),主要功能是读取ISP1581控制端点0发来的数据,数据存放在缓冲区rbuffer中。

2)int CTRLSendTestCommand(unsigned char usbSelect,unsigned short int testCommand),主要功能是发送测试命令,变量testCommand定义了测试命令。

3) int CTRLSendDMACommand(unsigned char usbSelect,unsigned char dmaDirection,unsigned char ramSelect,unsigned long dmaLength),主要功能是发送DMA传输命令,变量dmaDirection定义数据传输方向,ramSelect定义将要操作的USB外设的存储器,dmaLength定义了数据传输总数。

4)int DMARead(unsigned char usbSelect,unsigned char rbuffer,int len,int waitTime),主要功能是计算机批量读取ISP1581中的数据,而ISP1581以DMA方式从外部RAM读取数据。

5)int DMAWrite(unsigned char usbSelect, unsigned char rbuffer, int len, int waitTime),主要功能是计算机批量写数据到ISP1581,而ISP1581将以DMA方式写数据到外部RAM。

结语   

USB设备驱动程序开发是Windows编程中较难的一个方面,要求开发者不但要有良好的Windows编程知识,还要掌握USB控制芯片工作原理、USB传输协议、USB固件等相关知识,使用DriverStudio3.2进行USB设备驱动程序开发可大大减少工作量和工作难度,本文所设计的USB设备驱动程序,已经应用到某雷达的自动测试设备中,驱动程序在计算机应用程序控制下可以顺利的发送各种测试命令,批量输入或者输出大量数据,达到设计要求。

关键字:USB设备  驱动程序 引用地址:USB设备驱动程序的设计

上一篇:基于PIC的CAN总线超声波测距智能节点设计
下一篇:I²C总线的验证及实现

推荐阅读最新更新时间:2024-05-02 21:28

11-S3C2440驱动学习(八)嵌入式linux-块设备驱动程序
一、回顾字符设备驱动 主要分为简单字符设备驱动程序,和复杂字符设备驱动 1、简单字符设备驱动 对于简单的字符设备驱动,不需要采用分离分层的思想,主要包括以下几个部分。 2、复杂字符设备驱动 对于复杂的字符设备驱动,采用分离分层的思想,内核中已经实现好了核心层部分,我们只需要实现与硬件相关的部分就可以,最后形成一个总体。这样就是一个通用的字符驱动框架。如LCD驱动、V4L2驱动,当然有时候我们可以选择不采用分离分层的思想,按简单驱动程序的框架来实现一个驱动。 3、字符设备驱动常用技巧 (1) 查询方式 (2) 休眠唤醒,APP-read drv_read (3) poll机制 (4) 异步通知发信号
[单片机]
11-S3C2440驱动学习(八)嵌入式linux-块<font color='red'>设备</font><font color='red'>驱动程序</font>
QNX 4.25设备驱动程序的编写
摘要:介绍实时操作系统QNX4.25下编写设备驱动程序的大体框架、底层细节以及诸多注意点。针对使用较为普遍的PCI设备作为较为详细的描述。 关键词:驱动程序 QNX 实时操作系统 PCI 引言 QNX是一个多任务、多用户、分布式、可嵌入式符合POSIX标准的微内核的主流实时操作系统,广泛用于实时性能、开发灵活性、网络灵活性要求较高的场合,如电信系统、医疗仪器、航空航天、工业自动化、交通运输、POS机、信息家电等。 QNX是一个适合软件/硬件定制的实时操作系统。如果你曾经试图在传统的UNIX或Windows平台下开发设备驱动程序,那么,QNX下开发驱动程序一定会让你受宠若惊。由于QNX的微内核结构,QNX下的系统进程和用户
[嵌入式]
ds1868 c 驱动程序
/****************DS1868 数字电位器调试******************/ //注意:ds1868的管脚 调试是我用P2口的 5、6、7 脚 发现不好用 //另外线性效果也不是很理想,但是能够满足一般的要求了 #i nclude reg51.h #i nclude absacc.h #define LSB 0x01 #define HIGH 1 #define LOW 0 #define BUZZER_OFF BUZZER=1 sbit DS1868_RST=P3^5; //pin 5 sbit DS1868_CLK=P3^6; //pin 6 sbit DS1868_DQ =P3
[单片机]
HD4478U显示LCD与51单片机驱动程序
#include SST89x5x4.H #include absacc.h #include intrins.h sbit LCDRSPIN = P3^7; sbit LCDRWPIN = P3^6; sbit LCDEPIN = P2^6; #define UCHAR unsigned char void delay(unsigned int i) { UCHAR j; for(i; i 0; i--) for(j = 200; j 0; j--); } /////////////////////////////// //控制LCD unsigned char XPOS,YPOS; //测
[单片机]
基于STM32F103的任意I/O口矩阵键盘驱动程序
网上的矩阵键盘代码非常非常多,但绝大部分都是要连续I/O口的,就比如PA0-PA7、PB3-PB10等等等,这些都要用到一排的连续的单片机引脚。用过STM32单片机的都知道,STM32单片机一排过去连续的引脚的不是很多,就算刚好出现了一排PA0-PA10,可是呢,PA2、PA3串口2要用,PA9、PA10串口1要用,这就显得比较局限。而且市面上的那些很多都是修改引脚要全文上下一处处修改,麻烦且容易错漏。所以如果我矩阵键盘的引脚可以随便定义的话那么是不是就不用愁这个问题了? 所以,这就是我给大家带来的任意可用的I/O的矩阵键盘程序,按键扫描代码直接操纵IO口,得出按键值。用法很简单:先看下图 我们看到,在key4_4.c中已经
[单片机]
基于STM32F103的任意I/O口矩阵键盘<font color='red'>驱动程序</font>
Linux下I2C总线EEPROM驱动程序设计方法
1 引言 I2C (Inter-Integrated Circuit1总线是一种由Philips公司开发的2线式串行总线,用于连接微控制器及其外围设备。它是同步通信的一种特殊形式,具有接口线少、控制方式简单、器件封装形式小、通信速率较高等优点。在主从通信中,可有多个I2C总线器件同时接到I2C总线上,通过地址来识别通信对象。笔者在开发基于MPC8250的嵌入式Linux系统的过程中发现I2C总线在嵌入式系统中应用广泛,I2C总线控制器的类型比较多,对系统提供的操作接口差别也很大。与I2C总线相连的从设备主要有微控制器、EEPROM、实时时钟、A/D转换器等.MPC8250处理器正是通过内部的I2C总线控制器来和这些连接在I2C
[嵌入式]
8位共阴极数码管动态驱动程序
//################################################################## //****** 程序作用: 驱动8位数码管 **************************************** //****** 单片机型号: STC90C16RD+ **************************************** //****** 编写日期: 2013年6月8日晚 **************************************** //**
[单片机]
基于STM32Cube USB设备库应用的几个常见问题
简介:简单总结基于STM32Cube USB设备库应用的几个常见问题,如如何让大容量存储类驱动支持多个逻辑盘【LUN】?USB设备库是否可以任意运行在FULL SPEED或HIGH SPEED模式?等 1、如何动态地修改设备描述符或字符串描述符? 在文件usbd_desc.c里,与设备和字符串相关的描述符可以通过GetDescriptor的回调函数进行动态调整。 2、如何让大容量存储类驱动支持多个逻辑盘【LUN】? 在文件usbd_msc_storage_xxx.c中修改STORAGE_LUN_NBR。【xxx代表使用的存储介质】 STORAGE_Inquirydata数组里包含了每个LUN的标准查询数据【in
[单片机]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved