STM32F103自定义键盘修改HID报告长度后按键失效求助
我正在使用STM32F103制作自定义键盘,最初采用标准8字节HID报告时运行正常,对应的报告描述符如下:
0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) //Modifiers 0x05, 0x07, // Usage Page (Key Codes) 0x19, 0xe0, // Usage Minimum (224) 0x29, 0xe7, // Usage Maximum (231) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x81, 0x02, // Input (Data, Variable, Absolute) //Reserveds 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x01, // Input (Constant) reserved byte(1) //Regular Keypads 0x95, 0x06, // Report Count (normally 6) 0x75, 0x08, // Report Size (8) 0x26, 0xff, 0x00, 0x05, 0x07, // Usage Page (Key codes) 0x19, 0x00, // Usage Minimum (0) 0x29, 0xbc, // Usage Maximum (188) 0x81, 0x00, // Input (Data, Array) Key array(6 bytes) 0xC0 // End Collection (Application)
为支持更多同时按键,我将报告描述符中0x95, 0x06, // Report Count (normally 6)修改为0x95, 0x30, // Report Count (48),并对应修改HID报告结构体:
struct HIDreport { int8_t mod; int8_t reserv; int8_t key[lenth]; }; struct HIDreport report;
但修改后所有按键均无法工作,请问我遗漏了什么?
我来帮你梳理几个最可能的遗漏点,这些都是自定义HID键盘时常见的坑:
报告长度与USB端点配置不匹配
原来的标准报告总长度是1(mod) + 1(reserved) + 6(keys) = 8字节。修改后,报告计数改成了0x30(也就是48),所以新的报告总长度应该是1+1+48=50字节。你需要同步修改两个地方:- 结构体里的
lenth必须定义为48,否则数组长度不对,内存访问会出问题; - 检查STM32的USB端点配置,HID端点的
wMaxPacketSize要设置成能容纳50字节的值(比如64,因为USB全速端点的最大包长就是64)。如果还是用原来的8字节包长,数据根本无法正确传输到主机。
- 结构体里的
结构体内存对齐问题
STM32的编译器默认可能会对结构体做内存对齐优化,导致你的HIDreport结构体实际大小大于预期的50字节。这会让发送的报告数据错位,主机无法正确解析。解决方法是给结构体加上强制1字节对齐的属性:struct HIDreport { int8_t mod; int8_t reserv; int8_t key[48]; } __attribute__((packed));USB设备枚举问题
修改报告描述符后,主机需要重新识别设备的HID配置。如果你只是重新烧录程序而没有插拔USB线,主机可能还在使用旧的报告缓存,导致按键数据无法被正确解析。修改后一定要重新插拔设备,让主机重新枚举并加载新的HID描述符。报告填充逻辑的同步修改
原来的代码里,你可能只填充6个按键的位置,现在要支持48个,需要确保填充按键数据的逻辑也同步更新——比如释放按键时要把对应的位置清零,按下时要把按键码正确写入对应的数组索引。不过这个问题一般只会导致部分按键失效,而非全部,但也需要检查。
内容的提问来源于stack exchange,提问作者user174618

