案例中心

\ News

了解

当前位置:首页 > 案例中心 > 了解 > 详情

USB设计原理

发布时间:2007-12-10 浏览:9687次
  USB设备的枚举过程
  
  USB主机在检测到USB设备插入后,就要对设备进行枚举了。为什么要枚举呢?枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。调试USB设备,很重要的一点就是USB的枚举过程,只要枚举成功了,那么就已经成功大半了。
  在说枚举之前,先大概说说USB的一种传输模式——控制传输。这种传输在USB中是非常重要的,它要保证数据的正确性,在设备的枚举过程中都是使用控制传输的。控制传输分为三个阶段:①建立阶段。②数据阶段。③确认阶段。建立(setup)阶段都是由USB主机发起,它是一个setup数据包,里面包含一些数据请求的命令以及一些数据。如果建立阶段是输入请求,那么数据阶段就要输入数据;如果建立阶段是输出请求,那么数据阶段就要输出数据。如果在数据阶段,即便不需要传送数据,也要发一个0长度的数据包。数据阶段过后就是确认阶段。确认阶段刚好跟数据阶段相反,如果是输入请求,则它是一个输出数据包;如果是输出请求,则它是一个输入数据包。确认阶段用来确认数据的正确传输。
  好了,下面我们来看看枚举的详细过程。
  首先,USB主机检测到USB设备插入后,就会先对设备复位。设备复位后,USB主机就会对地址为0的设备发送获取设备描述符的标准请求。所有的USB设备在总线复位后其地址都为0,这样主机就可以跟那些刚刚插入的设备通过地址0通信。主机在建立阶段发出获取设备描述符的输入请求,设备收到该请求后,在数据阶段将设备描述符返回给主机。主机在成功获取到一个数据包的设备描述符后并且确认没有什么错误后(注意:有些USB设备的端点0大小不足18字节(但至少具有8字节),而标准的设备描述有18字节,在这种情况下,USB设备只能暂时按最大包将部分设备描述符返回,而主机在成功获取到前面一部分描述符后,就不会再请求剩下的设备描述符部分,而是进入设置地址阶段),就会返回一个0长度的确认数据包给设备。
  然后主机再对设备复位一下,接下来就会进入到设置地址阶段。这时USB主机发出一个设置地址的请求,并在后面跟着一个0长度的数据输出包。地址包含在建立包中,具体的地址USB主机会负责管理,它会分配一个唯一的地址给新的设备。USB设备在收到地址后,返回0长度的应答包,设备在收到这个0长度应答包的ACK之后,就可以起用新的地址了。这样设备就分配到了一个唯一的设备地址,以后主机就通过它来进行访问该设备。
  然后主机再次获取设备描述符,这次跟第一次可能有点不一样,这次需要获取完全部的18个字节的设备描述符。当然,如果你的端点0缓冲大于18字节的话,那就跟第一次的情形一样了。
  接下来,主机就会获取配置描述符。配置描述符总共为9字节。主机在获取到配置描述符后,根据里面的配置集合总长度,再获取配置集合。配置集合包括配置描述符,接口描述符,端点描符等等。
  如果有字符串描述符的话,还要获取字符串描述符。另外HID设备还有HID描述符等。使用BUS HOUND以及通过串口返回信息,很容易看到具体的过程。总之是主机请求什么,你的程序就响应什么。
  
  下面这些数据是使用BUS HOUND抓的,这个是在WIN2000下抓到的,如果在WINXP下,就看不到设置地址之前的数据。
  写了注释下面的部分就是主机和设备之间的数据通信,而其它的则是主机跟根集线器之间的通信数USB的描述符及各种描述符之间的依赖关系
  USB是个通用的总线,端口都是统一的。但是USB设备却各种各样,
  例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的
  设备的呢?这就要依赖于描述符了。
  USB的描述符主要有设备描述符,配置描述符,接口描述符,
  端点描述符,字符串描述符,HID描述符,报告描述符等等。
  关于报告描述符,请看我以前写的:《USB HID报告及报告描述符简介 》
  
  
  一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多
  少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义
  了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描
  述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;
  端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的
  描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置
  描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,
  先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置
  集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。
  其中可能还会有获取设备序列号,厂商字符串,产品字符串等。
  
  每种描述符都有自己独立的编号,如下:
  #define DEVICE_DEs criptOR               0x01  //设备描述符
  #define CONFIGURATION_DEs criptOR        0x02  //配置描述符
  #define STRING_DEs criptOR               0x03  //字符串描述符
  #define INTERFACE_DEs criptOR            0x04  //接口描述符
  #define ENDPOINT_DEs criptOR             0x05  //端点描述符
  
  下面分别详细介绍一下各描述符。
  
  1.设备描述符
  
  //定义标准的设备描述符结构
  
  typedef struct _DEVICE_DCEs criptOR_STRUCT
  {
  BYTE blength;                               //设备描述符的字节数大小
  BYTE bDes criptorType;                      //设备描述符类型编号
  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_DEs criptOR_STRUCT, * pDEVICE_DEs criptOR_STRUCT;
  
  //实际的设备描述符示例
  code DEVICE_DEs criptOR_STRUCT device_des criptor=   //设备描述符
  {
  sizeof(DEVICE_DEs criptOR_STRUCT),                   //设备描述符的字节数大小,这里是18字节
  DEVICE_DEs criptOR,                              //设备描述符类型编号,设备描述符是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_DEs criptOR_STRUCT
  {
  BYTE bLength;                               //配置描述符的字节数大小
  BYTE bDes criptorType;                       //配置描述符类型编号
  WORD wTotalLength;                          //此配置返回的所有数据大小
  BYTE bNumInterfaces;                        //此配置所支持的接口数量
  BYTE bConfigurationValue;                   //Set_Configuration命令所需要的参数值
  BYTE iConfiguration;                        //描述该配置的字符串的索引值
  BYTE bmAttributes;                          //供电模式的选择
  BYTE MaxPower;                              //设备从总线提取的最大电流
  }
  CONFIGURATION_DEs criptOR_STRUCT, * pCONFIGURATION_DEs criptOR_STRUCT;
  
  2.接口描述符
  
  //定义标准的接口描述符结构
  
  typedef struct _INTERFACE_DEs criptOR_STRUCT
  {
  BYTE bLength;                               //接口描述符的字节数大小
  BYTE bDes criptorType;                       //接口描述符的类型编号
  BYTE bInterfaceNumber;                      //该接口的编号
  BYTE bAlternateSetting;                     //备用的接口描述符编号
  BYTE bNumEndpoints;                         //该接口使用的端点数,不包括端点0
  BYTE bInterfaceClass;                       //接口类型
  BYTE bInterfaceSubClass;                    //接口子类型
  BYTE bInterfaceProtocol;                    //接口遵循的协议
  BYTE iInterface;                            //描述该接口的字符串索引值
  }
  INTERFACE_DEs criptOR_STRUCT, * pINTERFACE_DEs criptOR_STRUCT;
  
  4.端点描述符
  
  //定义标准的端点描述符结构
  
  typedef struct _ENDPOINT_DEs criptOR_STRUCT
  {
  BYTE bLegth;                                //端点描述符字节数大小
  BYTE bDes criptorType;                       //端点描述符类型编号
  BYTE bEndpointAddress;                      //端点地址及输入输出属性
  BYTE bmAttributes;                          //端点的传输类型属性
  WORD wMaxPacketSize;                        //端点收、发的最大包大小
  BYTE bInterval;                             //主机查询端点的时间间隔
  }
  ENDPOINT_DEs criptOR_STRUCT, * pENDPOINT_DEs criptOR_STRUCT;
  
  下面是一个配置描述符集合的定义
  typedef struct _CON_INT_ENDP_DEs criptOR_STRUCT
  {
  CONFIGURATION_DEs criptOR_STRUCT configuration_des criptor;
  INTERFACE_DEs criptOR_STRUCT  interface_descritor;
  ENDPOINT_DEs criptOR_STRUCT  endpoint_des criptor[ENDPOINT_NUMBER];
  }CON_INT_ENDP_DEs criptOR_STRUCT;
  
  配置描述符集合的示例
  
  
  code CON_INT_ENDP_DEs criptOR_STRUCT con_int_endp_des criptor=  //配置描述符集合
  {
  //configuration_des criptor                     //配置描述符
  {
  sizeof(CONFIGURATION_DEs criptOR_STRUCT),      //配置描述符的字节数大小,这里为9
  CONFIGURATION_DEs criptOR,                     //配置描述符类型编号,配置描述符为2
  (sizeof(CONFIGURATION_DEs criptOR_STRUCT)+
  sizeof(INTERFACE_DEs criptOR_STRUCT)+
  sizeof(ENDPOINT_DEs criptOR_STRUCT)*ENDPOINT_NUMBER)*256+
  (sizeof(CONFIGURATION_DEs criptOR_STRUCT)+
  sizeof(INTERFACE_DEs criptOR_STRUCT)+
  sizeof(ENDPOINT_DEs criptOR_STRUCT)*ENDPOINT_NUMBER)/256,   //配置描述符集合的总大小
  0x01,                                  //只包含一个接口
  0x01,                                  //该配置的编号
  0x00,                                  //iConfiguration字段
  0x80,                                  //采用总线供电,不支持远程唤醒
  0xC8                                   //从总线获取最大电流400mA
  },
  //interface_descritor                   //接口描述符
  {
  sizeof(INTERFACE_DEs criptOR_STRUCT),   //接口描述符的字节数大小,这里为9
  INTERFACE_DEs criptOR,                  //接口描述符类型编号,接口描述符为3
  0x00,                                  //接口编号为4
  0x00,                                  //该接口描述符的编号为0
  ENDPOINT_NUMBER,                       //非0端点数量为2,只使用端点主端点输入和输出
  0x08,                                  //定义为USB大容量存储设备
  0x06,                                  //使用的子类,为简化块命令
  0x50,                                  //使用的协议,这里使用单批量传输协议
  0x00                                   //接口描述符字符串索引,为0,表示没有字符串
  },
  
  //endpoint_des criptor[]
  {
  {                                     //主端点输入描述
  sizeof(ENDPOINT_DEs criptOR_STRUCT),  //端点描述符的字节数大小,这里为7
  ENDPOINT_DEs criptOR,                 //端点描述符类型编号,端点描述符为5
  MAIN_POINT_IN,                       //端点号,主输入端点
  ENDPOINT_TYPE_BULK,                  //使用的传输类型,批量传输
  0x4000,                              //该端点支持的最大包尺寸,64字节
  0x00                                 //中断扫描时间,对批量传输无效
  },
  
  {                                     //主端点输出描述
  sizeof(ENDPOINT_DEs criptOR_STRUCT),  //端点描述符的字节数大小,这里为7
  ENDPOINT_DEs criptOR,                 //端点描述符类型编号,端点描述符为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号输入端点
  
  
  
  

上一篇:运动物体的拍摄 2025-12-31

下一篇:关于 CD4067模拟开关 应用 2025-12-31

案例中心|产品中心|解决方案|新闻资讯|合作伙伴|技术支持|联系我们
Copyright © 2002-2025 深圳响拇指电子科技有限公司 版权所有 粤ICP备11091659号 0755-83031813