你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32 usb hid设备能发数据给PC,但不能接收PC的数据!!!

[复制链接]
Xingpengkun 提问时间:2026-5-21 16:42 / 未解决

移植的stm32 hid设备 只能在while(1)中发送数据给PC后,PC的上位机bushound才能发送数据给下位机。如果hid设备不发数据给PC,则bushound发送数据时会报错“invalid command”, bushound看不到数据发下去。请问这个是什么原因导致的?

这个问题看几年前就有人提出来,但是一直没人解决。

解决问题的+微15996227589发红包。


报告描述符如下:

CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */
  0x06, 0xA0, 0xFF,
  0x09, 0xA5,
  0xA1, 0x01,
  0x09, 0xA6,

  // 输入报表
  0x09, 0xA7,
  0x15, 0x00,
  0x25, 0xFF,
  0x75, 0x08,
  0x95, 0x40,
  0x81, 0x02,

  // 输出报表
  0x09, 0xA9,
  0x15, 0x00,
  0x25, 0xFF,
  0x75, 0x08,
  0x95, 0x40,
  0x91, 0x02,

//    0xC0 、
  /* USER CODE END 0 */
  0xC0    /*    END_COLLECTION                  */
};

收藏 1 评论6 发布时间:2026-5-21 16:42

举报

6个回答
Xingpengkun 回答时间:2026-5-21 17:03:09

移植的stm32 hid设备 只能在while(1)中发送数据给PC后,PC的上位机bushound才能发送数据给下位机。如果hid设备不发数据给PC,则bushound发送数据时会报错“invalid command”, bushound看不到数据发下去。请问这个是什么原因导致的?

这个问题看几年前就有人提出来,但是一直没人解决。

解决问题的+微15996227589发红包。

报告描述符如下:

CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = {   / USER CODE BEGIN 0 /   0x06, 0xA0, 0xFF,    0x09, 0xA5,    0xA1, 0x01,    0x09, 0xA6, 

  // 输入报表   0x09, 0xA7,    0x15, 0x00,    0x25, 0xFF,    0x75, 0x08,    0x95, 0x40,    0x81, 0x02, 

  // 输出报表   0x09, 0xA9,    0x15, 0x00,    0x25, 0xFF,    0x75, 0x08,    0x95, 0x40,    0x91, 0x02, 

//    0xC0 、   / USER CODE END 0 /   0xC0    /    END_COLLECTION                  / };

Xingpengkun 回答时间:2026-5-21 17:03:58

移植的stm32 hid设备 只能在while(1)中发送数据给PC后,PC的上位机bushound才能发送数据给下位机。如果hid设备不发数据给PC,则bushound发送数据时会报错“invalid command”, bushound看不到数据发下去。请问这个是什么原因导致的?

这个问题看几年前就有人提出来,但是一直没人解决。

解决问题的+微15996227589发红包。

报告描述符如下:

CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = {   / USER CODE BEGIN 0 /   0x06, 0xA0, 0xFF,    0x09, 0xA5,    0xA1, 0x01,    0x09, 0xA6, 

  // 输入报表   0x09, 0xA7,    0x15, 0x00,    0x25, 0xFF,    0x75, 0x08,    0x95, 0x40,    0x81, 0x02, 

  // 输出报表   0x09, 0xA9,    0x15, 0x00,    0x25, 0xFF,    0x75, 0x08,    0x95, 0x40,    0x91, 0x02, 

//    0xC0 、   / USER CODE END 0 /   0xC0    /    END_COLLECTION                  / };

网络孤客 回答时间:2026-5-22 09:32:13

不懂,问Deepseek

这个问题很典型,根本原因在于HID设备的输出端点(OUT)没有预先准备好接收数据,而主动发送一次输入报告(IN)恰好触发了接收准备。

原理分析

  1. USB HID 的数据传输机制

    • 输入报告(设备→主机):通过中断IN端点,设备调用 USBD_HID_SendReport() 将数据放入缓冲区,端点从NAK变为就绪,主机才能取走数据。
    • 输出报告(主机→设备):可通过两种方式:
      • 中断OUT端点(如果有),设备需预先调用 USBD_HID_ReceivePacket() 设置接收缓冲区,端点才响应主机的OUT令牌。
      • 控制端点(SET_REPORT请求),设备需在 USBD_CUSTOM_HID_SetReport() 回调中处理。 从你的报告描述符看,只有输入/输出报表,没有指明中断OUT端点,因此主机大概率使用 控制传输(SET_REPORT) 下发数据。
  2. 为什么必须先发送数据才能收到

    • 多数STM32 USB HID例程中,初始化时并未调用 USBD_CUSTOM_HID_ReceivePacket(),此时输出路径(EP0或OUT端点)处于未就绪状态。主机发送SET_REPORT时,设备会返回STALL,导致上位机报错 invalid command
    • 当你主动调用 USBD_HID_SendReport() 发送一次输入报告后,可能在该函数内部在发送完成的回调函数(如 CUSTOM_HID_OutEvent)中自动调用了接收准备函数(具体取决于你的代码实现)。于是输出端点就绪,后续主机再发数据就能成功。

解决方案

在初始化完成后,主动调用一次接收准备函数,让设备始终能响应主机的输出报告。

方法一:调用 USBD_CUSTOM_HID_ReceivePacket(如果使用中断OUT端点)

// 在初始化或主循环开始处
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;
USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS, hhid->Report_buf, USBD_CUSTOM_HID_OUTREPORT_SIZE);

注意 Report_buf 需要提前定义,大小与报告描述符中的输出报表长度一致(此处为0x40)。

方法二:实现 USBD_CUSTOM_HID_SetReport 回调(适用于控制传输)

usbd_custom_hid_if.c 中实现:

static int8_t CUSTOM_HID_SetReport_ZSQ(uint8_t *report, uint16_t len, uint8_t reportId)
{
    // 将 report 中的数据复制到你的应用缓冲区
    memcpy(usb_rx_buffer, report, len);
    // 设置标志,通知主循环处理
    return (USBD_OK);
}

并将此函数注册到 USBD_CUSTOM_HID_ItfTypeDef 结构体的 SetReport 成员中。

如何验证

  • 使用USB分析仪抓包,观察枚举后主机发送SET_REPORT时设备是否回复STALL
  • 检查你的STM32工程中是否调用了 USBD_CUSTOM_HID_ReceivePacket。如果没有,加上即可解决。
  • 确保报告描述符中的输出报表长度与 USBD_CUSTOM_HID_ReceivePacket 中指定的长度一致(此处为64字节)。

补充说明

  • 即使没有中断OUT端点,HID主机仍可通过控制传输发送输出报告。设备只需正确实现 SetReport 回调,不需要主动发送任何输入报告。
  • 你遇到的“发一次才能收”的现象,说明当前代码中接收准备与发送动作耦合了,检查 USBD_HID_SendReport 被调用后是否顺带调用了接收函数。

按上述方法修改后,设备应该可以随时接收PC下发的数据,无需先发送。

opqASZ 回答时间:2026-5-22 09:43:37

网络孤客 发表于 2026-5-22 09:32
不懂,问Deepseek</p>
<p>

[md]可以加您一个联系方式嘛,一起讨论一下技术tabuxxwol这是v,有什么不明白一起探讨一下

xmshao 回答时间:2026-5-22 12:10:05

ST官方是有相关例程可以作为参考进行移植。

不过,例程里是基于2字节大小的数据进行处理的,看你好像用到64个数据。

这样的话,注意相应端点及report的数据缓冲大小要相应调整,即从2调整到64。

相关的数据处理函数按理也要调整。

网络孤客 回答时间:2026-5-23 07:52:21

opqASZ 发表于 2026-5-22 09:43
可以加您一个联系方式嘛,一起讨论一下技术tabuxxwol这是v,有什么不明白一起探讨一下
...

我只是个菜鸟,业余玩玩而已

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版