项目概述
1.1 实现功能
本项目基于 NXP FRDM-MCXA156 开发板,实现了一个标准的 USB HID 游戏手柄设备,主要功能包括:
- 16 个数字按钮: 通过 4x4 矩阵键盘实现 14 个按钮 + 2 个摇杆按键
- 双摇杆输入: 左右两个模拟摇杆,各提供 X/Y 轴数据
- USB HID 协议: 标准 HID Gamepad 设备,即插即用,无需驱动
- 实时响应: 10ms 扫描间隔,低延迟输入
1.2 技术特点

RT-Thread使用情况概述
2.1 内核配置
#define RT_THREAD_PRIORITY_MAX 32 // 32 级优先级
#define RT_TICK_PER_SECOND 1000 // 1ms 系统节拍
#define RT_USING_TIMER_SOFT // 软件定时器
#define RT_USING_SEMAPHORE // 信号量
#define RT_USING_MUTEX // 互斥锁
#define RT_USING_MAILBOX // 邮箱
2.2 使用的组件

2.3 线程设计

2.4 自动初始化
项目使用 RT-Thread 自动初始化机制:
INIT_BOARD_EXPORT(rt_hw_adc_init); // ADC 驱动初始化
INIT_DEVICE_EXPORT(key_init); // 矩阵键盘初始化
INIT_DEVICE_EXPORT(joystick_init); // 摇杆初始化
INIT_COMPONENT_EXPORT(cherryusb_init); // USB 初始化
INIT_APP_EXPORT(gamepad_app_start); // 应用层启动
硬件框架
3.1 系统框图
┌─────────────────────────────────────────────────────────────┐
│ FRDM-MCXA156 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 4x4 矩阵 │ │ 双摇杆模块 │ │ USB Device │ │
│ │ 键盘 │ │ (带按键) │ │ (Full Speed) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ GPIO P2/P3 ADC0 CH0/1/8/13 USB0 │
│ │ │ │ │
│ ┌──────┴────────────────┴─────────────────────┴──────────┐│
│ │ MCXA156 MCU ││
│ │ (Cortex-M33 @ 96MHz) ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

3.2 引脚分配
3.2.1 矩阵键盘 (4x4)

3.2.2 摇杆 ADC

3.2.3 摇杆按键

软件框架说明
4.1 软件框架
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ gamepad_app.c ││
│ │ (整合输入设备,映射到 USB HID 报告) ││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ 功能层 (Function) │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
│ │ key_app.c │ │ joystick_app.c│ │ usb_app.c │ │
│ │ (矩阵键盘) │ │ (双摇杆) │ │ (USB HID) │ │
│ └───────────────┘ └───────────────┘ └─────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 驱动层 (Driver) │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
│ │ drv_pin.c │ │ drv_adc.c │ │ CherryUSB │ │
│ │ (GPIO) │ │ (ADC) │ │ (USB Stack) │ │
│ └───────────────┘ └───────────────┘ └─────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ RT-Thread 内核 │
│ (线程调度、IPC、设备框架、自动初始化) │
├─────────────────────────────────────────────────────────────┤
│ 硬件抽象层 (HAL) │
│ NXP MCX SDK / CMSIS │
└─────────────────────────────────────────────────────────────┘
4.2 数据流
矩阵键盘 ──► key_read() ──────────────────────────────────┐
│
左摇杆 ADC ──► joystick_left_read() ──► apply_deadzone() ──┤
├──► gamepad_thread
右摇杆 ADC ──► joystick_right_read() ──► apply_deadzone() ──┤ │
│ ▼
摇杆按键 ──► rt_pin_read() ────────────────────────────────┘ scale_axis()
│
▼
USB HID Report
│
▼
hid_gamepad_send_report()
│
▼
USB Host(PC)
严格遵守了 感知 --> 认知 --> 控制 系统设计模式。
软件模块说明
5.1 key_app 模块(矩阵键盘)
文件: applications/key_app.c, applications/key_app.h
功能: 4x4 矩阵键盘扫描
核心函数:
rt_uint8_t key_read(void); // 返回 0-15 表示按键索引,0xFF 表示无按键
扫描原理:
- 逐列输出低电平
- 读取所有行引脚状态
- 检测到低电平表示该交叉点按键被按下
5.2 joystick_app 模块(摇杆)
文件: applications/joystick_app.c, applications/joystick_app.h
功能: 双摇杆 ADC 读取与按键检测
数据结构:
typedef struct {
int16_t x; // X轴: -32768 ~ 32767
int16_t y; // Y轴: -32768 ~ 32767
bool btn; // 按键: true=按下
} joystick_data_t;
核心函数:
rt_err_t joystick_left_read(joystick_data_t *data);
rt_err_t joystick_right_read(joystick_data_t *data);
5.3 usb_app 模块(USB HID)
文件: applications/usb_app.c, applications/usb_app.h
功能: USB HID 游戏手柄设备实现
HID 报告结构 (9 字节):
typedef struct __attribute__((packed)) {
uint16_t buttons; // 16 个按钮
int8_t left_x; // 左摇杆 X (-127 ~ 127)
int8_t left_y; // 左摇杆 Y
int8_t right_x; // 右摇杆 X
int8_t right_y; // 右摇杆 Y
uint8_t left_trigger; // 左扳机 (0-255)
uint8_t right_trigger; // 右扳机 (0-255)
uint8_t hat; // 方向键 (0-8)
} usb_gamepad_report_t;
USB 描述符配置:
- VID: 0x045E (Microsoft)
- PID: 0x02FF (Generic Gamepad)
- 端点: 0x81 (IN), 中断传输
- 轮询间隔: 1ms
5.4 gamepad_app 模块(应用层)
文件: applications/gamepad_app.c, applications/gamepad_app.h
功能: 整合所有输入设备,映射到 USB HID 报告
核心特性:
- 死区处理: 消除摇杆中心位置的抖动
- 变化检测: 只有状态变化时才发送报告
- 发送重试: USB 忙碌时保留报告,下次重试
按键映射:

5.5 drv_adc 模块(ADC 驱动)
文件: Libraries/drivers/drv_adc.c
功能: LPADC 驱动,支持多通道 ADC 读取
关键修改:
- 修复了多通道初始化覆盖问题
- 添加了超时保护,防止系统死锁
- 优化了命令槽分配(4 个通道使用 4 个独立命令槽)
演示效果
6.1 启动日志
KEY OK
joystick: init OK
[USB] Initializing HID Gamepad...
[USB] HID Gamepad initialized successfully
[USB] VID:0x045E PID:0x02FF
[GAMEPAD] Started (interval: 10ms)
System Start
[GAMEPAD] Thread started
[USB] Device Configured - Gamepad Ready!
6.2 Windows 测试
- 设备连接后,在”设备管理器”中显示为 “USB Gamepad HID”
- 使用 joy.cpl(游戏控制器)可测试所有按钮和摇杆

- 使用 gamepad-tester.com 在线平台课测试所有按钮和摇杆


6.3 功能演示




代码地址
Git 仓库: https://github.com/Rolmoland/Project_GamepadMi
主要文件:
applications/
├── main.c # 主入口
├── gamepad_app.c/h # 游戏手柄应用层
├── key_app.c/h # 矩阵键盘模块
├── joystick_app.c/h # 摇杆模块
└── usb_app.c/h # USB HID 模块
board/
├── MCUX_Config/board/pin_mux.c # 引脚配置
└── ports/cherryusb/ # CherryUSB 适配
Libraries/drivers/
└── drv_adc.c # ADC 驱动(已修改)
总结
本项目成功实现了基于 RT-Thread 的 USB HID 游戏手柄,具有以下特点:
- 模块化设计: 硬件层、功能层、应用层分离,易于维护
- 实时性好: 基于 RT-Thread 实时内核,10ms 扫描周期
- 兼容性强: 标准 HID 协议,Windows/Linux/macOS 免驱
- 可扩展: 可方便添加震动反馈、LED 指示等功能
这个项目完整展示了如何利用 RT-Thread 的设备驱动框架和 CherryUSB 协议栈,在 NXP MCXA156 这样的 Cortex-M33 平台上快速构建一个功能完善的 USB HID 外设。其清晰的架构和代码实现,也为其他嵌入式开发者提供了一个很好的参考案例。如果你对更多嵌入式系统开发技巧感兴趣,欢迎到 云栈社区 交流探讨。