不用写USB底层驱动有多爽?基于CherryUSB的USB HID鼠标极简实战

教育培训 2026-10-24 chq123 3292

本文将以NXP FRDM-MCXA366开发板为硬件平台,借助 RT-Thread 操作系统中的 CherryUSB 软件包,从零开始完成 USB HID 鼠标设备的模拟实验。实验最终效果是:将开发板通过 USB 连接到电脑后,电脑将其识别为一个 USB 鼠标,鼠标光标将在屏幕上做持续的圆周运动,充分验证 HID 设备枚举与数据上报的完整链路。

目录

01

硬件介绍

02

CherryUSB 与 USB HID 鼠标模拟

03

使用说明(开发环境搭建与配置)

04

功能演示

05

工程代码

06

心得体会

硬件介绍

FRDM-MCXA366 开发板概览

479f4c8e-ce95-11f1-9b19-92fbcf53809c.png

FRDM-MCXA366 是 NXP 面向 MCX A366 MCU 推出的紧凑型、可扩展开发板,专为快速原型开发而设计。其核心规格如下:

参数

说明

MCU

NXP MCXA366VLQ

内核

ARM Cortex-M33,最高主频 240 MHz

Flash

最高 1024 KB

SRAM

最高 256 KB(含 8 KB ECC)

USB

USB FS Type-C 接口(全速 USB)

调试器

板载 MCU-Link Lite,支持 CMSIS-DAP 与 JTAG/SWD

扩展接口

Arduino UNO 接口、FRDM Header、mikroBUS、Pmod、FlexIO/LCD、SmartDMA/Camera

MCX A 系列是 NXP 推出的高性能、低功耗微控制器系列,集成了 MAU(数学加速单元)与 SmartDMA,在性能与功耗之间取得了良好平衡。

USB 接口说明

FRDM-MCXA366 板载USB Type-C接口,可工作在USB Full-Speed (FS)模式下。本实践将 USB 工作于 Full-Speed Device 模式,开发板作为USB 从机(Device),连接到电脑(USB Host)。

USB 连接说明:

J15(MCU-Link USB):用于烧录固件与调试串口输出,连接电脑

J10(USB 外设接口Type-C):用于模拟 HID 鼠标,连接电脑另一个 USB 口

注意:需使用两根 USB Type-C 线,一根连调试口,一根连 USB Device 功能口。

CherryUSB 与 USB HID 鼠标模拟

CherryUSB 简介

CherryUSB 是一个开源的轻量级 USB 主从协议栈,凭借其精简的代码结构与优秀的移植性,已成为 RT-Thread 生态中广泛推荐使用的 USB 协议栈实现,官方将其作为软件包集成并在官方文档和示例中重点推荐。其主要特点包括:

支持 USB Device 与 USB Host 双模式

IP 以 port 形式组织,芯片适配复用方便

内置丰富的设备类模板:CDC ACM、HID(鼠标/键盘)、MSC、RNDIS 等

与 RT-Thread ENV 工具链深度集成,通过 menuconfig 一键配置

HID 鼠标设备原理

USB HID(Human Interface Device)是 USB 规范中定义的人机交互设备类,鼠标是其中最典型的应用之一。HID 鼠标通过中断传输(Interrupt Transfer)端点周期性向主机上报数据包,数据包格式如下:

字节

含义

Byte 0

按键状态(bit0=左键, bit1=右键, bit2=中键)

Byte 1

X 轴位移(有符号,-127 ~ +127)

Byte 2

Y 轴位移(有符号,-127 ~ +127)

Byte 3

滚轮位移(有符号,-127 ~ +127)

CherryUSB 内置了标准 HID 鼠标的报告描述符(Report Descriptor)和完整的数据上报模板,用户只需调用封装好的 API 即可。

MCXA366 的 USB IP 说明

对于 MCXA366 来说,其 USB 控制器 IP 属于 kinetis_mcx 系列,USB 寄存器基地址为 0x400A4000。CherryUSB 的 port 目录下已有对应的 IP 驱动实现,适配工作主要集中在 usb_dc_low_level_init() 函数中完成时钟、中断、引脚复用等底层初始化。

使用说明(开发环境搭建与配置)

前置准备

软件环境:

RT-Thread 源码(建议使用最新稳定版)

ENV 工具(用于 menuconfig 配置)

Keil MDK(AC6 编译器)或 GCC 工具链

串口终端工具(本文使用Tabby)

硬件准备:

FRDM-MCXA366 开发板 × 1

USB Type-C 数据线 × 2(一根用于调试,一根用于 USB HID)

获取 BSP

进入 RT-Thread 源码目录,找到 MCXA 系列 BSP:

cdbsp/nxp/mcx/mcxa/frdm-mcxa366

使用 ENV 配置 CherryUSB

在 BSP 目录下打开 ENV 工具,执行:

menuconfig

按如下路径进入 CherryUSB 配置:

RT-Thread Components → Device Drivers →UsingUSBwithCherryUSB

配置步骤:

① 选择 Enable usb device mode,回车进入:

② USB 速度选择 FS(全速):

Chooseusb speed: (FS) --->

③ USB Device IP 选择 kinetis_mcx:

Chooseusb device ip: (kinetis_mcx) --->

④ 使能 HID 设备并选择模板:

[*]Enable usb hid device USB device template(hid_mouse) --->

配置项如下图:

配置完成后保存退出,执行:

pkgs--update

4ac7dd68-ce95-11f1-9b19-92fbcf53809c.png

更新软件包。

编写初始化代码

开发板支持CherryUSB需要一些移植文件(主要是 usb_config.h 文件,CherryUSB 官方移植文档中对此有说明)。

我们将 frdm-mcxa156\board 下的 ports 目录粘贴到 frdm-mcxa366\board 下。

在frdm-mcxa366\board\ports\cherryusb\cherryusb.c 文件中,追加下面的鼠标测试代码:

#ifdefRT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSEexternvoidhid_mouse_init(uint8_tbusid,uintptr_treg_base);externvoidhid_mouse_test(uint8_tbusid);/* USB HID 鼠标初始化,在系统组件初始化阶段自动调用 */staticintrt_hw_mcxa366_cherryusb_hid_init(void){ /* 0x400A4000u 为 MCXA366 USB 控制器寄存器基地址 */ hid_mouse_init(0,0x400A4000u); return0;}INIT_COMPONENT_EXPORT(rt_hw_mcxa366_cherryusb_hid_init);/* 导出 MSH 命令,在串口终端手动触发鼠标运动测试 */staticinthid_example(intargc,char**argv){ hid_mouse_test(0); return0;}MSH_CMD_EXPORT(hid_example, USB HID mouse example - draw circle);#endif/* RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE */

代码说明:

hid_mouse_init(busid, reg_base):初始化 USB HID 鼠标设备,busid 从 0 开始,reg_base 填写芯片 USB 寄存器基地址。

hid_mouse_test(busid):执行鼠标测试,内部通过周期性发送 X/Y 位移数据使鼠标光标在屏幕上做圆周运动。

INIT_COMPONENT_EXPORT 宏确保 USB 在 RT-Thread 启动时自动初始化。

MSH_CMD_EXPORT 将 hid_example 注册为 FinSH 命令,可在串口终端输入触发。

在首次编译时,可能会报错缺少USB_ClockInit函数。我们在 usb_glue_mcx.c 中加入对MCXA366芯片的兼容代码。

#elifdefined(MCXA156_H_) || defined(MCXA366_H_)#defineUSBD_IRQ USB0_IRQHandlervoidUSB_ClockInit(void){ RESET_PeripheralReset(kUSB0_RST_SHIFT_RSTn); CLOCK_EnableUsbfsClock();}

代码位置如图:

编译与下载

使用 Keil MDK:

在 ENV 中生成 Keil 工程:

scons--target=mdk5

使用 AC6 编译器打开工程编译,连接 MCU-Link 调试器(J15 口),下载固件到开发板。

硬件连接

按如下方式连接硬件:

使用第一根 USB Type-C 线连接开发板MCU-Link 调试口(J15)到电脑,用于串口调试输出

使用第二根 USB Type-C 线连接开发板USB Device 功能口(J10)到电脑,用于 HID 鼠标通信

上电后等待系统启动

查看串口输出

打开串口终端(波特率 115200),复位开发板,可看到 RT-Thread 启动日志:

4aeec900-ce95-11f1-9b19-92fbcf53809c.png

USB 枚举验证

将第二根 USB 线插入电脑后,电脑应自动枚举出 USB HID 鼠标设备。可通过以下方式验证:

Windows 设备管理器:

打开设备管理器 → 人体学输入设备(HID),可看到新增的 USB 输入设备 或 HID-compliant mouse。

4afc10b0-ce95-11f1-9b19-92fbcf53809c.png

执行鼠标运动测试

在串口终端输入命令:

msh> hid_example

此时可观察到:

电脑屏幕上的鼠标光标开始做持续的圆周运动

4b22cade-ce95-11f1-9b19-92fbcf53809c.png

运动轨迹原理:

hid_mouse_test() 函数内部通过数学方式周期性计算圆上各点的 X/Y 坐标差值,逐步发送给主机,形成圆周轨迹:

#defineCURSOR_STEP 2U#defineCURSOR_WIDTH 20Uvoiddraw_circle(uint8_t*buf){ staticint32_tmove_cnt =0; staticuint8_tstep_x_y =0; staticint8_tx =0, y =0; move_cnt++; if(move_cnt > CURSOR_WIDTH) { step_x_y++; step_x_y = step_x_y %4; move_cnt =0; } switch(step_x_y) { case0: { y =0; x = CURSOR_STEP; }break; case1: { x =0; y = CURSOR_STEP; }break; case2: { y =0; x = (int8_t)(-CURSOR_STEP); }break; case3: { x =0; y = (int8_t)(-CURSOR_STEP); }break; } buf[0] =0; buf[1] = x; buf[2] = y; buf[3] =0;}

工程代码

本文工程代码已合并入主线master:

GitHub 仓库:【https://github.com/RT-Thread/rt-thread/tree/master/bsp/nxp/mcx/mcxa/frdm-mcxa366】

PR 地址: 【https://github.com/RT-Thread/rt-thread/pull/11381】

心得体会

CherryUSB 的适配体验

在本次实践中,最值得分享的经验是 CherryUSB 在 RT-Thread 生态中的高度集成。

以前在RT-Thread上支持USB外设,基本都需要实现一个drv_usbd.c驱动文件。我之前也是这个思路,对照官方SDK中的例程研究了很久,但突然翻到之前大佬在FRDM-MCXA156开发板上测评USB的文章,发现CherryUSB已经做了完善的支持,MCXA156和MCXA366属于同一系列,代码结构非常相似,对照着配置很快就将demo跑了起来。

总结

本次实践完整走通了FRDM-MCXA366 + RT-Thread + CherryUSB + USB HID 鼠标这一技术路径,验证了 NXP MCX A 系列新一代 MCU 在 RT-Thread 生态下的 USB 设备开发能力。CherryUSB 的模板化设计让 HID 鼠标的实现变得异常简洁——核心应用代码不超过 20 行——而背后 USB 协议栈的复杂性被完全屏蔽。对于希望在 MCX A 系列上快速实现 USB 功能的开发者,CherryUSB + RT-Thread 是目前最推荐的技术组合。