STM32H5 USBX 裸机实现 HID 双向通信:OUT 端点添加完整指南
作者:意法半导体
查看完整版应用笔记:经验分享 | LAT1658 STM32H5基于USBx裸机添加OUT端点实现HID类双向通信
文章概述
在基于 STM32H5 + USBX 开发自定义 HID 设备时,默认例程仅支持 IN 端点(MCU → PC)发送 ,当用户尝试使用 EP OUT1 实现 PC → MCU 数据接收时会出现 STALL 报错。本文基于官方 LAT1658 应用笔记,完整梳理如何在裸机环境下为 STM32H5 USBx 添加 OUT 端点、开启 HID 双向通信 ,提供可直接复现的配置步骤、宏定义、描述符修改与收发代码,解决实际开发中最常见的 USB HID 接收异常问题。
一、问题背景:默认 HID 例程不支持 OUT 端点
- 现象
- 基于
Ux_Device_HID_Standalone 例程运行正常
- MCU 可通过IN 端点 上传数据到上位机
- 上位机通过OUT 端点 发数据 → 设备返回 STALL
- 仅使用 EP0(控制端点)收发不报错
- 根因
- 标准 USB HID 设备默认只有 IN 端点
- USBX 协议栈默认未使能 HID Interrupt OUT 双向传输
- 必须手动开启宏、配置端点、修改报告描述符并实现接收回调
二、适用平台与环境
- MCU :STM32H5 系列(以 NUCLEO-H563ZI 为例)
- 框架 :STM32CubeMX + USBX 设备库
- 模式 :裸机(无 RTOS)
- 功能 :Custom HID + 双向中断传输(IN + OUT)
- 端点 :EP1 IN + EP1 OUT
三、完整实现步骤(可直接照做)
步骤 1:复制并新建工程
- 复制官方例程:
Projects\NUCLEO-H563ZI\Applications\USBX\Ux_Device_HID_Standalone
- 重命名为:
Ux_Device_HID_Test
步骤 2:STM32CubeMX 关键配置(必须正确)
- USBX Device Class
- 取消:MOUSE / KEYBOARD
- 使能:CUSTOM(自定义 HID)
- 必须开启的选项
plaintext
UX_DEVICE_CLASS_HID_INTERRUPTOUT_SUPPORT = Enabled
- 端点配置建议
plaintext
USBD_HID_CUSTOM_ENDPOINT_OUT_ADDRESS = 0x01
USBD_HID_CUSTOM_ENDPOINT_OUT_FS_MPS = 64
USBD_HID_CUSTOM_ENDPOINT_IN_FS_MPS = 64
步骤 3:开启 USBX HID OUT 支持宏定义
在相关头文件中添加 / 确认以下宏:
c
运行
/* 使能HID双向端点 */
#define UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT
#define UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
/* 自定义接收错误码 */
#define UX_DEVICE_CLASS_HID_RECEIVER_ERROR (UX_STATE_STEP + 5)
步骤 4:添加 / 修正 HID 报告描述符与设备描述符
确保报告描述符支持双向 Feature/Output 报告 ,并正确配置:
- 双向传输能力
- 数据长度(与端点 MPS 匹配)
- 双向报告 ID 区分
步骤 5:实现 HID 发送任务(IN 端点)
在 USBX_DEVICE_HID_CUSTOM_Task() 中实现主动上报:
c
运行
VOID USBX_DEVICE_HID_CUSTOM_Task(VOID)
{
static ULONG tick = 0;
/* 定时发送 */
if (HAL_GetTick() - tick >= 200)
{
tick = HAL_GetTick();
/* 填充上报数据 */
UINT status = ux_device_class_hid_event_set(
hid_Custom,
p_hid_event,
report_id,
report_length
);
}
}
步骤 6:实现 HID 接收函数(OUT 端点)
实现上位机 → 单片机数据接收:
c
运行
UINT Custom_HID_Receive(VOID)
{
UCHAR receive_buf[64];
ULONG actual_length;
/* 读取OUT端点数据 */
return ux_device_class_hid_receive(
hid_Custom,
receive_buf,
USBD_HID_CUSTOM_EPOUT_FS_MPS,
&actual_length
);
}
接收数据存入:HID_Custom_RecvBuf
四、最终实现效果
-
MCU → PC(IN 端点)
定时上报 64Byte 数据,稳定无丢包
-
PC → MCU(OUT 端点)
上位机任意发送数据,MCU 正常接收,不再 STALL
-
满足:
- 自定义 HID 设备
- 中断双向传输
- 裸机运行
- 兼容 STM32H5 USBx
五、常见错误与避坑
-
OUT 端点配置后仍 STALL
→ 未开启 UX_DEVICE_CLASS_HID_INTERRUPTOUT_SUPPORT
-
接收长度不匹配
→ OUT 端点 MPS 必须与报告长度一致
-
工程编译报错
→ 缺少头文件、宏重复定义、事件队列长度不足
-
只能发不能收
→ 未实现 ux_device_class_hid_receive() 接收入口
六、适合人群
- STM32H5/G0/G4 系列 USB 开发工程师
- 需要实现 USB HID 双向通信的固件开发者
- 遇到 OUT 端点 STALL 问题的调试人员
- 裸机 USBX 协议栈使用者
文章总结
STM32H5 使用 USBX 实现 Custom HID 双向通信 的核心,是手动开启 INTERRUPT OUT 支持 + 正确配置 OUT 端点 + 实现接收回调 。
按照本文步骤操作,可快速解决官方默认例程 “只能发不能收” 的问题,实现稳定可靠的 USB HID 双向数据传输,大幅提升开发效率。 |