之前这半个月的时间在搞USB自定义HID双向通信,刚开始用的是官方CUBEMX例程,但是后来遇到问题不得不自己生成USB工程代码,参考了网上的一些文档,发现还是存在一些问题导致无法枚举成功,所以这里写一个文档详细记下整个流程,供自己以后参考。
所用CubeMx版本为4.16,采用芯片是stm32f373RCT6,下面是整个流程
一、新建一个工程
二、选择芯片具体型号
如果是网上买的板子或者自己画的板子,那么选择MCU Selector,如果是ST官方的开发板,选择Board Selector,我是网上买的stm32f373rct6,然后在2里面进行相应配置,由于要使用USB,所以在3里面添加USB外设。
双击具体型号,进行下一步配置
三、引脚及时钟配置
由于f373的usb对应引脚是PA11,PA12,所以直接在图形中点击引脚复用为USB功能,然后在2出选择Custom HID,3处RCC选择陶瓷晶振
Sys处选择 Serial Wire,USB处打√
时钟配置:软件会让你选择是否由它自动配置时钟,你可以自由选择,此处我选择的是外部8M时钟,f373USB时钟是48M
四、工程配置
主要的选项就是工程名,工程位置,选择编译工具,我选择的是MDK-ARM V5
五、点击图中如下图标生成工程代码
六、对工程代码第一次编译
首先工程代码编译选项,各人根据自己情况进行配置,编译工程代码,运行之后可以在PC设备管理器看到有USB设备插入,但是该USB设备是无法正常工作的。需要对代码进行一些修改才行
在文件usbd_custom_hid_if.c里面的同名数组__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[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)
//14
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, 0x40,//(64 fields)
0x81, 0x02,//(data, variable, absolute)
//32
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)
//52
然后在文件usbd_conf.h里修改该数组大USBD_CUSTOM_HID_REPORT_DESC_SIZE为52,即报告描述符所用的字节数为52(默认为2),同时将该文件中的宏USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 大小改为64(该宏的作用有待商榷);此外更改usbd_customhid.h中的宏CUSTOM_HID_EPIN_SIZE大小为64,CUSTOM_HID_EPOUT_SIZE 大小为64,表示输入输出端点一次传输数据大小最大为64字节
七、此时再次编译工程,就可以成功枚举出CustomHID设备了
八、数据的发送
直接调用发送函数USBD_CUSTOM_HID_SendReport就可以实现数据的发送
九、数据的接收
(1)数据的接收就不是简单调用了,而要进行一些修改
(2)首先在usbd_customhid.c文件中定义一个数组和一个全局变量
unsigned char USB_Recive_Buffer[64]; //用来存储接收数据的buffer
volatile unsigned char USB_Received_Count = 0; //用来表示接收数据的字节个数
(注意在对应的头文件中extern,从而便于main.c文件调用)
然后对接收函数进行修改,修改之后的样子如下:
static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
USB_Received_Count = USBD_GetRxCount( pdev,epnum );
USBD_LL_PrepareReceive(pdev,CUSTOM_HID_EPOUT_ADDR,USB_Recive_Buffer, sizeof( USB_Recive_Buffer ));
return USBD_OK;
}
(3)在main.c中包含头文件#include “usbd_customhid.h”,while循环这样写:
while (1)
{
if (USB_Received_Count>0)
{
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, USB_Recive_Buffer,USB_Received_Count );
HAL_Delay(500);
USB_Received_Count = 0;
}
}
重新编译工程就可以实现数据的双向传输了
注意:即使是同样的板子,按着别人的文档操作也还是可能出现各种问题,这时就要具体情况具体分析,软件开发本来就是各种坑,但是在填坑的过程中,我们也能获得成就感,此处共勉。