【STM32F769Discovery开发板试用】USB-HS HID收发简单测评
[复制链接]
STM32的大部分评估板和第三方开发板都带有USB接口,USB接口配置为Device模式的话就可以跟电脑进行通信了,一般Device模式又分为HID/CDC/DFU/MS/Audio等协议,其中HID为人体学输入设备,CDC为虚拟串口设备,DFU为固件升级设备,MS为大容量存储设备,Audio为音频通信设备,HID适用于简单/低速的透传通信或是虚拟为鼠标键盘等人体学输入设备,可以自定义每个透传字段的长度,特征值等,不需要对数据包中的逐个字节进行解析;CDC适用于高速/大流量的透传通信,可以以winusb形式与电脑进行通信,不可以自定义透传字段特征值,只能从一帧数据包中逐个字节进行解析;DFU只适用于主控代码升级;MS只适用于将主控虚拟为U盘等存储设备;Audio只适用于将主控虚拟为声卡设备。在数据透传应用上,HID协议与CDC协议极其相似。
官方给出的搭建HID代码例程的步骤非常简单,只需要使用CubeMX并配置发送字段即可完成,一步步开始吧,不过USB通信是需要固定48MHz时钟的,对于官方的评估板或者时钟设计参考官方评估板的第三方开发板,一般尽量使用CubeMX的板级初始化功能(即Access to Board Selector):
不使用芯片级初始化功能(Access to MCU Selector)意义在于,可以正确初始化USB时钟,避免不必要的麻烦。进入CubeMX引脚配置界面,将不必要的外设如ETH I2S SAI QSPI FMC LTDC等全部剔除,并设置USBHS(高速接口)为Device模式,外挂PHY,SOF不启用:
为什么是外挂PHY呢,很简单,看原理图和板子的芯片布局就知道了:
板子F769主控的USBHS接口是通过一块USB3320 USB-PHY芯片引出物理层microUSB接口的。
然后是对于USB Device第三方外设的配置,设置模式为Custom HID:
最后确认USB时钟频率为48MHz即可生成工程:
工程生成后,按照ST官方给出USBHID文档的指引,需要替换usbd_custom_hid_if.c文件下的CUSTOM_HID_ReportDesc_HS枚举数组:
#define REPORT_INPUT_LEN 64
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_HS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06,0xA0,0xFF,//用法页(FFA0h, vendor defined)
0x09, 0x01,//用法(vendor defined)
0xA1, 0x01,//集合(Application)
0x09, 0x02 ,//用法(vendor defined)
0xA1, 0x00,//集合(Physical)
0x06,0xA1,0xFF,//用法页(vendor defined)
//输入报告
0x09, 0x03 ,//用法(vendor defined)
0x09, 0x04,//用法(vendor defined)
0x15, 0x80,//逻辑最小值(0x80 or -128)
0x25, 0x7F,//逻辑最大值(0x7F or 127)
0x35, 0x00,//物理最小值(0)
0x45, 0xFF,//物理最大值(255)
0x75, 0x08,//报告长度Report size (8位)
0x95, REPORT_INPUT_LEN,
//报告数值
0x81, 0x02,
//输入(data, variable, absolute)
//输出报告
0x09, 0x05,
//用法(vendor defined)
0x09, 0x06,
//用法(vendor defined)
0x15, 0x80,
//逻辑最小值(0x80 or -128)
0x25, 0x7F,
//逻辑最大值(0x7F or 127)
0x35, 0x00,
//物理最小值(0)
0x45, 0xFF,
//物理最大值(255)
0x75, 0x08,
//报告长度(8位)
0x95, 0x40,
//报告数值(64 fields)
0x91, 0x02,
//输出(data, variable, absolute)
0xC0,
//集合结束(Physical)
0xC0
//集合结束(Application)
};
这个数组会被初始化函数集USBD_CustomHID_fops_HS调用:
USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_HS =
{
CUSTOM_HID_ReportDesc_HS,
CUSTOM_HID_Init_HS,
CUSTOM_HID_DeInit_HS,
CUSTOM_HID_OutEvent_HS
};
然后修改usbd_conf.h的USBD_CUSTOM_HID_REPORT_DESC_SIZE,这里填52,即刚刚那个数组的长度:
添加回调函数,这步必不可少:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_IncTick();
}
上述代码修改完毕之后就可以用USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));函数进行USBHID发送,每次调用函数发送的单位是64字节,固定的:
当然为了便于系统和HID软件识别,需要修改VID PID 设备名等参数:
#define USBD_VID 1155
#define USBD_PID_HS 22352
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PRODUCT_STRING_HS "donatello1996 STM32F769 USBHID Device"
#define USBD_CONFIGURATION_STRING_HS "Custom HID Config"
#define USBD_INTERFACE_STRING_HS "Custom HID Interface"
最后使用示波器抓取发送函数耗时:
while(1)
{
GPIOJ->BSRR |= 0x00000002;
USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));
GPIOJ->BSRR |= 0x00020000;
USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));
}
可以看出,即使是HID这种低速模式,发送间隔居然也缩小到不可思议的500ns,也就是1us可以发送128个字节,那么1s就可以发送128MB,在多数项目中绝对够用了,如果是使用高速的CDC模式则更快,1s发送几百MB不在话下。
|