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

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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版