基于STM32 HAL库的自定义USB HID设备通信
作者:互联网
最近有个项目需要用到STM32的高速通信,准备调试一下STM32的USB功能,但是发现F103C8T6只有全速USB,因此作为HID设备一帧只能发送64字节,最小间隔是1ms,显然这个是很慢不能满足要求了,高速USB还是只能外接高速USB PHY。这里只记录一下调试过程不说原理了,USB协议十分复杂,学习的书籍还是参考《圈圈教你玩USB》比较合适。
1.代码生成
方便起见直接用CubeMX生成大部分的代码,然后在上面修改即可,步骤参见如下:https://www.cnblogs.com/untitled-x6/p/13439067.html。
直接生成代码后是无法识别的,因为报文描述符没有配置。这里推荐一个报文描述符的生成工具“hid报告描述符工具”,使用方法见如下。http://www.mcublog.cn/software/2020_03/bgmsf-scgj/
配置完成,将数组复制到usbd_custom_hid_if.c文件报告描述符数组中__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END,就可以发送接收了。
发送数据函数为USBD_CUSTOM_HID_SendReport(),接收数据函数同样在usbd_custom_hid_if.c文件里面的函数CUSTOM_HID_OutEvent_FS()。
/** Usb HID report descriptor. */
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
/* USER CODE BEGIN 0 */
0x05,0x8c, /* USAGE_PAGE (ST Page) */
0x09,0x01, /* USAGE (Demo Kit) */
0xa1,0x01, /* COLLECTION (Application) */
// The Input report
0x09,0x03, // USAGE ID - Vendor defined
0x15,0x00, // LOGICAL_MINIMUM (0)
0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255)
0x75,0x08, // REPORT_SIZE (8bit)
0x95,0x40, // REPORT_COUNT (64Byte)
0x81,0x02, // INPUT (Data,Var,Abs)
// The Output report
0x09,0x04, // USAGE ID - Vendor defined
0x15,0x00, // LOGICAL_MINIMUM (0)
0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255)
0x75,0x08, // REPORT_SIZE (8bit)
0x95,0x40, // REPORT_COUNT (64Byte)
0x91,0x02, // OUTPUT (Data,Var,Abs)
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
2.调试
上位机调试工具目前我用了两款,一款是PortHelper,另外一款是经典的Bus Hound。
2.1 PortHelper
这一款使用起来比较简单,功能也十分多,除了串口,USB HID外还有网口,蓝牙等。
首先查找USB,然后根据USB设备的名称找到STM32的USB接口,我这里的名称是USB_TEST。该部分在usbd_desc.c文件里面使用宏定义。调用的顺序是MX_USB_DEVICE_Init()函数对USBD_DescriptorsTypeDef结构体FS_Desc初始化,从而初始化一些参数。源代码如下:
USBD_DescriptorsTypeDef FS_Desc =
{
USBD_FS_DeviceDescriptor
, USBD_FS_LangIDStrDescriptor
, USBD_FS_ManufacturerStrDescriptor
, USBD_FS_ProductStrDescriptor
, USBD_FS_SerialStrDescriptor
, USBD_FS_ConfigStrDescriptor
, USBD_FS_InterfaceStrDescriptor
};
另外注意宏定义的这些参数是在CubeMX里面可以修改的,其中PID和VID两个参数十分重要,windows下需要这两个参数区分不同的USB器件。
#define USBD_VID 1155
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PID_FS 22352
#define USBD_PRODUCT_STRING_FS "USB_TEST"
#define USBD_CONFIGURATION_STRING_FS "Custom HID Config"
#define USBD_INTERFACE_STRING_FS "Custom HID Interface"
找到设备后,打开,然后在发送区发送数据即可。此处由于我在主函数中规定了只有STM32接收到的第一个字节是0x55,才会通过USB HID返回一个字符串“USB_CUSTOM_HID TEST”。对于通信协议可以自己定义,但是注意一帧数据最大是64个字节,可见除去协议开销,HID的通信速度并不快。
这里有个连续发送间隔,我设置了10ms,但是这款工具仍然是以1秒发送间隔发送,不知道有没有人用过1ms发送间隔的。
另外这款软件也可以监听USB端口的数据,点击监视HID,然后启动监视即可看到发送接收的数据。
2.2 Bus Hound
打开软件后,首先点击Device,根据程序设置的PID和VID找到STM32的USB端口,这里需要注意,要勾选USB端口的上一层USB Input Device,然后才可以进行一些列操作。
2.2.1 发送命令
点击Device页面的 Send Commands,然后在弹出的页面选择USB。
这里可以清楚地看到,STM32的USB HID有三个端点,端点0只支持控制传输,传输种类是3,这个端点在USB枚举时会和上位机通信,获取设备的相关信息,枚举成功后才会识别为USB设备。端点0是不可配置的。
端点2有输出和输出两个端口,只支持中断传输,传输种类是3,最大数据包为64字节(第一节里面配置的REPORT_COUNT),每个字节有效位为8位(第一节里面配置的REPORT_SIZE)。
实际上,端点2在程序里面定义成了两个端点,发送端点和接收端点。而这两个端点号是相互关联,不能随意定义的。例如发送端点是0x01,那么接收端点必定是0x81。
在USB协议中端点地址是一个uint_8t的变量,端点地址:0~3位是端点号,第7位是方向(0-OUT,1-IN),那么由这5位可以确定32个端点地址。其中输入端点0-15输出端点0-15。
端点号在"usbd_customhid.h"文件里面宏定义,同时定义了端点一帧的大小。这个宏同样在MX_USB_DEVICE_Init函数初始化调用。
/** @defgroup USBD_CUSTOM_HID_Exported_Defines
* @{
*/
#define CUSTOM_HID_EPIN_ADDR 0x82U
#define CUSTOM_HID_EPIN_SIZE 0x40U
#define CUSTOM_HID_EPOUT_ADDR 0x02U
#define CUSTOM_HID_EPOUT_SIZE 0x40U
修改发送字节数为64,然后修改下方发送的数据,点击RUN就能发送一次数据。
2.2.1 USB监视
同样该软件也有监视的功能,回到打开软件的界面,点击第一个Capture就可以查看USB端口的发送和接收数据(必须先选中需要监视的USB端口)。发送和接收的数据如下所示。
发送的数据:
接收的数据:
参考文档:
【1】http://usb.baiheee.com/usb_projects/easy_usb_51_programer_plus/usb_hid_user_def.html
【2】https://zhuanlan.zhihu.com/p/338157070
【3】http://www.mcublog.cn/software/2020_03/bgmsf-scgj/
【4】https://www.cnblogs.com/xingboy/p/9913963.html
【5】https://www.cnblogs.com/untitled-x6/p/13439067.html
标签:FS,HAL,USB,自定义,CUSTOM,USBD,HID,端点 来源: https://blog.csdn.net/radarsmile/article/details/122811081