随着电脑更新换代、USB接口逐渐替代传统接口(串口等),为了更加方便与PC机进行通讯,引入USB通讯。
- 如何才能实现产品与PC又快又稳定通讯
- 如何解决串口通讯中接受不定时帧间隔问题
- 如何实现即插即用的USB免驱功能
USB免驱我们首先想到的是便是标准类别的USB设备(USB鼠标、键盘、游戏杆等)或者大容量存储(U盘、基于闪存的存储、媒体播放器等)不需要安装驱动程序,因为Windows会在设备第一次插入时自动处理,但HID采用中断类数据传输、传输数据量限制显然不适合大数据量快速通讯。
USB使用USB内部CDC类虚拟串口通讯速度要比我们普通的串口通讯速率要快,但需要安装驱动,有时现场安装环境不同可能出现安装驱动失败问题,造成用户体验度差。
那么有没有既能实现免驱、有能兼容虚拟串口提高通讯速率呢?
答案是肯定的!
WCID是WinUsb设备功能的扩展,由Microsoft在Windows8开发人员预览版期间提出,WinUSB自Windows XP SP2以来一直是Windows一部分的功能。
WinUsb设备是一种通用串行总线(USB)设备,其固件定义了某些Microsoft操作系统(OS)特征描述符,这些描述符将兼容ID报告为"WINUSB"。WinUsb设备的用途是让Windows将Winusb.sys作为设备的功能驱动程序载入,而无需自定义INF文件。对于WinUsb设备,你无须为设备分发INF文件,这大大简化了驱动程序安装过程。截至2012年5月,从Windows Vista开始的所有平台上都提供了自动 WinUSB WCID 驱动程序。在 Windows 8 或更高版本地系统上已经集成了该驱动程序,这意味着Windows 8 或更高版本地系统上不需要安装驱动程序,系统自动会匹配WinUSB驱动,而对于Vista、Windows7、XP系统,可以通过一些第三方软件(如Zadig)来安装或生成WCID版本的驱动程序,同样只需要安装一次WCID版本的驱动软件,以后所有WCID设备都可以使用该驱动,间接实现了免驱
WinUsb限制条件
WinUSB有许多限制条件,一般来说注意以下几点即可:
- WinUSB不支持Windows 2003 ( 32bit/64bit )
- WinUSB不支持Windows XP 64位(可以通过第三方驱动支持)
- USB设备版本必需是2.0或2.0以上,WinUSB不支持USB1.0和1.1
WinUsb的版本支持
- Windows 7 在基于 x86、基于 x64 和基于 Itanium 的系统上支持 WinUSB。
- 较新版本的 Windows 在基于 x86 和基于 x64 的系统上支持 WinUSB。
- WinUSB 支持从 Windows 8 开始支持同步传输。
USB全速设备的插入检测
常规USB设备枚举
USB设备插入主机后、会有以下活动:
USB设备连接之后一般枚举过程
- §主机(下称H):你是什么设备?
- §设备(下称D):12 01 0100……Device Descriptor
- § H:你有几种功能?
- § D:09 02 09……Configuration Descriptor
- § H:每个功能有几个接口?
- § D:09 04 00……Interface Descriptor
- § H:每个接口使用哪几个端点?
- § D:06 05 82……Endpoint Descriptor
- § H:好了,我知道你是谁了,开始传输数据吧!
- D:OK,Read Go
WinUsb设备枚举
- 当Windows检测到有USB设备插入,首先会向设备索取设备描述符长度,设备正确回复后Windows分配USB设备地址,并以之前收到的实际长度去获取完整的设备描述符。
- 获取USB设备信息,包含基本配置、设备接口、端点等信息
- Windows判断第一步获取的bcdUSB版本号如果大于等2.0,则还会索引0xEE处的OS字符串描述符,确认设备是否支持WCID,若回复内容为MSFT100则说明该设备支持WCID,后续才会继续获取兼容ID特征描述等
- 获取兼容ID特征描述符,回复兼容信息为WinUSB设备
- 获取兼容ID后,系统会根据兼容ID的情况请求属性描述符,对于WinUSB设备需要注册设备接口GUID
- 后续其他信息获取…
基于STM32F407ZGTX正点原子开发板抓包分析如下:
在线调试:
OS字符串描述符(0xEE获取”MSFT100”)
扩展属性描述符(注册设备接口GUID) 仅在设备第一次枚举被识别到(也可通过修改VID、PID)
扫盲:VID、PID
VID(Vender ID供应商识别码)和PID(Product ID产品识别码)
每一个USB设备都有VID和PID,其中,VID是由供应商向USB-IF(Implementers Forum 应用者论坛)申请。每一个供应商的VID是唯一,PID是由供应商自行决定。
主机通过VID和PID来识别不同的设备,根据他们(以及设备的版本号),可以给设备加载或安装相应的驱动程序。VID和PID的长度都是两个字节
使用”Device Monitoring Studio”应用层抓包软件抓包如下:
首先获取设备描述符
获取配置描述符
根据配置描述符获取接口描述符、输入、输出端点描述符
各个描述符的含义
设备描述符(Device Descriptor)
Eg:
Joystick_DeviceDescriptor[ ] =
{
0x12, /* 整个Descriptor的长度:18字节 */
0x01, /* Descriptor的类别:Device Descriptor(0x01) */
0x00, 0x02, /* 设备所遵循的USB协议的版本号:2.00 */
0x00, /* 设备所实现的类:由每个接口描述符描述所实现的类*/
0x00, /* 设备所实现的子类:由每个接口描述符描述 */
0x00, /* 设备所遵循的协议类别:由每个接口描述符描述*/
0x40, /* 端点0的最大数据包长度:64字节*/
0x83, 0x04, /* IDVendor: 0x0483 (for ST) */
0x10, 0x57, /* IDProduct: 0x5710 */
0x00, 0x02, /* bcdDevice: 2.00*/
1, /* 用于描述生产厂商的字符描述符的索引号 */
2, /* 用于描述产品的字符描述符的索引号*/
3, /* 用于描述产品系列号的字符描述符的索引号*/
0x01 /* 设备所支持的配置数目:1*/
}
配置描述符号:
Eg:
Joystick_ConfigurationDescriptor[ ] =
0x09, /* 描述符的长度:9字节 */
0x02, /* 描述符的类型: 0x02 配置描述符 */
JOYSTICK_SIZ_CONFIG_DESC, 0x00, /* 完整的描述符包括接口描述符、 端点描述符和类描述符的长度 */
0x01, /* 配置所支持的接口数目:1*/
0x01, /* 用SetConfiguration选择此配置时所指定的配置号*/
0x00, /* 用于描述此配置的字符描述符的索引号:0 */
0xE0, /* 供电配置:B7(1 保留), B6(自供电), B5(远程唤醒), B4-
B0(0 保留) */
0x32, /* 最大功耗,以2mA为单位计算:0x32表示 100mA */
接口描述符:
Eg:
Joystick_InterfaceDescriptor[ ] =
0x09, /* 描述符的长度:9字节 */
4, /* 描述符的类型:0x04接口描述符(Interface) */
0x00, /* 选择此接口的索引号,从0开始计算:0 */
0x00, /* 用于选择此设置的索引号:0 */
0x01, /* 实现此接口需要使用的端点数目:1 */
0x03, /* 此接口所遵循的类:HID Class 如果是WinUsb修改为0xFF*/
0x01, /* 此接口所遵循的子类:1=BOOT, 0=no boot */
0x02, /* 此接口所支持的协议:0自定义、1键盘、2鼠标 */
0, /* 用于描述此接口的字符描述符的索引号 */
端点描述符:
Eg:
Joystick_InterfaceDescriptor[ ] =
0x07, /* 描述符长度:7字节 */
5, /* 描述符类型:端点描述符*/
0x81, /* 端点的特性:B3-B0(端点号), B6-B4(0), B7(1=IN, 0=OUT)
0x81:Endpoint1/ IN */
0x03, /* 端点的类型:B1-B0(00=控制 01=同步 10=大容量 11=中断)
0x03:中断端点 */
0x04, 0x00 /* 此端点的最大有效数据长度:4 字节 */
0x20, /* 主机查询此端点数据的间隔时间:(1ms或125us单位):
0x20:32 ms */
各种传输特性比较
USB HID采用中断方式
FS最大速率62.5KB/s 最大一包64字节
LS 800B/S 最大一包8字节
WinUsb采用Bulk传输
FS 最大速率800KB/s 最大一包64字节 传输受硬件影响
数据拆包接收发送规则:
STM32、GD32芯片数据接收数据采用分包接收,每包数据64字节。
数据发送库函数优化掉,不需要特别关心分包发送。
USB数据同步
计算机管理->通用串行总线设备->WinUsb
注意点:
- 上位机在扫描WinUsb设备名称时,会过滤‘-’字符串,导致识别失败,故WinUsb设备名称禁止出现‘-’
- 接口描述符中bIntergaceClasss字段必须给0xFF 否则上位机报错
参考:
WinUsb实现USB免驱通讯介绍_嵌入式小娄的博客-CSDN博客
STM32 WinUSB(WCID)免驱高速通信 20M/s(附详细测试)_bingwueyi的博客-CSDN博客
https://www.cnblogs.com/yanye0xff/p/16710614.html
GD32移植WinUsb 成功例程如下:
https://download.csdn.net/download/qq_35257512/87838361?spm=1001.2014.3001.5503
STM32移植WinUsb成功例程如下:
https://download.csdn.net/download/qq_35257512/87755345?spm=1001.2014.3001.5503