Chinaunix首页 | 论坛 | 博客
  • 博客访问: 650975
  • 博文数量: 195
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 894
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-21 16:48
文章分类

全部博文(195)

文章存档

2024年(1)

2023年(1)

2022年(3)

2021年(16)

2020年(4)

2019年(5)

2018年(10)

2017年(72)

2016年(36)

2015年(47)

我的朋友

分类: 嵌入式

2017-02-16 10:33:46

转载自:
http://blog.csdn.net/tianshiyalin/article/details/17250755

http://blog.csdn.net/cescf4/article/details/8601457

http://blog.csdn.net/yanlai20/article/details/12967015

USB2.0是向下兼容USB1.X的,即USB2.0支持高速,全速,低速的USB设备(HIGH-SPEED,FULL-SPEED,LOW-SPEED),而USB1.X不支持高速设备。因此如果高速设备接在USB1.X的hub上,也只能工作在全速状态。因此对速度的识别是很重要的,否则没办法以想要的速度通信。

全速和低速区分

根据规范,全速和低速很好区分。因为在设备端有一个1.5K的上拉电阻,上电后,有上拉电阻的那根数据线会被拉高,根据 D+或D-的电平状态来检测是全速还是低速设备。如下图:




高速识别


全速,高速的识别比较简单,但是USB2.0,USB1.X只有一对数据线,就没办法有第三种状态来表示高速设备了,所以高速设备的识别稍微复杂。

高速设备是以一个全速设备的身份出现的,即和全速设备一样,高速设备也在D+端有一个1.5K的上拉电阻。USB2.0的HUB把设备当成一个全速设备,然后进行一系列的握手信号来确认双方的身份,一方面HUB要检测设备是高速还是全速,另一方面设备也要检测HUB是USB2.0还是USB1.X的,如果HUB是USB2.0,设备也是高速的 就工作在高速模式,否则只能工作在全速模式。


下图展示了一个高速设备连到USB2.0 hub上的情形:

HUB连接到设备或上电时,向主机报告,主机通过发送Set_port_feature请求让hub复位新插入的设备。设备复位操作是驱动数据线到复位SE0(D+,D-都为低电平),并持续至少10MS。

高速设备复位后,通过内部的电流源向D-持续灌17.78MA大小的电流。因为此时D+端的1.5K上拉电阻还没撤销,在hub端,全速/低速驱动器形成一个45欧姆的终端电阻,两电阻并联约形成45欧姆的阻抗,所以在HUB端可以看到一个 800ma(17.78*45)的电压,这个就是Chirp K信号。Chirp K 的持续时间是 1ms -  7ms.

在HUB端,虽然下达了复位信号,并一直驱动着SE0,但usb2.0的高速接收器一直在检测 Chirp  K信号,如果没有检测到,就继续复位操作,知道复位结束,然后就工作在全速状态。如果只是一个全速的hub,不支持高速设备,那么hub也不会理会Chirp k信号,之后设备也不会切换到高速模式。

如果是高速 HUB,设备在发送的Chirp k信号结束后的100us内,HUB必须回复一连串的KJKJKJ........序列,向设备表明这是一个usb2.0的hub,这里的kj序列式连续的,且不能中断,每个K或J的持续时间是 40us--60us.

再回到设备端,设备检测到6个hub发送的 Chirp信号(3对KJ)后,它必须在500us内切换到高速模式。切换动作有:

 1.断开1.5K的上拉电阻

2. 连接D+/D-上的高速终端电阻(high-speed termination),其实就是全速/低速差分驱动器。

3.进入默认的高速状态

执行完 1,2两步后,USB信号线上看的到现象就发生变化了:HUB发动的 Chirp降到原来的一半,400mv。这是因为设备端挂载新的终端电阻后,并联原来的终端电阻,结果为22.5欧姆,17.78*22.5为 400mv,以后高速设备操作的 信号幅值就是 400mv而不是 全速/低速的 3.3V。

至此高速设备与usb2.0握手完毕,开始进行480Mbps的通信。

转帖,原帖出自: http://hi.baidu.com/doyanger/blog/item/af45d995dd64f419d31b704d.html



USB的描述符及各种描述符之间的依赖关系


USB是个通用的总线,端口都是统一的。但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的设备的呢?这就要依赖于描述符了。


USB的描述符主要有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,HID描述符,报告描述符等等。


关于报告描述符,请看:《USB HID报告及报告描述符简介 》

****.com/93/198.aspx。

 

一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;端点描述符定义了端点的大小,类型等等。

 

由此我们可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。

 

 

每种描述符都有自己独立的编号,如下:

 

#define DEVICE_DESCRIPTOR               0x01 //设备描述符

#define CONFIGURATION_DESCRIPTOR        0x02 //配置描述符

#define STRING_DESCRIPTOR               0x03 //字符串描述符

#define INTERFACE_DESCRIPTOR            0x04 //接口描述符

#define ENDPOINT_DESCRIPTOR             0x05 //端点描述符

 

下面分别详细介绍一下各描述符。

 

1.设备描述符

 

//定义标准的设备描述符结构

 

typedef struct _DEVICE_DCESCRIPTOR_STRUCT

 

{

 

BYTE blength;                               //设备描述符的字节数大小

 

BYTE bDescriptorType;                      //设备描述符类型编号

 

WORD bcdUSB;                                //USB版本号

 

BYTE bDeviceClass;                          //USB分配的设备类代码

 

BYTE bDeviceSubClass;                       //USB分配的子类代码

 

BYTE bDeviceProtocol;                       //USB分配的设备协议代码

 

BYTE bMaxPacketSize0;                       //端点0的最大包大小

 

WORD idVendor;                              //厂商编号

 

WORD idProduct;                             //产品编号

 

WORD bcdDevice;                             //设备出厂编号

 

BYTE iManufacturer;                         //设备厂商字符串的索引

 

BYTE iProduct;                              //描述产品字符串的索引

 

BYTE iSerialNumber;                         //描述设备序列号字符串的索引

 

BYTE bNumConfigurations;                    //可能的配置数量

 

}

 

DEVICE_DESCRIPTOR_STRUCT, * pDEVICE_DESCRIPTOR_STRUCT;

 

//实际的设备描述符示例

 

code DEVICE_DESCRIPTOR_STRUCT device_descriptor=   //设备描述符

 

{

 

sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小,这里是18字节

 

DEVICE_DESCRIPTOR,                              //设备描述符类型编号,设备描述符是01

 

0x1001,   //USB版本号,这里是USB01.10,即USB1.1。由于51是大端模式,所以高低字节交换

 

0x00,                                 //USB分配的设备类代码,0表示类型在接口描述符中定义

 

0x00,                                 //USB分配的子类代码,上面一项为0时,本项也要设置为0

 

0x00,                                //USB分配的设备协议代码,上面一项为0时,本项也要设置为0

 

0x10,                                //端点0的最大包大小,这里为16字节

 

0x7104,                             //厂商编号,这个是需要跟USB组织申请的ID号,表示厂商代号。

 

0xf0ff,        //该产品的编号,跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序

 

0x0100,       //设备出厂编号

 

0x01,        //设备厂商字符串的索引,在获取字符串描述符时,使用该索引号来识别不同的字符串

 

0x02,        //描述产品字符串的索引,同上

 

0x03,         //描述设备序列号字符串的索引,同上

 

0x01                        //可能的配置数为1,即该设备只有一个配置

 

};

 

2.配置描述符

 

//定义标准的配置描述符结构

 

typedef struct _CONFIGURATION_DESCRIPTOR_STRUCT

 

{

 

BYTE bLength;                               //配置描述符的字节数大小

 

BYTE bDescriptorType;                       //配置描述符类型编号

 

WORD wTotalLength;                          //此配置返回的所有数据大小

 

BYTE bNumInterfaces;                        //此配置所支持的接口数量

 

BYTE bConfigurationValue;                   //Set_Configuration命令所需要的参数值

 

BYTE iConfiguration;                        //描述该配置的字符串的索引值

 

BYTE bmAttributes;                          //供电模式的选择

 

BYTE MaxPower;                              //设备从总线提取的最大电流

 

}

 

CONFIGURATION_DESCRIPTOR_STRUCT, * pCONFIGURATION_DESCRIPTOR_STRUCT;

 

2.接口描述符

 

//定义标准的接口描述符结构

 

typedef struct _INTERFACE_DESCRIPTOR_STRUCT

 

{

 

BYTE bLength;                               //接口描述符的字节数大小

 

BYTE bDescriptorType;                       //接口描述符的类型编号

 

BYTE bInterfaceNumber;                      //该接口的编号

 

BYTE bAlternateSetting;                     //备用的接口描述符编号

 

BYTE bNumEndpoints;                         //该接口使用的端点数,不包括端点0

 

BYTE bInterfaceClass;                       //接口类型

 

BYTE bInterfaceSubClass;                    //接口子类型

 

BYTE bInterfaceProtocol;                    //接口遵循的协议

 

BYTE iInterface;                            //描述该接口的字符串索引值

 

}

 

INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT;

 

4.端点描述符

 

//定义标准的端点描述符结构

 

typedef struct _ENDPOINT_DESCRIPTOR_STRUCT

 

{

 

BYTE bLegth;                                //端点描述符字节数大小

 

BYTE bDescriptorType;                       //端点描述符类型编号

 

BYTE bEndpointAddress;                      //端点地址及输入输出属性

 

BYTE bmAttributes;                          //端点的传输类型属性

 

WORD wMaxPacketSize;                        //端点收、发的最大包大小

 

BYTE bInterval;                             //主机查询端点的时间间隔

 

}

 

ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT;

 

下面是一个配置描述符集合的定义

 

typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT

 

{

 

CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;

 

INTERFACE_DESCRIPTOR_STRUCT interface_descritor;

 

ENDPOINT_DESCRIPTOR_STRUCT endpoint_descriptor[ENDPOINT_NUMBER];

 

}CON_INT_ENDP_DESCRIPTOR_STRUCT;

 

配置描述符集合的示例

 

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor= //配置描述符集合

 

{

 

//configuration_descriptor                     //配置描述符

 

{

 

sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),      //配置描述符的字节数大小,这里为9

 

CONFIGURATION_DESCRIPTOR,                     //配置描述符类型编号,配置描述符为2

 

(sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+

 

sizeof(INTERFACE_DESCRIPTOR_STRUCT)+

 

sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+

 

(sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+

 

sizeof(INTERFACE_DESCRIPTOR_STRUCT)+

 

sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256,   //配置描述符集合的总大小

 

0x01,                                  //只包含一个接口

 

0x01,                                  //该配置的编号

 

0x00,                                  //iConfiguration字段

 

0x80,                                  //采用总线供电,不支持远程唤醒

 

0xC8                                   //从总线获取最大电流400mA

 

},

 

//interface_descritor                   //接口描述符

 

{

 

sizeof(INTERFACE_DESCRIPTOR_STRUCT),   //接口描述符的字节数大小,这里为9

 

INTERFACE_DESCRIPTOR,                  //接口描述符类型编号,接口描述符为3

 

0x00,                                  //接口编号为4

 

0x00,                                  //该接口描述符的编号为0

 

ENDPOINT_NUMBER,                       //非0端点数量为2,只使用端点主端点输入和输出

 

0x08,                                  //定义为USB大容量存储设备

 

0x06,                                  //使用的子类,为简化块命令

 

0x50,                                  //使用的协议,这里使用单批量传输协议

 

0x00                                   //接口描述符字符串索引,为0,表示没有字符串

 

},

 

//endpoint_descriptor[]

 

{

 

{                                     //主端点输入描述

 

sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7

 

ENDPOINT_DESCRIPTOR,                 //端点描述符类型编号,端点描述符为5

 

MAIN_POINT_IN,                       //端点号,主输入端点

 

ENDPOINT_TYPE_BULK,                  //使用的传输类型,批量传输

 

0x4000,                              //该端点支持的最大包尺寸,64字节

 

0x00                                 //中断扫描时间,对批量传输无效

 

},

 

{                                     //主端点输出描述

 

sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7

 

ENDPOINT_DESCRIPTOR,                 //端点描述符类型编号,端点描述符为5

 

MAIN_POINT_OUT,                      //端点号,主输出端点

 

ENDPOINT_TYPE_BULK,                  //使用的传输类型,批量传输

 

0x4000,                              //该端点支持的最大包尺寸,64字节

 

0x00                                 //中断扫描时间,对批量传输无效

 

}

 

}

 

};

 

其中关于端点的类型定义如下

 

//定义的端点类型

 

#define ENDPOINT_TYPE_CONTROL           0x00 //控制传输

 

#define ENDPOINT_TYPE_ISOCHRONOUS       0x01 //同步传输

 

#define ENDPOINT_TYPE_BULK              0x02 //批量传输

 

#define ENDPOINT_TYPE_INTERRUPT         0x03 //中断传输

 

端点号的定义如下

 

#define MAIN_POINT_OUT           0x02   //2号输出端点

 

#define MAIN_POINT_IN            0x82   //2号输入端点

阅读(2685) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~