STM32CubeMx生成的USB CDC代码修改为WINUSB设备
前言
WINUSB在Windows中是可以免驱的,那HID也是免驱的,用HID不是一样吗?不一样! HID采用中断传输,传输速度上不去,如果是使用的是USB2.0 FULL speed,那速度更低,可能很多场合都满足不了了。但是WINUSB就不一样了,winusb可以采用批量传输,数据吞吐量大大提高。(HID理论速度:10001964Byte/s, 1ms传输1次, 1次传输19个DAT事务, 1个DAT事务最大64B,好像也不慢了),下面就介绍一下STM32如何在CDC设备的基础上修改为WINUSB设备。
关于如何对WINUSB进行DEBUG
请注意,Windows仅查询OS字符串描述符一次,在开发过程中会造成麻烦。OS描述符存储在注册表中
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags\VVVVPPPPRRRR
(VVVV - VID; PPPP - PID; RRRR - 版本号)
请删除你USB设备对应的注册表项,然后使用USBDeview卸载设备,以便始终获得新的设备插入行为。
Src/usbd_desc.c
第128行,USBD_SUPPORT_USER_STRING_DESC后添加
#if (USBD_SUPPORT_WINUSB==1)
uint8_t *USBD_WinUSBOSStrDescriptor(uint16_t *length);
uint8_t *USBD_WinUSBOSFeatureDescriptor(uint16_t *length);
uint8_t *USBD_WinUSBOSPropertyDescriptor(uint16_t *length);
#endif // (USBD_SUPPORT_WINUSB==1)
在USBD_DescriptorsTypeDef FS_Desc中,最后的地方添加
#if (USBD_SUPPORT_WINUSB == 1)
, USBD_WinUSBOSFeatureDescriptor
, USBD_WinUSBOSPropertyDescriptor
#endif // (USBD_SUPPORT_WINUSB==1)
在/* USB_DeviceDescriptor */后添加
#define USB_LEN_OS_FEATURE_DESC 0x28
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_WINUSB_OSFeatureDesc[USB_LEN_OS_FEATURE_DESC] __ALIGN_END =
{
0x28, 0, 0, 0, // length
0, 1, // bcd version 1.0
4, 0, // windex: extended compat ID descritor
1, // no of function
0, 0, 0, 0, 0, 0, 0, // reserve 7 bytes
// function
0, // interface no
0, // reserved
W, I, N, U, S, B, 0, 0, // first ID
0, 0, 0, 0, 0, 0, 0, 0, // second ID
0, 0, 0, 0, 0, 0 // reserved 6 bytes
};
#define USB_LEN_OS_PROPERTY_DESC 0x8E
#if defined ( __ICCARM__ ) /* IAR Compiler */
#pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_WINUSB_OSPropertyDesc[USB_LEN_OS_PROPERTY_DESC] __ALIGN_END =
{
0x8E, 0, 0, 0, // length 246 byte
0x00, 0x01, // BCD version 1.0
0x05, 0x00, // Extended Property Descriptor Index(5)
0x01, 0x00, // number of section (1)
//; property section
0x84, 0x00, 0x00, 0x00, // size of property section
0x1, 0, 0, 0, //; property data type (1)
0x28, 0, //; property name length (42)
D, 0,
e, 0,
v, 0,
i, 0,
c, 0,
e, 0,
I, 0,
n, 0,
t, 0,
e, 0,
r, 0,
f, 0,
a, 0,
c, 0,
e, 0,
G, 0,
U, 0,
I, 0,
D, 0,
0, 0,
// D6805E56-0447-4049-9848-46D6B2AC5D28
0x4E, 0, 0, 0, // ; property data length
{, 0,
1, 0,
3, 0,
E, 0,
B, 0,
3, 0,
6, 0,
0, 0,
B, 0,
-, 0,
B, 0,
C, 0,
1, 0,
E, 0,
-, 0,
4, 0,
6, 0,
C, 0,
B, 0,
-, 0,
A, 0,
C, 0,
8, 0,
B, 0,
-, 0,
E, 0,
F, 0,
3, 0,
D, 0,
A, 0,
4, 0,
7, 0,
B, 0,
4, 0,
0, 0,
6, 0,
2, 0,
}, 0,
0, 0,
};
在文件末尾添加
#if (USBD_SUPPORT_WINUSB==1)
const uint8_t USBD_OS_STRING[8] = {
M,
S,
F,
T,
1,
0,
0,
USB_REQ_MS_VENDOR_CODE,
};
uint8_t *USBD_WinUSBOSStrDescriptor(uint16_t *length)
{
USBD_GetString((uint8_t *)USBD_OS_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
uint8_t *USBD_WinUSBOSFeatureDescriptor(uint16_t *length)
{
*length = USB_LEN_OS_FEATURE_DESC;
return USBD_WINUSB_OSFeatureDesc;
}
uint8_t *USBD_WinUSBOSPropertyDescriptor(uint16_t *length)
{
*length = USB_LEN_OS_PROPERTY_DESC;
return USBD_WINUSB_OSPropertyDesc;
}
#endif // (USBD_SUPPORT_WINUSB==1)
Inc/usbd_conf.h
在文件中添加
#define USBD_SUPPORT_WINUSB 1
Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
在static uint8_t USBD_GetLen(uint8_t *buf);后添加
#if (USBD_SUPPORT_WINUSB==1)
static void USBD_WinUSBGetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
#endif // (USBD_SUPPORT_WINUSB==1)
在USBD_StdDevReq函数中,case USB_REQ_CLEAR_FEATURE:分支后面添加
#if (USBD_SUPPORT_WINUSB==1)
case USB_REQ_MS_VENDOR_CODE:
USBD_WinUSBGetDescriptor( pdev, req );
break;
#endif // (USBD_SUPPORT_WINUSB==1)
在USBD_StdItfReq函数中,switch的default分支中添加
#if (USBD_SUPPORT_WINUSB==1)
if ( req-bmRequest == 0xC1 ) {
USBD_WinUSBGetDescriptor( pdev, req );
break;
}
#endif // (USBD_SUPPORT_WINUSB==1)
在USBD_GetDescriptor函数中,第一个switch的case USB_DESC_TYPE_STRING:分支中的USBD_IDX_INTERFACE_STR子分支后添加
#if (USBD_SUPPORT_WINUSB==1)
case 0xEE: // OS String
pbuf = (uint8_t *) pdev-pClass-GetWinUSBOSDescriptor(len);
break;
#endif // (USBD_SUPPORT_WINUSB==1)
在该文件最后添加
#if (USBD_SUPPORT_WINUSB==1)
static void USBD_WinUSBGetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
uint16_t len;
uint8_t *pbuf;
switch (req-wIndex)
{
case 0x04: // compat ID
pbuf = pdev-pDesc-GetWinUSBOSFeatureDescriptor(len);
break;
case 0x05:
pbuf = pdev-pDesc-GetWinUSBOSPropertyDescriptor(len);
break;
default:
USBD_CtlError(pdev , req);
return;
}
if((len != 0) (req-wLength != 0))
{
len = MIN(len , req-wLength);
USBD_CtlSendData (pdev,
pbuf,
len);
}
}
#endif // (USBD_SUPPORT_WINUSB==1)
Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h
在#define USB_REQ_SYNCH_FRAME后添加
// WinUSB MS Vendor Code
#define USB_REQ_MS_VENDOR_CODE 0xA0
在typedef struct _Device_cb USBD_ClassTypeDef中,末尾添加
#if (USBD_SUPPORT_WINUSB == 1)
uint8_t *(*GetWinUSBOSDescriptor)(uint16_t *length);
#endif
在typedef struct USBD_DescriptorsTypeDef中,末尾添加
#if (USBD_SUPPORT_WINUSB==1)
uint8_t *(*GetWinUSBOSFeatureDescriptor)(uint16_t *length);
uint8_t *(*GetWinUSBOSPropertyDescriptor)(uint16_t *length);
#endif
Middlewares/ST/STM32_USB_Device_Library/CDC/inc/usbd_cdc.c
在static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);后添加
#if (USBD_SUPPORT_WINUSB==1)
uint8_t* USBD_WinUSBOSStrDescriptor(uint16_t *length);
#endif //(USBD_SUPPORT_WINUSB==1)
在USBD_ClassTypeDef USBD_CDC中,末尾添加
#if (USBD_SUPPORT_WINUSB==1)
USBD_WinUSBOSStrDescriptor
#endif // (USBD_SUPPORT_WINUSB==1)
本文参考自:https://0w0.pw/417.html
更新于:3个月前相关文章
- 春节代码 新年快乐html 灯笼js
- 圣诞树代码 下雪
- 表白代码,爱心树html
- git pull 从远程获取代码并合并本地的版本
- 使用C#的Socket实现最简单的TCP通信示例代码
- vscode中自动将json格式的内容自动生成对应的代码
- 代码写得好 在哪里都能蹦迪
- C#检测网络端口是否被占用的参考代码
- vscode打开代码中文显示乱码的问题
- linux中USB设备的绑定和解绑(类似于Windows中disable和enable)
- HTML-CSS-JS Prettify 代码格式化插件
- Linux下不写驱动如何访问PCI/PCIe设备的内存空间
- 有没有一个在线工具可以将Python代码转换为Java代码?
- 为什么C代码比Python代码运行得更快?
- 你如何在 Python 中编写自动售货机代码?
- 代码中的解耦思维
- 在C#中通过Windows API读写INI文件的简单实现代码
- C#中通过代码获取当前系统主板BIOS中序列号等信息的方法
- Python代码转换成C++
- Java高级面试题解析及代码示例