本帖最后由 小恩GG 于 2025-12-3 18:24 编辑
基于 MCXN947 的 USB HID 鼠标多按键功能实现与分析
一、主要内容 USB HID(Human Interface Device)协议是嵌入式开发中常见的接口标准,广泛应用于键盘、鼠标等输入设备。本文将基于 MCXN947 SDK 官方USB HID Mouse 示例,扩展实现多按键控制鼠标上下左右移动及左键点击,并通过 USB 逻辑分析仪进行抓包验证,帮助开发者了解 HID 协议及 USB 枚举过程。 二、开发环境 硬件 - FRDM-MCXN947开发板
- USB逻辑分析仪(如 Teledyne)
软件 - MCUXpressoIDE
- FRDM-MCXN947 SDK
三、USB HID Mouse 基础知识 1. HID(Human Interface Device,人机接口设备)协议是 USB 标准中的一种设备类协议,主要用于描述和传输人机交互设备的数据,如键盘、鼠标、游戏手柄、触摸屏等。
HID 协议通过 报告描述符(Report Descriptor) 定义数据结构,主机根据该描述符解析输入、输出的报告,实现设备与主机之间的数据交互。
核心概念:
- 报告描述符(Report Descriptor):用于描述设备数据格式和功能,定义输入、输出报告的结构。
- 报告(Report):设备与主机之间传输的数据单元,
2. HID Mouse 报告格式 标准鼠标输入报告结构如下,共四个字节
四、USB 枚举过程分析 1. 获取设备描述符 主机发送 GET_DESCRIPTOR 请求,结构如下:
USB逻辑分析仪抓取的获取设备描述符包:
从机返回设备描述符:
USB逻辑分析仪可解析描述符:
2. 设置地址 SET_ADDRESS 当设备复位后,都使用默认地址0。主机从地址为0的设备获取设备描述符,一旦收到设备描述符之后,主机就会发送设置地址的请求SET_ADDRESS。地址值存放在wValue中。 USB逻辑分析仪抓取设置地址包:
3. 设置配置描述符 SET_CONFIGURATION 主机发送SET_CONFIGURATION 命令:
配置描述符包含 Configuration、Interface、HID、Endpoint 描述符,必须按顺序排列。在文件usb_device_descriptor.c 文件的数组g_UsbDeviceConfigurationDescriptor[]定义。
五、功能扩展与代码实现 在官方 HID Mouse 示例中,鼠标移动是通过定时器控制的矩形轨迹。为了实现更灵活的控制,我们设计并实现了多按键控制鼠标上下左右移动及左键点击 的功能。 1. 需求分析 - 增加 4 个方向移动键(上、下、左、右)和一个左键点击键。
- 按键触发鼠标移动,替代默认的矩形轨迹控制方式。
2. 设计思路 - GPIO 初始化与中断处理:通过 GPIO 中断检测按键状态。
- HID 报告更新逻辑:根据按键状态修改 HID 报告并发送给主机。
3. 按键映射 根据FRDM-MCXN947 开发板子现有资源,利用如下五个引脚下降沿模拟鼠标按键。
4. GPIO 中断处理
void GPIO00_IRQHandler(void) { key = 1; // 左键点击 GPIO_GpioClearInterruptFlags(BOARD_INITPINS_SW2_GPIO,1U << 23); }
void GPIO40_IRQHandler(void) { if(GPIO_PinGetInterruptFlag(BOARD_INITPINS_KEY_RIGHT_GPIO,BOARD_INITPINS_KEY_RIGHT_PIN)) { key = 2; // 右移 } elseif(GPIO_PinGetInterruptFlag(BOARD_INITPINS_KEY_UP_GPIO,BOARD_INITPINS_KEY_UP_PIN)) { key = 3; // 上移 } elseif(GPIO_PinGetInterruptFlag(BOARD_INITPINS_KEY_DOWN_GPIO,BOARD_INITPINS_KEY_DOWN_PIN)) { key = 4; // 下移 } else if(GPIO_PinGetInterruptFlag(BOARD_INITPINS_KEY_LEFT_GPIO,BOARD_INITPINS_KEY_LEFT_PIN)) { key = 5; // 左移 } else { key = 0; // 无操作 } GPIO_GpioClearInterruptFlags(BOARD_INITPINS_KEY_RIGHT_GPIO,0xffffffff); }
5. 修改HID发送报告 static usb_status_t USB_DeviceHidMouseAction(void) { switch(key) { case 1: // 左键点击 g_UsbDeviceHidMouse.buffer[0] = 0x01; g_UsbDeviceHidMouse.buffer[1] = 0; g_UsbDeviceHidMouse.buffer[2] = 0; break;
case 2: // 右移 g_UsbDeviceHidMouse.buffer[0] = 0; g_UsbDeviceHidMouse.buffer[1] = 20; g_UsbDeviceHidMouse.buffer[2] = 0; break;
case 3: // 上移 g_UsbDeviceHidMouse.buffer[0] = 0; g_UsbDeviceHidMouse.buffer[1] = 0; g_UsbDeviceHidMouse.buffer[2] = 20; break;
case 4: // 下移 g_UsbDeviceHidMouse.buffer[0] = 0; g_UsbDeviceHidMouse.buffer[1] = 0; g_UsbDeviceHidMouse.buffer[2] =(uint8_t)(-20); break;
case 5: // 左移 g_UsbDeviceHidMouse.buffer[0] = 0; g_UsbDeviceHidMouse.buffer[1] =(uint8_t)(-20); g_UsbDeviceHidMouse.buffer[2] = 0; break;
default: // 无操作 g_UsbDeviceHidMouse.buffer[0] = 0; g_UsbDeviceHidMouse.buffer[1] = 0; g_UsbDeviceHidMouse.buffer[2] = 0; break; }
key = 0; // 重置按键状态
returnUSB_DeviceHidSend(g_UsbDeviceHidMouse.hidHandle, USB_HID_MOUSE_ENDPOINT_IN, g_UsbDeviceHidMouse.buffer, USB_HID_MOUSE_REPORT_LENGTH); }
六、实现效果与USB 抓包验证 - 按下对应按键,鼠标在屏幕上实现上下左右移动。
- SW2 按键触发左键点击。
通过 USB 逻辑分析仪验证 HID 报告是否正确发送,确保按键触发对应的鼠标动作。
1. 点击按键P4_5,根据定义,鼠标右移: 抓取USB逻辑分析包:
可见 X 值为 0x14,Y 值为 0,表示向右移动 0x14。
2. 按一下开发板SW2,根据定义,模拟点击鼠标左键。 抓取USB逻辑分析包:
七、总结 本文详细介绍了: - USB HID mouse 协议枚举过程
- 多按键控制鼠标移动的实现
- USB抓包验证方法
该案例适合 USB 初学者参考,帮助快速理解HID 鼠标协议和嵌入式 USB 开发。
|