细说STM32单片机USBD_Custom_HID项目创建及编程方法
无论接收到还是发送出去的,都有两种格式,一种ASCII字符,一种ASCII 16进制值。本例,作者通过创建一个USBD_Custom_HID的键盘项目,并提供一套软件DEMO,向读者介绍此类项目的开发经验、编程入口。接收区,1帧,64字节数据,数据内容是程序赋值的,帧头、1、2、...、63,共64个字节。一共发了2次数据,发送的是字符,ASCII字符,64字节,1个字符占一个字节,空格也占一个字
目录
本例,作者通过创建一个USBD_Custom_HID的键盘项目,并提供一套软件DEMO,向读者介绍此类项目的开发经验、编程入口。
项目继续使用旺宝红龙开发板STM32F407ZGT7 KIT V1.0。本项目使用的原理图部分如下:

一、项目目的
- 实现一个USBD_Custom_HID项目;
- 编写USBD descriptors,如何编写USBD descriptor将由作者的其他文章介绍;
- 开发板的USBD接口连接到电脑后,自动实现HID驱动;
- 使用USB分析软件查找到该USBD HID,校验设备参数;
- 验证USBD HID的收发;
- 使用USART验证收发;
二、CubeIDE项目配置
使用STM32CubeIDE,Version: 1.19.0。
1、RCC
HSE选择外部晶振,USB时钟=48MHz。

2、SYS
DEBUG选择serial wire.
3、USART6
设置PG9、PG14为USART6,参数默认。
4、USB_OTG_FS
Mode选择Device Only,默认MCU管脚PA11、PA12,参数默认。
5、USB_DEVICE
Class For FS IP选择为:Custom HID。其它参数设置如下图:


6、NVIC
Time Base的优先级修改为0,其它默认。
三、软件设计
设置完毕后,通过STM32CubeIDE自动生成软件框架。
1、main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_customhid.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t send_buf[64] = {0};
uint8_t i;
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USB_DEVICE_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
/**
* This is the DEMO sent by the HID device.
* Write whatever you want to send.
*
**/
for(i=0;i<64;i++)
{
send_buf[i] = i;
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, send_buf, 64);
// send_buf[0]++;
// HAL_Delay(2000);
}
/* USER CODE END 3 */
}
// 省略以下默认生成的代码
/* USER CODE BEGIN 4 */
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 4 */
// 省略以下默认生成的代码
USER CODE BEGIN 3沙箱里的代码的使用方法:
- 当需要在电脑端的USB分析仪软件连续显示USBD_HID设备发送的数据时,启用此段代码。也就是测试USBD_HID发送,同时注释掉usbd_custom_hid_if.c(这个函数是APP应用接口函数)里的CUSTOM_HID_OutEvent_FS()里的私有代码;
- 当需要在电脑端的USB分析仪软件发送数据,然后USBD_HID设备接收并转发送该数据时,注释此段代码。也就是测试USBD_HID接收和发送,同时启用usbd_custom_hid_if.c里的CUSTOM_HID_OutEvent_FS()里的私有代码;
2、usbd_custom_hid_if.c
/**
******************************************************************************
* @file : usbd_custom_hid_if.c
* @version : v1.0_Cube
* @brief : USB Device Custom HID interface file.
******************************************************************************
/* Includes ------------------------------------------------------------------*/
#include "usbd_custom_hid_if.h"
/* USER CODE BEGIN INCLUDE */
#include <stdio.h>
#include "usart.h"
/* USER CODE END INCLUDE */
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
void Test_Report_buf_Print(USBD_CUSTOM_HID_HandleTypeDef *hhid);
/* USER CODE END PV */
/** @defgroup USBD_CUSTOM_HID_Private_Variables USBD_CUSTOM_HID_Private_Variables
* @brief Private variables.
* @{
*/
/** 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 */
/**This Desc description must be modified manually
* and consistent with the parameters of the CubeMX settings page.
* */
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 */
};
/** @defgroup USBD_CUSTOM_HID_Exported_Variables USBD_CUSTOM_HID_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes USBD_CUSTOM_HID_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
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);
/**
* @}
*/
USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_FS =
{
CUSTOM_HID_ReportDesc_FS,
CUSTOM_HID_Init_FS,
CUSTOM_HID_DeInit_FS,
CUSTOM_HID_OutEvent_FS
};
//省略以下自动生成的默认代码
/**
* @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 */
/**
* Start next USB packet transfer once data processing is completed.
*
* This function is called in the USB Custom HID device of STM32,
* and is used to handle events after USB receives a packet of data.
* */
UNUSED(event_idx);
UNUSED(state);
USBD_CUSTOM_HID_HandleTypeDef *hhid = hUsbDeviceFS.pClassData;
if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS) != (uint8_t)USBD_OK)
{
return -1;
}
else{
printf("Received DATA is ");
Test_Report_buf_Print(hhid); //test
}
/**
* @brief pClassData points to the data interface of USB Device Class.
* Further,
* hUsbDeviceFS.pClassData is the instantiation of hhid.
*/
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, hhid->Report_buf,64);
printf("Transmitted DATA is ");
Test_Report_buf_Print(hhid); //test
return (USBD_OK);
/* USER CODE END 6 */
}
/* USER CODE BEGIN 7 */
/**
* @brief Send the report to the Host
* @param report: The report to be sent
* @param len: The report length
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
/*
static int8_t USBD_CUSTOM_HID_SendReport_FS(uint8_t *report, uint16_t len)
{
return USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, report, len);
}
*/
/* USER CODE END 7 */
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void Test_Report_buf_Print(USBD_CUSTOM_HID_HandleTypeDef *hhid)
{
printf("Report_buf[63]:\r\n");
for(int i=0;i<USBD_CUSTOMHID_OUTREPORT_BUF_SIZE;i++){
printf("%d ",hhid->Report_buf[i]);
}
printf("\r\n");
for(int i=0;i<USBD_CUSTOMHID_OUTREPORT_BUF_SIZE;i++){
printf("%c",hhid->Report_buf[i]);
}
printf("\r\n");
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
该段代码中的Usb HID report descriptor是需要设计者设计的,具体的设计方法可以参考本文作者的其他文章。
四、运行并测试
编译后下载到开发板上。注意,下载的时候关闭USB分析仪软件,否则USB分析仪软件因为固件更新而连接不上导致卡死。
有很多USB分析仪软件,本文使用单片机多功能调试助手,PortHelper.exe.
1、查找USBD_HID设备

查找到STM32 Custom HID设备,就是本项目生成的设备,电脑端正常自动驱动。截图中的PID、VID、PVN都是CubeMX设置的,其含义为:

2、测试USBD_HID设备发送
按照上面文字里的规定,生成和下载代码。

接收区,1帧,64字节数据,数据内容是程序赋值的,帧头、1、2、...、63,共64个字节。每相邻两帧间隔2ms。
开启监视后的效果,该结果可以另存为CSV文件。

3、测试USBD_HID设备接收、发送
按照上面文字里的规定,生成和下载代码。

一共发了2次数据,发送的是字符,ASCII字符,64字节,1个字符占一个字节,空格也占一个字节。多余的字节被忽略。

在串口助手上,共收到4组数据,每组里包括接收到的和发送出去的。无论接收到还是发送出去的,都有两种格式,一种ASCII字符,一种ASCII 16进制值。

USB分析仪上,也接收到了2次数值,只能显示16进制数值,不能显示字符。
更多推荐



所有评论(0)