提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
学习STM32中的USB通信的时候,面对USB中数据帧结构、设备描述符/配置描述符/接口描述符/端点描述符等等的概念,入门即放弃。因此抛开所有,先让开发板的小灯闪起来,一点一点调试、一点一点熟悉、一点一点深入,一点一点理解。LET’S DO。先来玩HID
一、开发板USB硬件
翻到了一块吃灰的STM32F407ZGT6的板子和SCH原理图。
![]() | usb Low-Speed -->1.5Mbps(192kB/s) usb Full-Speed -->12Mbps(1.5MB/s) |
![]() | 支持Full-Speed |
二、STM32CubeMX 设置
1.设置小灯灯和串口
![]() | ![]() |
---|
DMA 串口传输
2.开启USB
![]() | ![]() |
---|
![](https://img-blog.csdnimg.cn/1855f1d2f5a846dba835b569bb4e9037.png)
![](https://img-blog.csdnimg.cn/13e93a23e8c14c1194845f99f3518240.png)
其余参数保持默认
3.时钟设置
![](https://img-blog.csdnimg.cn/fda66c87595345acb127e2baa0cd828c.png)
导出工程,用KEIL 打开
三、KEIL中的代码
1.设置串口,测试
在main.c 中添加
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define debug(...) {\
int len=0;\
len=snprintf(debug_buf , 128, __VA_ARGS__);\
if(len>0)\
{\
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)debug_buf, len );\
}\
}
/* USER CODE END PD */
/* USER CODE BEGIN PV */
char debug_buf[128];
/* USER CODE END PV */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
debug("Enter main while loop!\r\n");
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_Delay(500);
}
/* USER CODE END 3 */
记得选中,不然可能发现串口无信息输出。
2.设置USB,测试
报文描述符 usbd_custom_hid_if.c
从别人那里照抄
/** 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) /
/* 6 */
// The Input report
0x09,0x03, // USAGE ID - Vendor defined
0x15,0x00, // LOGICAL_MINIMUM (0)
0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255)
0x75,0x08, // REPORT_SIZE (8)
0x95,CUSTOM_HID_EPIN_SIZE, //0x95,0x16, REPORT_COUNT (20)
0x81,0x02, // INPUT (Data,Var,Abs)
//19
// The Output report
0x09,0x04, // USAGE ID - Vendor defined
0x15,0x00, // LOGICAL_MINIMUM (0)
0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255)
0x75,0x08, // REPORT_SIZE (8)
0x95,CUSTOM_HID_EPOUT_SIZE, //0x95,0x16, REPORT_COUNT (20)
0x91,0x02, // OUTPUT (Data,Var,Abs)
//32
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
发送数据长度 报文长度 usbd_conf.h
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES 1U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/*---------- -----------*/
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 64U
/*---------- -----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 33U
/*---------- -----------*/
#define CUSTOM_HID_FS_BINTERVAL 0x1U
/****************************************/
收发数据长度 时间间隔 usbd_customhid.h
/** @defgroup USBD_CUSTOM_HID_Exported_Defines
* @{
*/
#ifndef CUSTOM_HID_EPIN_ADDR
#define CUSTOM_HID_EPIN_ADDR 0x81U
#endif /* CUSTOM_HID_EPIN_ADDR */
#ifndef CUSTOM_HID_EPIN_SIZE
#define CUSTOM_HID_EPIN_SIZE 0x40U
#endif /* CUSTOM_HID_EPIN_SIZE */
#ifndef CUSTOM_HID_EPOUT_ADDR
#define CUSTOM_HID_EPOUT_ADDR 0x01U
#endif /* CUSTOM_HID_EPOUT_ADDR */
#ifndef CUSTOM_HID_EPOUT_SIZE
#define CUSTOM_HID_EPOUT_SIZE 0x40U
#endif /* CUSTOM_HID_EPOUT_SIZE*/
#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 41U
#define USB_CUSTOM_HID_DESC_SIZ 9U
#ifndef CUSTOM_HID_HS_BINTERVAL
#define CUSTOM_HID_HS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_HS_BINTERVAL */
#ifndef CUSTOM_HID_FS_BINTERVAL
#define CUSTOM_HID_FS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_FS_BINTERVAL */
#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x02U
#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */
#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 163U
#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */
#define CUSTOM_HID_DESCRIPTOR_TYPE 0x21U
#define CUSTOM_HID_REPORT_DESC 0x22U
#define CUSTOM_HID_REQ_SET_PROTOCOL 0x0BU
#define CUSTOM_HID_REQ_GET_PROTOCOL 0x03U
#define CUSTOM_HID_REQ_SET_IDLE 0x0AU
#define CUSTOM_HID_REQ_GET_IDLE 0x02U
#define CUSTOM_HID_REQ_SET_REPORT 0x09U
#define CUSTOM_HID_REQ_GET_REPORT 0x01U
通信关键函数:
usb hid 数据发送函数:usbd_customhid.c 中
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
usb hid 数据接收回调函数:usbd_custom_hid_it.c中
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
拷贝代码
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
extern unsigned char USB_Recive_Buffer[64];
extern unsigned char USB_Received_Count;
/* USER CODE END PV */
...
/**
* @brief Manage the CUSTOM HID class events
* @param event_idx: Event index
* @param state: Event state
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
/* USER CODE BEGIN 6 */
// UNUSED(event_idx);
// UNUSED(state);
int i;
/*查看接收数据长度*/
USB_Received_Count = USBD_GetRxCount( &hUsbDeviceFS,CUSTOM_HID_EPOUT_ADDR ); //第一参数是USB句柄,第二个参数的是接收的末端地址;要获取发送的数据长度的话就把第二个参数改为发送末端地址即可
USBD_CUSTOM_HID_HandleTypeDef *hhid; //定义一个指向USBD_CUSTOM_HID_HandleTypeDef结构体的指针
hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;//得到USB接收数据的储存地址
for(i=0;i<USB_Received_Count;i++)
{
USB_Recive_Buffer[i]=hhid->Report_buf[i]; //把接收到的数据送到自定义的缓存区保存(Report_buf[i]为USB的接收缓存区)
}
/* Start next USB packet transfer once data processing is completed */
if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS) != (uint8_t)USBD_OK)
{
return -1;
}
return (USBD_OK);
/* USER CODE END 6 */
}
main.c
添加如下代码
extern USBD_HandleTypeDef hUsbDeviceFS; //外部声明USB的句柄
/* USER CODE END Includes */
...
/* USER CODE BEGIN PV */
unsigned char USB_Recive_Buffer[64] = {0}; //USB接收缓存
unsigned char USB_Received_Count = 0;//USB接收数据计数
/* USER CODE END PV */
...
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1000);
debug("Enter main while loop!\r\n");
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, USB_Recive_Buffer, 64);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_Delay(500);
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)USB_Recive_Buffer, 64);
debug("\r\n");
HAL_Delay(1000);
debug("USB_Received_Count=== %d\r\n",USB_Received_Count);
}
/* USER CODE END 3 */
四、测试
![](https://img-blog.csdnimg.cn/b07fa8c9fb0243ce8222c5609cfb8d4b.png)
总结
慢慢来,尖刺就是生梨。