使用STM32CubeMX创建USB Custom HID工程

本文档详细介绍了如何使用STM32CubeMX配置STM32H7 MCU以实现USB CustomHID和MSC功能,包括选择MCU、配置系统参数和USB时钟,以及修改工程代码以支持数据的发送和接收。作者提供了一段CustomHID报告描述符的配置示例,并给出了主函数的修改建议,以便设备能接收并回传数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

由于项目需要,要实现USB组合设备(Custom HID + MSC)功能。
我的思路是先使用STM32CubeMX工具生成 Custom HID工程,再生成一个MSC的工程,两个功能独立调试OK之后,进行组合调试。本文为后续组合设备功能做铺垫。

实验步骤

1、打开STM32CubeMX工具,选择你的MCU型号

在这里插入图片描述
笔者这里使用的是STM32H7的MCU,你们选择自己的MCU型号即可(比如,F103C8T6,F407ZGT6等)

2、配置系统参数,USB参数等

在这里插入图片描述笔者的这颗MCU使用的是外部8M的晶振,主频倍频到了 550M,其他MCU根据实际情况配置主频即可,但是USB的时钟一定要设置为48M

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述调试模式选择SW 两线模式

在这里插入图片描述
堆栈空间尽量设置大一点
在这里插入图片描述
最后生成我们的工程即可。

3、修改工程代码并编译

初次编译我们的工程OK之后,开始我们的修改。
由于我的MCU的原因,作为设备时只支持高速模式(HS)而不是全速模式(FS)两者只是通讯速度上有差异,修改时不用特别在意。
首先,修改usbd_custom_hid_if.c文件中HID自定义报告描述符的数组内容如下

/** Usb custom HID report descriptor. */
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_HS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 1 */
  0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1) 表示一个报文标签之类的用途类页
  0x09, 0x01,                    // USAGE (Vendor Usage 1) 表示一个报告ID标志
  0xa1, 0x01,                    // COLLECTION (Application) 表示应用集合,要以下面最后的0xc0结束它

  0x09, 0x01,                    //   USAGE (Vendor Usage 1)功能的一个卷标志
  0x15, 0x00,                    //   LOGICAL_MINIMUM (0)  表示每个传输数据限定为0
  0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255) 表示每个传输数据的最大值限定为255
  0x95, 0x40,                    //   REPORT_COUNT (64)  每次发送的数据长度,这里是64位
  0x75, 0x08,                    //   REPORT_SIZE (8)   同下REPORT_SIZE
  0x81, 0x02,                    //   INPUT (Data,Var,Abs) 表示USB要输入数据到PC的功能

  0x09, 0x01,                    //   USAGE (Vendor Usage 1) 每个功能的一个卷标志
  0x15, 0x00,                    //   LOGICAL_MINIMUM (0)    表示每个传输数据限定为0
  0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)    表示每个传输数据的最大值限定为255
  0x95, 0x40,                    //   REPORT_COUNT (64) 每次接收的数据长度,这里是64位
  0x75, 0x08,                    //   REPORT_SIZE (8)        传输字段的宽度为8bit,表示每个传输的数据范围为0~ffff ffff
  0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) 表示USB设备要接收PC的数据的功能
  // 0xc0                           // END_COLLECTION  结束标志
  /* USER CODE END 1 */
   0xC0    /*     END_COLLECTION             */
};

为何要这样配置,是参考的一篇文章,我把链接贴出来,大家自行去查看
链接: https://www.cnblogs.com/xingboy/p/9913963.html

然后取消发送函数的注释,并添加到usbd_custom_hid_if.h中

int8_t USBD_CUSTOM_HID_SendReport_HS(uint8_t *report, uint16_t len)
{
  return USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS, report, len);
}

我的测试方法,PC给该设备发送数据,设备收到之后将信息返回给PC
修改接收函数

uint8_t receive_Flag = 0; //接收到数据标志位
uint8_t receive_buffer[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];//缓存区,一次缓存一帧,即最大64个字节

static int8_t CUSTOM_HID_OutEvent_HS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 10 */
  UNUSED(event_idx);
  UNUSED(state);

    /* Start next USB packet transfer once data processing is completed */
  if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceHS) != (uint8_t)USBD_OK)
  {
    return -1;
  }

  receive_Flag = 1;	//接收数据标志位 表示接收到一帧数据
  memcpy(&receive_buffer[0], hUsbDeviceHS.pClassData, USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);	//将接收到的数据存入自己定义的缓冲数组中

  return (USBD_OK);
  /* USER CODE END 10 */
}

注意:USB数据传输是多帧传输,一帧数据最大为64个字节

main函数如下

#include "usbd_custom_hid_if.h"

int main(void)
{
  MPU_Config();
  HAL_Init();
  SystemClock_Config();
  PeriphCommonClock_Config();
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();

  while (1)
  {
    extern uint8_t receive_Flag;
    extern uint8_t receive_buffer[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
    if (receive_Flag) {
      receive_Flag = 0;
      USBD_CUSTOM_HID_SendReport_HS(receive_buffer, USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);
    }
  }
}

下载验证

在这里插入图片描述
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值