最近想做一个USBHID数据收发,查找了很多文章,其中两篇文章作者写的很详细,值得参考
https://www.cnblogs.com/xingboy/p/9913963.html
https://blog.csdn.net/guanlizhongxintishi/article/details/87882207
1.配置时钟树
选择外部时钟源
外部晶振为25M,设置M,N,P,Q,使USB时钟必须是48M
2.设置USB
中断会自动勾选,不用管
配置USB,选择Custom Human Interface Device Class,之前选择了Human Interface Device Class,设备变成了鼠标模式
CUSTOM_HID_FS_BINTERVAL,这个是指数据传输的最小时间间隔(ms)这里修改为跟下面USB传输部分中修改时间间隔一致 USBD_CUSTOM_HID_REPORT_DESC_SIZE 这个是指报告描述符所用的字节数为34(默认为2);USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 表示输入输出端点一次传输数据大小最大为64个字节(默认为2)
3.生成工程
生成代码的时候注意把堆的大小改大一点,不然容易出现设备识别出来出现感叹号的情况
4.工程代码修改
生成工程先编译一下,
在usbd_customhid.h文件中修改发送与接收长度为64
#define CUSTOM_HID_EPIN_SIZE 0x40
#define CUSTOM_HID_EPOUT_SIZE 0x40
在 usbd_custom_hid_if.c 文件里,找到 CUSTOM_HID_ReportDesc_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 */
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x40, // REPORT_COUNT (64)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x40, // REPORT_COUNT (64)
0x75, 0x08, // REPORT_SIZE (8)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
文件中
CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
这个函数为USB接收函数,我们仿照这个函数创建一个USB接收处理函数
CUSTOM_HID_OutDulBuf_FS
static int8_t CUSTOM_HID_Init_FS(void);
static int8_t CUSTOM_HID_DeInit_FS(void);
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state);
static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf);
/**
* @}
*/
USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_FS =
{
CUSTOM_HID_ReportDesc_FS,
CUSTOM_HID_Init_FS,
CUSTOM_HID_DeInit_FS,
CUSTOM_HID_OutEvent_FS,
CUSTOM_HID_OutDulBuf_FS,
};
typedef struct _USBD_CUSTOM_HID_Itf
{
uint8_t *pReport;
int8_t (* Init)(void);
int8_t (* DeInit)(void);
int8_t (* OutEvent)(uint8_t event_idx, uint8_t state);
int8_t (* OutDulBuf)(uint8_t* DulBuf);
} USBD_CUSTOM_HID_ItfTypeDef;
此函数功能为USB接收到数据后再发送出去
static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf)
{
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, DulBuf, 64);
return (0);
}
通过追踪CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)函数,可知它调用了USBD_CUSTOM_HID_ReceivePacket(USBD_HandleTypeDef *pdev)
在此函数中添加数据接收
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutDulBuf(hhid->Report_buf);
5.数据收发验证
代码烧写至开发板,使用PortHelper 工具,点击查找USB,可以发现有一个STM32 Custom Human interface设备,点击打开USB,勾选Hex发送和Hex显示,点击发送,EP2区域会接收64个字节数据
历时三四天,终于把USBHID数据收发调通了,整理一下,分享大家,希望都能有所帮助。