当前位置:首页 >> 信息与通信 >>

AVRUSB技术探讨


AVRUSB 技术探讨
作者: 作者:邵子扬、王育强、吕益光

摘要
本文介绍了一种独特的 AVR 单片机和计算机进行 USB 通信的方法:AVRUSB。介绍了 AVRUSB 技术的基本原理、特点、应用,同时还详细的介绍了 AVRUSB 系统的单片机软件开发 和计算机软件开发的方法。

关键字: 关键字:
AV

RUSB,LibUSB,LibUSB-Win32

正文

1 简介
1.1 AVRUSB 是什么
AVRUSB 技术是利用高性能的 8 位 RISC 架构的 AVR 单片机,使用单片机的 IO 口来模拟 USB 的通信端口,由软件来实现 USB 通信协议,将普通的 AVR 单片机模拟成一个 USB 低速设 备,从而实现 AVR 单片机与计算机之间的通信和控制。

AVRUSB 技术的基本原理就是利用 AVR 单片机的普通 IO 端口来模拟 USB 的硬件端口进行 通信。因为低速 USB 设备的速度是 1.5M 位/秒,而 AVR 单片机是单指令周期的,在单片机使 用 12MHz 的时钟频率时,正好是 1.5MHz 的 8 倍。也就是说,单片机每 8 条指令就精确完成 一个数据位的采集。采用这种方法时,对单片机的时序要求非常严格,所以软件的核心部分 代码完全由汇编语言实现。

1.2 AVRUSB 的历史
AVRUSB 技术最早的文档可见于 AVR 的官方应用笔记《AVR309 Software Universal

Serial Bus (USB)》(软件 USB)一文中。在这篇应用笔记里,详细的介绍了如何使用 AVR 单片机的普通 IO 口来实现 USB 通信,同时介绍了计算机的驱动程序以及计算机上用户程序 的编程方法,并提供了全部源码。但是 AVR309 中介绍的单片机程序完全是使用汇编语言编 写的,不利于将程序移植到其他应用环境中,也不利于程序的维护(毕竟使用汇编语言的人 相对比较少,使用 C 语言编程是大部分人的选择),这使得其应用受到了很多限制。

后来,OBJECTIVE 公司推出了 AVRUSB。它以汇编语言实现 USB 通信的底层接口,用 C 语言实现用户层的程序接口。用户接口被简化为很简单的几个函数(在最简化的情况下,只 需要三个函数,一个初始化函数、一个轮询函数和一个数据处理函数)和一个配置文件,用 户可以完全不会使用汇编语言编程。 同时它还提供了一个稳定而成熟的用户程序框架, 用户 可以在此框架的基础上, 通过修改和扩展接口函数的功能来实现各种 USB 通信功能和控制功 能,实现各种带 USB 接口的应用系统。并且,AVRUSB 支持目前最流行的 AVR GCC 编译器和 IAR C 编译器,因此具有很强的实用性。

1.3 AVRUSB 的特点
1.3.1 低成本
传统的单片机与计算机进行 USB 通信, 需要使用专用的接口芯片进行 USB 协议转换, 如 CP2101、FT232、CH342、PDIUSBD12、SL811 等。象 CP2101、FT232 这样的芯片使用起来虽 然简单,但是功能比较单一;而 PDIUSBD12、SL811 功能较强,但是使用复杂。并且这些专 用芯片的价格都相对较高,增加了系统的成本。而 AVRUSB 简单易用,成本低廉,只需要一 个普通的低成本 AVR 单片机以及很少的几个外部元件,就可以组成一个 USB 系统。

AVRUSB 的代码为 AVR GCC 编译器做了高度优化,同时也完全兼容于更专业的 IAR C 编 译器。 程序编译后在最小情况下还不到 2KB, 因此绝大部分的 AVR 单片机都可以使用 AVRUSB (只要支持外部中断 INT0,Flash 容量不小于 2KB 就可以实现 AVRUSB 的功能)。这样在很 多低成本的小容量 AVR 单片机上也可以使用 AVRUSB,如 ATtiny2313、ATmega45、ATmega48 等,因此 AVRUSB 技术具有很高的实用价值。

资源丰富,容易开发 1.3.2 资源丰富,容易开发
AVRUSB 提供了一个完整而又简单易用、成熟稳定的应用程序框架。这个框架包括了底 层(单片机部分)和上层(PC 部分),单片机可以使用 gcc(或者 IAR)编程;PC 上则可以 使用各种通用编程软件,如 Windows 下使用 VC、VB、Delphi、C++ Builder、BDS2006、GCC, Linux 下使用 GCC 等等。用户可以在这个框架基础上添加和扩展各种功能,快速开发出适合

于各种需求的单片机控制系统,而且 AVRUSB 支持 Windows、Linux、MacOS 等多种操作系统, 具有很好的跨平台特性。

1.4 AVRUSB 的应用
AVR 单片机低成本、高性能的特性,使得 AVRUSB 非常适合于应用到 USB 加密狗、USB 接口的系统控制、 低速 USB 数据采集等, 这样构成的具有 USB 通信功能的单片机系统比很多 使用专用芯片的系统简单、成本低。

目前,AVRUSB 已经成功应用到了很多产品上,比较有名的有:USBasp(USB 接口的 AVR 编程器)、AVRCDC(USB 转 RS232 串口)、USB Bootlader(USB 接口的 Bootloader 软件)等。 在 http://www.obdev.at/products/avrusb/projects.html 中,还专门列举了很多使用 AVRUSB 的开源项目,这些项目提供了完整的单片机程序和计算机程序的代码和原理图。我 们在开发自己的 AVRUSB 应用时,可以参考这些资源,在这些开源项目的基础上进行修改, 快速开发出适合于自己需求的应用来。 本文作者也成功的将 AVRUSB 用到公司的一个项目中, 很好的实现了一个 USB 接口的开关矩阵控制。

1.5 AVRUSB 的限制
因为 AVRUSB 使用普通 IO 口模拟来 USB 通信的过程, 由软件实现了硬件完成的功能。 而 USB 通信的速率是比较高的。因此,在进行 USB 通信时单片机的 CPU 占用率比较高的(大于 90%)。

另外,因为受到单片机的处理能力限制,所以通信的数据处理能力不是很强,最大数据 处理速度约为 20k/s,因此 AVRUSB 不适合用于大数据量通信的应用场合。

2 硬件结构
构成一个 AVRUSB 系统的硬件结构非常简单,只需要一个普通的 AVR 单片机(大部分型 号都可以),再加上少量的外部元件(晶体、几个电阻以及可选的稳压二极管等),就组成 了一个基本的 AVRUSB 系统,如图 1。

U1 23 24 25 26 27 28 1 R2 R3 68 68 14 15 16 17 18 19 9 10 PC0/ADC0 PC1/ADC1 PC2/ADC2 PC3/ADC3 PC4/ADC4/SDA PC5/ADC5/SCL PC6/RST PB0/ICP1 PB1/OC1A PB2/OC1B/SS PB3/MOSI/OC2 PB4/MISO PB5/SCK PB6/X1/TOSC1 PB7/X2/TOSC2 ATMEGA8 C2 C3 RXD/PD0 TXD/PD1 INT0/PD2 INT1/PD3 XCK/T0/PD4 T1/PD5 AIN0/PD6 AIN1/PD7 VCC AVCC ARef GND GND 2 3 4 5 6 11 12 13 VCC 7 20 21 C1 8 22

VUSB USB VBUS DD+ GND 1 2 D3 D+ 4 R4 152

D1

D2

12M

的基本硬件接口 图 1. AVRUSB 的基本硬件接口

图中的单片机以 ATmega8 为例。数据线 D-上的上拉电阻 R4 用来通知计算机这是一个低 速 USB 设备(这是在 USB 规范中定义的,更多内容请参考 AVR309 以及 USB 的官方文档)。 12MHz 晶体和两个 22p 的电容 C2 和 C3 组成单片机运行所必须的时钟。 和 D- 数据线可使 D+ 用单片机的任意 IO 端口,但是必须使用相同的 IO 端口。在这里 D+ 连接到 PB1,D- 连接到 PB0。此外数据线 D+还需要连接到 INT0 上,这是为了在不同的 AVR 单片机中使用 AVRUSB 时 有更好的适应性和兼容性, 无需修改底层核心部分程序的代码。 如果 D-连接到端口 D 上 (就 是和 INT0 同一端口中),同时 D+只连接到 INT0,还可以节省出一个端口来。

电阻 R2、R3 起到限流和保护作用,防止在意外情况下损坏计算机的 USB 端口或单片机 的端口。 单片机所需的电源 Vcc 可由 USB 的 5V 输出电源直接提供, 或者由 USB 的 5V 电源转 换得到(如 LDO、稳压二极管等),或者通过电池等其他外部电源来供电。

D+和 D-上的 3.6V 稳压二极管 D1 和 D2 起到限制数据线上的电平的作用。 因为在 USB 规 范中规定数据线 D+和 D-上的电平范围是 3.0V 至 3.6V, AVR 单片机的输出电平是 Vcc。 而 如 果单片机的 Vcc 是 5V,在没有 D1 和 D2 的情况下将造成电平不匹配,会造成在很多计算机 中无法正确识别出 USB 设备。 如果用户系统的 Vcc 在 3.0V 至 3.6V 之间, 就可以省略这两个 稳压二极管。从这里也可以看出用户系统的 Vcc 必须高于 3V。

上面硬件就组成了一个最小的 AVRUSB 系统,它能够和计算机进行 USB 通信。在上面最 小系统的基础上,如果添加一个红外传感器,就可以接收发送红外信号,就是一个 USB 红外 控制器;如果添加一个 MAX202,就是一个带缓冲的 USB <-> RS232 串口转换器;如果加入 ADC 转换功能,就是 USB 的数据采集器;如果加入 ADC 和电源控制,就能够实现一个简单实 用的 USB 充电器……各种功能的 AVRUSB 系统都是在这个最小系统的基础上,添加不同功能 的外围模块或接口来实现的。

3 单片机程序的开发 单片机程序的
要使用 AVRUSB,就需要在单片机中开发合适的软件,实现特定的功能。下面将具体介 绍开发需要使用的工具软件和开发的步骤。

3.1 开发环境
AVRUSB 可使用 AVR GCC 编译器或 IAR C 编译器。因为 AVRUSB 特别为 AVR GCC 编译器做 了优化,并且 AVR GCC 还是免费软件,使用非常广泛,是目前 AVR 单片机主要的开发工具软 件之一,所以我们下面以 AVR GCC 为例来介绍。

在 Windows 操作系统下开发时,使用 WinAVR 中带有的 AVR GCC 编译器;代码编辑、仿 真和调试使用了 Atmel 公司的 AVR Studio,这个 IDE 的好处是不需要用手工修改 makefile 配置文件, 减少了初学者的使用难度。 如果希望使用其他 IDE 或编辑软件作为开发工具也可 以,下面的使用步骤也是类似的。如果是在 Linux 操作系统下开发,可以使用 Linux 版本的 AVR GCC,以及其他工具软件进行编辑和调试。

3.2 建立项目文件
要将 AVRUSB 加入到自己的程序中,首先需要在 AVR Studio 中建立一个新的项目 (Project),然后将 AVRUSB 所需要的文件复制到项目文件的文件夹中(当然也可以不用复 制文件,只添加已经存在的 AVRUSB 的文件路径到项目中也可以,但是将项目的所有文件放 在一个文件夹下更容易对整个项目进行维护)。一般来说,凡是使用 AVRUSB 的项目,在项 目文件夹下都会单独存放一个 USBDRV 的文件夹,里面存放着所有与 AVRUSB 相关的文件。 AVRUSB 包含了多个文件,但是我们只需要添加以下几个文件到项目中:

usbconfig.h iarcompat.h usbdrv.h

用户配置文件 为兼容 IAR 编译器而定义的宏 usb 驱动接口文件的头文件

usbdrv.c usbdrvasm.asm usbdrvasm.S oddebug.h oddebug.c

usb 驱动接口文件 为兼容 IAR 编译器而使用的底层接口函数文件的别名 汇编语言编写的底层接口函数 调试用函数的头文件(不使用调试功能时可以不添加) 包含调试用的函数(不使用调试功能时可以不添加)

注意到上面的文件除了 usbconfig.h 外, 都在 USBDRV 文件夹中。 USBDRV 文件夹中一 在 般都有一个 usbconfig-prototype.h 文件, 这个文件是用户配置文件 usbconfig.h 的原始模 板,我们需要将这个文件复制到项目文件夹中并将它改名为 usbconfig.h。复制后,还需要 再添加 USBDRV 文件夹的路径到项目的包含路径中,这样在编译时才可以正确找到上面的文 件,如图二(因为 USBDRV 文件夹在项目文件夹下,所以显示出的是相对路径)。如果不使 用 AVR Studio,也可以使用其他的 IDE 软件或编辑软件,但是可能会需要用户自行手工修 改项目配置文件 makefile,具体做法这里就不做介绍了。

图 2. 添加 USBDRV 路径到项目中

3.3 参数配置
在编译项目之前,除了需要对项目本身的参数进行配置外(如 AVR 单片机的型号、系统

时钟频率、代码优化等级等),还需要对 AVRUSB 的参数进行配置,这样才能产生出正确的 代码。AVRUSB 中包含的参数虽然看起来很多,其实配置起来很容易。在用户配置文件 usbconfig.h 中存放了所有与 USB 相关的配置参数,配置参数都是以宏定义的方式给出,配 置参数的过程就是修改相关的宏定义。只要修改这个文件中的参数就可以实现不同的功能, 其它的文件不用修改。

为了获得尽可能高的效率,AVRUSB 中使用了大量的宏定义和条件编译,用以获得最小 的代码大小和最快的运行速度。 配置文件 usbconfig.h 中的参数非常多, 1 列出了主要需 表 要修改的参数。 一般的情况下只要修改这几个参数就可以了, 其它的参数可以根据用户的实 际需求做适当的修改。

表 1:usbconfig.h 中的主要参数 :

USB_CFG_IOPORTNAME

定义 USB 数据线使用的端口。只要是通用的 IO 都可以,没 有特殊的要求。 USB 数据线 D-使用的引脚。 USB 数据线 D+使用的引脚。因为 D+要求同时连接到 INT0 上, 所以一般情况下需要使用 3 个 IO 口。 如果 D+使用的引 脚就是 INT0,那么可以少使用一个 IO 端口。 设备生产商的 ID 号 设备的产品 ID 号。这两个参数就是 Windows 识别 USB 设备 的主要参数。需要注意的是,这两个参数都是低字节在前, 高字节在后。 设备的版本号次版本号在前,主版本号在后。在 Windows 的设备管理中可以看到这个版本号 设备生产商的名称,它在 Windows 的设备管理中可以看到。 这里一般写入的是网址。 设备生产商名称的长度。 设备的名称,它在 Windows 的设备管理中可以看到。设备 名称和生产商的名称都是以字符的方式定义的,它们目前 不支持中文。 设备名称的长度。

USB_CFG_DMINUS_BIT USB_CFG_DPLUS_BIT

USB_CFG_VENDOR_ID USB_CFG_DEVICE_ID

USB_CFG_DEVICE_VERSION

USB_CFG_VENDOR_NAME

USB_CFG_VENDOR_NAME_LEN USB_CFG_DEVICE_NAME

USB_CFG_DEVICE_NAME_LEN

3.4 主要接口函数
配置好参数,就可以开始编写用户程序了。用户程序和计算机之间的 USB 通信是通过 AVRUSB 提供的接口函数完成的,接口函数有 6 个,下面将分别介绍。

3.4.1 初始化函数
在使用 AVRUSB 前,需要进行必要的初始化,这通过调用初始化函数 usbInit()完成。 一般是在程序其他部分初始化完成后再调用函数 usbInit(),最后再调用 sei()函数允许中 断。

void main()

{

… usbInit(); sei(); … while(1) { … } //主循环

}

3.4.2 USB 事件处理函数
在用户程序的主循环中需要定期调用 USB 事件处理函数 usbPoll()。USB 事件处理函数 usbPoll()在没有 USB 事件需要处理时将直接返回,否则将调用内部函数进行相应的事件处 理,最后再将数据通过传递到后面介绍的用户接口函数中。通常的用法是:

while(1) //主循环 { usbPoll(); //USB 事件处理 …… //其他用户事件 }

一次 USB 通信的超时时间是 50ms。所以在编程时注意其他事件不要占用太长的时间, 使得 usbPoll()函数不能及时执行。

用户事件 事件接口函数 3.4.3 用户事件接口函数
在用户程序中需要编写 USB 用户事件接口函数,完成 USB 通信。AVRUSB 将用户接口简 化为以下 3 个函数,这三个函数需要用户进行编程处理,它们将完成 USB 通信的数据处理。

usbFunctionWrite usbFnctionRead usbFunctionSetup

主机向单片机写入数据 主机从单片机中读取数据 一般功能设置

函数 usbFunctionSetup 负责传递 USB 请求,参数存放在一个 8 字节的数组中(uchar data[8]),其的含义是:

uchar requestType; uchar request; unsigned value; unsigned index; unsigned length;

//[0] //[1] //[2], [3] //[4], [5] //[6], [7]

请求类型 请求的内容 参数 序号 长度

在一般情况下,除了 data[0]和 data[1]用于存放 USB 事件的请求参数外,data[2]至 data[7]都可以传递用户参数。 这样在数据量非常小的时候, 通过 usbFunctionSetup 就可以 完成全部参数传递了,不需要使用函数 usbFnctionRead 和 usbFunctionWrite。这时可以在 usbconfig.h 中将宏 USB_CFG_IMPLEMENT_FN_READ 和 USB_CFG_IMPLEMENT_FN_WRITE 设置为 0,禁止使用函数 usbFnctionRead 和 usbFunctionWrite,这样可以节省出不少代码空间。

在传递的数据比较多时, 就需要使用 usbFunctionWrite 和 usbFnctionRead 函数了。 这 两个函数具有相同的参数(uchar *data, uchar len),len 表示参数的数量,*data 指向数 据缓冲区。在编程时,一般是先在 usbFunctionSetup 函数中根据计算机发送过来的请求类 型和参数来设置一个全局标志, 然后在 usbFunctionWrite 和 usbFnctionRead 函数中根据相 应全局标志进行不同的功能处理。

数据校验 3.4.4 数据校验
为了保证 USB 数据通信的可靠,避免传输中出现误码,还应当对数据进行校验。USB 通 信使用了 CRC 校验来保证通信的可靠性,数据校验的方法是调用 usbCrc16()函数,函数的 使用方法是:

crc = usbCrc16((uchar *)(unsigned)(usbAppBuf + 1), usbRxLen - 3);

USB 数据缓冲区中存放的校验结果在

((uchar *)(unsigned)(usbAppBuf + 1))[usbRxLen - 3] 和 ((uchar *)(unsigned)(usbAppBuf + 1))[usbRxLen - 2] 两个字节中。

将计算结果和缓冲区的数据进行比较就可以知道通信缓冲区中的数据是否正确了。 需要 注意的是 usbCrc16 函数并不是在用户程序中调用的,而是在 usbdrv.c 文件中的 usbPoll 函数中。在 usbPoll 函数的开始部分有一段注释,解释了可以在此调用 usbCrc16 函数。

在很多 AVRUSB 项目中(如 USBasp)并没有处理 CRC 校验,这是因为在 USB 通信中对时 间要求比较严格,AVRUSB 在底层处理时来不及进行数据校验,所以底层函数在接收到数据 后就直接将 ACK 信号发送回去了。 这样即使在数据校验中发现了错误, 也不能由底层函数报 告给计算机, 只能在用户程序中向计算机发出错误报告。 在一般要求不高的应用中可以不进 行数据校验,以简化程序结构。但是在要求比较高的控制系统中应当进行 CRC 校验,使得整 个系统具有更高的可靠性。 当然, 用户也可以不使用比较耗时的 CRC 校验而用其他方法建立 起自己的数据错误处理机制。

4 计算机程序编程
计算机程序的编程主要包括了驱动程序的设计和用户程序的开发, 每个部分又包含了很 多内容。

4.1 PID 和 VID
每种 USB 设备都有一个 PID 和 VID。VID 是生产商的代号,PID 是产品的代号,每个代 号都是一个双字节的整数。PID 和 VID 不能随意设置,它是由 USB 标准协会进行分配的,就 像 IP 地址的分配一样。一个 USB 的 PID/VID 许可需要花费 1500 美元,在很多情况下,特别 对小公司是一个很大的费用。针对这种情况,AVRUSB 提供了 3 个免费的 PID/VID 对,分别 适用于 HID 类、CDC 类和通用类设备,使用 AVRUSB 的用户可以免费使用它们,这样对于大 多数应用来说就不用再自己去申请 PID/VID 了。

表二: 表二:免费的 PID/VID 对 VID 控制类 CDC 类 HID 类 0x16C0 0x16C0 0x16C0 PID 0x05DC 0x05DF 0x05E1

PID 和 VID 在驱动程序和用户程序中都将用到, 它是 windows 识别 USB 设备的关键参数, 用户程序也需要通过 PID 和 VID 来查找相应的 USB 设备。

4.2 USB 设备类型
AVRUSB 有多个版本,早期的版本只支持控制类的 USB 设备和最多两个节点,而最新的

版本还可以支持 CDC 类(串口类)和 HID 类(人体工学设备)以及最多 4 个节点。CDC 类和 HID 类都无需自己编写 Windows 的驱动程序 (Windows 自带) AVRUSB 的作者不推荐使用 CDC 。 类的方式(据说是因为在有些计算机上兼容性不好),而推荐使用 HID 类,但是使用 HID 类的应用目前还不是很多, 支持的程序也比较少。 本文将只介绍应用最广泛的控制类设备的 编程方法。

4.3 驱动程序 驱动程序
对于每种 USB 设备,都需要有相应的驱动程序。只有安装了驱动程序后,USB 设备才能 被操作系统所识别,设备才能正常工作。每个驱动程序都包含了底层驱动程序、设备描述文 件等几部分。

虽然现在已经有很多优秀的开发底层驱动程序的工具, 但是对于一般用户来说开发驱动 程序还是一件比较复杂的事情。AVRUSB 的底层驱动程序使用了 LibUSB,这是一个很有名的 开源 USB 驱动程序,支持多种操作系统平台,在 Windows 操作系统下对应的版本是 LibUSB-Win32。也就是说,计算机上的 USB 底层驱动程序不需要用户自己再编写了,直接使 用 LibUSB 就行了,用户只需要编写设备描述文件。设备描述文件是一个文本文件,用于说 明设备的参数,主要就是设备的 PID、VID、设备名称、使用的底层驱动程序名称等。

定制自己的 4.3.1 定制自己的 USB 设备驱动程序
要想让 LibUsb-Win32 成为自己开发的 USB 设备的驱动程序, 只需对 LibUsb-Win32 提供 的 libusb.inf 设备信息文件 (INF) 的内容按照其中的注释给出的说明进行适当的修改即可。 其中最重要的修改是对 VID/PID 的修改, 将文件中的 VID/PID 值替换为自己开发的 USB 设备 的 VID/PID 值(也就是上面表二给出的值)。其它可以修改的内容还有设备制造商名称,设 备描述字符串等等。

以 LibUSB-Win32 的 0.1.10.1 版本为例,一个使用 LibUSB 的 USB 设备驱动程序包至少 要包含以下的 3 个文件:libusb0.sys、libusb0.dll 和 libusb.inf。在 LibUsb-Win32 的 0.1.10.1 版 本 中 , 还 提 供 了 一 个 用 于 自 动 生 成 INF 文 件 的 向 导 工 具 。 该 工 具 位 于 libusb-win32-device-bin-0.1.10.1\bin 目录下,文件名为 inf-wizard.exe。通过使用该 向导工具,可以方便地生成与自己开发的 USB 设备相关的 INF 文件。需要注意的是,该向导 工具不仅生成了一个 INF 文件,同时也生成了一个安全目录文件(*.cat),该文件包含的 由 Microsoft 提供的对将要安装到 Windows 系统上的驱动程序文件的数字签名。 如果没有这 样的安全目录文件, 需要从生成的 INF 文件中删除掉“Version“部分中的“CatalogFile“内容。

设备的 4.3.2 预安装 USB 设备的驱动程序
通过“找到新硬件向导“的方式来安装设备的驱动程序作为 Windows 系统的一种标准方式 已经使用很多年了,每当我们加入一个新的设备到计算机上时,Windows 会提示我们发现一 个新的设备, 然后进一步提示我们去查找并安装相应的驱动程序。 这个步骤对于终端用户来 说还是不太方便,对他们而言,希望只要将新的硬件装(插)到 Windows 系统上就可以使用 了,而无需再做其它额外的工作。

Microsoft 已经认识到了这个问题,并已制作了一套能够在 Win2000 及更高版本的操作 系统上使用的驱动程序安装工具——Driver Install Frameworks (DIFx)。这些工具能够进 行驱动程序的预安装, 即新硬件在系统上可用之前安装驱动程序。 这允许当一个匹配的设备 首次被连接到电脑上时,相应的驱动程序能够被自动装载。

Driver Package Installer(DPInst)是 DIFx 工具集中的工具之一,该工具提供了进 行驱动程序预安装的最简单也是最常用的方法。DPInst 由 DPInst.exe 和 DPInst.xml 这两 个文件组成,其中 DPInst.xml 是一个可以对安装过程进行配置的文件。将驱动程序包放在 与 DPInst.exe 和 DPInst.xml 一样的目录下(或者将驱动程序包放在 DPInst.exe 所在目录 的子目录下),然后运行 DPInst.exe,就可以将驱动程序包进行安装。以下是 DPInst.xml 的一个例子:

<?xml version="1.0"?> <dpInst> <search> <subDirectory>DriverPackage</subDirectory> </search> <language code="0x804"> <dpinstTitle>XXX 控制器 USB 设备驱动程序安装向导</dpinstTitle> <welcomeTitle> 欢迎使用 XXX 控制器 USB 设备驱动程序安装向导! </welcomeTitle> <welcomeIntro> 此向导将帮助您安装 XXX 控制器 USB 设备驱动程序。没有该驱动程序, XXX 控制器 USB 设备将无法运行。 </welcomeIntro> <eulaHeaderTitle>最终用户许可协议</eulaHeaderTitle> <eulaYesButton>我同意此协议(&amp;A)</eulaYesButton> <eulaNoButton>我不同意此协议(&amp;D)</eulaNoButton> <installHeaderTitle> 正在为您的设备安装该驱动程序,请稍候... </installHeaderTitle> <finishTitle> 祝 贺 您 ! 该 驱 动 程 序 已 成 功 安 装 到 了 您 的 电 脑 上 。 </finishTitle> <finishText>您现在可以使用 XXX 控制器 USB 设备了。</finishText> <eula type="txt" path="CustomData\eula.txt" /> </language> <legacyMode/> <icon>CustomData\CtrlDevIcon.ico</icon> </dpInst>

我们可以将上面的文件打包到我们应用程序的安装程序中, 当安装应用程序时自动将驱 动程序安装到 Windows 中。经过这样预安装驱动程序后,当 Windows 发现新的硬件后,用户 可以让 Windows 自动搜索驱动程序,完成设备的识别,简化了用户的操作。

4.4 用户程序的开发
完成了驱动程序的开发, 我们还需要完成更复杂的用户程序开发。 开发用户应用程序同 样需要使用到 LibUSB,开发使用的编程语言可以使用任何常用的编程语言,在 Linux 下一 般是 GCC、Kylix 等;在 Windows 下选择就比较多一些,GCC、VC、VB、Delphi/CBC 等都可 以。

因为我们平时使用 Windows 操作系统比较多,所以下面介绍在 Windows 操作系统下的 LibUSB 使用方法和编程,LibUSB 在 Win32 平台下对应的版本是 LibUSB-Win32。

LibUSB4.4.1 LibUSB-Win32 简介
LibUSB-Win32 是一个用于 Windows 操作系统(Win98SE、WinME、Win2k 和 WinXP)上的 通用 USB 设备驱动程序。该驱动程序允许使用者在不写任何一行核心驱动程序代码的情况 下,可以访问 Windows 系统上的任意一个 USB 设备。该驱动程序具有以下特点:

能够与任意一个已安装的 USB 设备进行通信 可被用作自己开发的 USB 设备的驱动程序 支持批量和中断传输 支持 USB 规范中定义的所有标准设备请求 支持 USB 设备制造商的自定义请求

LibUsb-Win32 是由 http://libusb-win32.sourceforge.net 发布的,遵守 GNU Lesser General Public License(LGPL)和 GNU General Public License(GPL)许可协议。这些 协议明确规定:允许 LibUsb-Win32 用于商业软件,而不只是开源软件。

LibUSB SB4.4.2 使用 LibUSB-Win32
LibUSB-Win32 为 C/C++程序员提供了用于开发的头文件和 Lib 文件, 其中 Lib 文件还提 供了 BCC、GCC 和 MSVC 这三个版本。C/C++程序员在自己的程序中要使用 LibUSB-Win32 时, 只需包含提供的头文件,并链接合适的 Lib 文件即可。

对于 Delphi 程序员来说, LibUsb-Win32 没有提供现成的 Import Unit (导入单元文件) , 不过 Internet 上已经有程序员提供了对 LibUSB-Win32 的 Delphi Pascal 转换文件。Delphi 程序员可以从 http://www.xs4all.nl/~ynlmns/ 上下载 Delphi 版的 LibUsb-Win32 文件。 值得注意的是,该版 LibUSB-Win32 不仅提供了 Import Unit(LibUSB.pas),还提供了一 个 DLL 文件(USBLibExport.dll)。在对 LibUSB-Win32 编程时,这个 DLL 必须作为程序的 一部分,通过调用这个 DLL 中的函数来访问 LibUSB-Win32,这样的效率比较低。本文的作 者在 LibUSB.pas 文件的基础上进行了分析和研究,对原 LibUSB.pas 做出了如下一些修改:

1) 在 interface 部分中,将所有导出函数声明中的调用约定“stdcall”改为了
“cdecl”;

2) 在 implementation 部分中,将所有导出函数中 external 指示符后面所跟的字符

串“USBLibExport.dll”改为了“libusb0.dll”。

3) 进一步封装了 LibUSB 中的函数,使之和 AVRUSB 单片机底层函数相对应,简化了
LibUSB 函数的使用,方便了用户编程调用。

这样可以不再需要使用 USBLibExport.dll 而直接访问 LibUSB-Win32。 Delphi 程序员只 需将修改后的 LibUSB.pas 包含到自己的程序中, 就可让自己的程序直接使用 LibUsb-Win32 了。这个修改后的 LibUSB.pas 文件可以在本文作者的博客上下载: http://shaoziyang.bloger.com.cn/user2/88141/archives/2006/323777.shtml

4.4.3 常用的函数
LibUsb-Win32 为开发人员提供了一套丰富的 API 函数,包括核心函数、设备操作、控 制传输、批量传输和中断传输等几类。下面就几个常用的函数进行一下简单介绍: 1) void usb_init(void); 该函数用于初始化 LibUSB-Win32,它必须第一个被调用。

2) int usb_find_busses(void); 查找系统上所有的 USB 总线。

3) int usb_find_devices(void); 查找每一根 USB 总线上的所有 USB 设备, 该函数应该在 usb_find_busses 函数 之后被调用。

4) struct usb_bus *usb_get_busses(void); 获取已找到的 USB 总线序列,返回值是一个指向 USB 总线序列首地址的指针。

5) usb_dev_handle *usb_open(struct *usb_device dev); 打开一个指定的 USB 设备。 在对某个 USB 设备执行任何操作之前, 首先要打开 该 USB 设备,就像打开一个文件、打开一个句柄一样。函数的返回值是一个设备 句柄,该句柄在后面与设备进行通信时会被用到。

6) int usb_close(usb_dev_handle *dev); 关闭一个指定的 USB 设备。在使用完某个 USB 设备后,应该关闭该 USB 设备, 这和在使用完一个句柄后需要关闭句柄是一样的。

7) int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout); 向 USB 设备发送一个请求。函数各参数的含义如下: dev:USB 设备句柄,该参数指定了向哪个 USB 设备发送请求; requesttype:请求的类型,说明了是读请求,还是写请求。可以是标准 请求、类请求或自定义请求; request:表示具体请求的值;

value:与请求相关的参数; index:与请求相关的参数; bytes:表示在数据阶段时传输的数据; size:表示在数据阶段时传输的数据量,以字节为单位; timeout:请求的超时设置,最大值为 5000,以毫秒为单位。

通过使用以上七个函数, 就可以与 USB 设备进行简单通信了, 通信的主要流程可分为以 下四步: 1) 调用 usb_init 函数,进行初始化。 2) 打开要进行通信的 USB 设备的句柄。首先依次调用 usb_find_busses、 usb_find_devices 和 usb_get_busses 这三个函数, 获得已找到的 USB 总线序 列;然后通过链表遍历所有的 USB 设备,根据已知的要打开 USB 设备的 ID (VID/PID),找到相应的 USB 设备;最后调用 usb_open 函数打开该 USB 设 备(在这里假设总线上没有相同 VID 和 PID 的 USB 设备。如果总线上存在着 相同 VID 和 PID 的设备,还需要进行其他条件判断,比如设备名称,以保证 是打开的是期望的 USB 设备)。 3) 与 USB 设备进行通信。使用 usb_control_msg 函数,向 USB 设备读取数据或 写入数据。 4) 关闭 USB 设备。完成所有操作后,调用 usb_close 函数关闭已经打开的 USB 设备。

5 其他要注意的问题
在使用 AVRUSB 时,需要注意以下问题: 1. 晶体一定要使用 12MHz 的,误差范围在±0.2%之内。如果晶体频率误差太大,对 USB 通信会有一定的影响,容易造成通信失败。 2. 一个型号的 AVR 单片机往往分为 8M/10M/16M 等多个频率等级,不同的电压也有 不同的频率限制(参考数据手册上相应的说明)。很多 8M/10M 频率等级的单片机 在 12M 频率下也可以使用(超频),在一般情况下没有太大的问题。不过在可能情 况下应当尽量使用 16M 频率等级的单片机,以提高系统的稳定性。 3. 使用 AVRUSB 的 CDC 类做 USB 转串口时,因为只能使用 12M 的晶体,所以有很多波 特率的误差比较大,超过了串口通信允许的±2%误差范围。一般最好使用 2400、 9600、19200 等误差较小的波特率。 4. AVRUSB 定义的缓冲区最大是 254。 通信时, 一次往缓冲区写入数据不要超过缓冲区 的大小,否则很容易在通信时造成数据丢失。 5. AVRUSB 中使用了大量的宏定义和条件编译进行系统配置,这样造成了程序的可读 性比较差,特别是刚开始时很难弄明白。而且 AVRUSB 没有专门的说明文档,只有 通过研究源代码以及代码中的注释来学习。但是这也是一种编程技巧和编程风格,

可以有效的提高程序的代码效率。

参考资料: 参考资料 1. ATMEL 公 司 的 应 用 笔 记 《 AVR309 Software Universal Serial Bus (USB) 》 : http://www.atmel.com/ 2. AVR309 的中文翻译《AVR309 软件 USB》:http://shaoziyang.bloger.com.cn/ 3. AVRUSB 的官方开源项目 PowerSwitch:http://www.obdev.at/products/avrusb/ 4. 使用 AVRUSB 的编程器 USBasp:http://www.fischl.de/usbasp/ 5. LibUSB:http://libusb.sourceforge.net 6. LibUSB-Win32:http://libusb-win32.sourceforge.net

(全文完)

联系方式: 联系方式: EMAIL:shaoziyang@126.com 或 shaoziyang@gmail.com


相关文章:
AVRUSB技术探讨[1]
关键字: AVRUSB,LibUSB,LibUSB-Win32 1 简介 1.1 AVRUSB 是什么 AVRUSB 技术是利用高性能的 8 位 RISC 架构的 AVR 单片机,使用单片机的 IO 口来模拟 ...
AVRUSB技术探讨
AVRUSB技术探讨_信息与通信_工程科技_专业资料。AVRUSB 技术探讨作者: 作者:邵子扬、王育强、吕益光 摘要本文介绍了一种独特的 AVR 单片机和计算机进行 USB 通信的...
AVRUSB技术探讨1
AVRUSB技术探讨1本文介绍了一种独特的AVR单片机和计算机进行USB通信的方法:AVRUSB。介绍了AVRUSB技术的基本原理、特点、应用,同时还详细的介绍了AVRUSB系统的单片机软...
AVRUSB技术探讨
AVRUSB技术探讨_工学_高等教育_教育专区。AVRUSB技术探讨AVRUSB 技术探讨 作者: 作者:邵子扬、王育强、吕益光摘要 本文介绍了一种独特的 AVR 单片机和计算机进行 ...
浅谈在应用编程技术
详细介绍了 AVR 单片机 Atmega64 以及 DSP 芯片 ...存储器的产品如何使 用在应用编程技术进行了探讨。 ...外部的通讯接口(串口,网口,USB,蓝牙,红外等等)擦...
JTEG
如下 图: 2、AVRJTAG 仿真器工作原理 AVR 的 ...4、JTAG 驱动安装 由于该 USBJTAG 是一个 USB ...参考方法交付物显著缩短了用于生成内核的专业技术实现...
大学学习理论与方法
湖南农业大学课程论文 学姓 院:科学技术师范学院 名...这块板子是 USB 下载 的,拿回来之后经过测试一切...大三下学期我基本都是在学习 51 单片机和 avr ...
我的论文(1)
计算机科学与技术专业毕业设计 毕业设计(论文)独创性...CC2531 可支持 USB 2.0 全速设备; 9、与 CC259x...高度优化的 IAR AVR C/C++编译器、AVR IAR 汇编...
向超论文
社会背景单片机的出现是计算机制造技术高速发展的产物,...3 5、体积小巧,携带方便 USB 接口通讯及供电,通讯...目前支持的单片机类型有:68000 系列、AVR 系列、8051...
毕业设计论文
西安交通大学本科生毕业设计论文 摘要 数据采集技术是...按与计算机通信的方式不同可以有串口的、USB 的、...可以仿真 51 系列、AVR,PIC 等常用的单片机及其外围...
更多相关标签:
avr jtag ice usb驱动 | avrusb | avr usb | avr usbisp | usb avr jtag 驱动 | usb avrisp xpii | avr usbasp | avrisp usbasp |