1. 任务介绍
本项目旨在开发一款基于 RP2350B 微控制器的多功能空中鼠标(Air Mouse)。主要功能包括:
- 姿态解算:利用加速度计数据,通过互补滤波或低通滤波算法解算当前的俯仰(Pitch)和横滚(Roll)角度。
- USB HID 输出:将解算出的姿态角度映射为 USB 鼠标的光标移动,并支持左键、右键及自定义快捷键。
- 交互与显示:
- 4个拨码开关:用于硬件设置鼠标灵敏度档位(0-15)。
- WS2812 LED:根据不同颜色指示当前连接状态、灵敏度热力图显示及休眠呼吸效果。
- 4个按键:分别映射鼠标左键、右键、中键及演示翻页功能,支持短按与长按区分。
- K1: 左键 / PageUp
- K2: 启用禁用 / 重置中心
- K3: 中键 / F5
- K4: 右键 / PageDown
- 双位数码管:实时显示当前灵敏度档位数值。
- 电源管理:支持空闲自动休眠,并通过摇动或按键唤醒的低功耗设计。
2. 项目介绍
该项目使用了RP2350B核心板、C 语言,实现了一个 RP2350B 空中鼠标系统的设计。它的主要功能为:基于 RP2350B,板上有 KXTJ3 姿态传感器、双位 7 段数码管、2 颗 WS2812 及 8 个单色 LED,主要用于实现 USB 体感鼠标与光效交互演示。
本项目这款集成了体感控制与丰富人机交互界面的嵌入式输入设备。核心在于利用微控制器的强大算力和丰富外设,将简单的传感器数据转化为流畅的人机交互体验。项目不仅实现了基本的空中鼠标功能,还通过精心设计的 UI(数码管、RGB LED)提供了直观的状态反馈。主要应用于演示演讲、智能电视控制等场景,无需桌面即可操作光标。
3. 硬件介绍
本项目基于 RP2350B 平台,主要硬件组成如下:
- 主控芯片 (MCU):RP2350B。
- 采用双核架构(ARM Cortex-M33 / RISC-V),本项目主要使用其 ARM 核心。
- 利用其 PIO(可编程 I/O)和 DMA(直接存储器访问)特性来驱动高速外设,减轻 CPU 负担。
- 姿态传感器 (IMU):KXTJ3-1057。
- 一款低功耗三轴加速度计,通过 I2C 接口与 MCU 通信。
- 由于该传感器仅提供加速度数据(无陀螺仪),本项目采用基于倾角测量的算法来模拟鼠标移动。
- 显示模块:2位 7段数码管(共阳/共阴可选)。
- 由两片 74HC595 移位寄存器级联驱动。
- 用于显示当前的灵敏度等级(00-15)或其他状态代码。
- RGB 指示灯:WS2812B。
- 集成控制器的全彩 LED,用于指示连接状态(红/绿)和呼吸灯效果。
- 辅助指示灯:8个单色 LED。
- 用于辅助显示灵敏度档位(二进制或进度条形式)。
- 输入设备:
- 4个 轻触按键:接入 ADC 输入端,通过电阻分压网络识别不同按键。
- 4位 拨码开关:接入 ADC 或 GPIO,用于配置参数。
- 接口:Type-C USB 接口,用于供电及 USB HID 通信。
4. 方案框图和项目设计思路
4.1 系统框图

4.2 设计思路
- 高性能并发架构:
- 项目采用了 Super Loop + 中断/DMA 的架构。
- 主循环 (100Hz):负责核心业务逻辑,包括传感器读取、姿态解算、按键扫描和 USB 报文发送。
- 底层驱动:
- Display (74HC595):利用 PIO (Programmable I/O) 状态机实现高速串行数据发送,完全不占用 CPU 时间,实现高刷新率无闪烁显示。
- WS2812:采用 PWM + DMA 方案生成精确时序,避免在发送 LED 数据时关闭中断,保证了 USB 通信的稳定性。
- USB 任务:通过 TinyUSB 协议栈处理 HID 中断传输,确保鼠标回报率。
- 姿态解算算法:
- 由于硬件限制(仅加速度计),采用 倾角检测算法。
- 计算重力向量在 X/Y 轴的分量来得出 Pitch 和 Roll 角度。
- 引入 低通滤波器 (Low Pass Filter) 平滑数据,减少手部抖动带来的光标颤动。
- 加入 死区 (Deadzone) 控制,确保静止时鼠标光标稳定。
- 状态机管理:
- 系统维护
DISCONNECTED->CONNECTED->SLEEP三种状态。 - 通过 加速度幅值检测 实现“摇一摇唤醒”功能,当检测到的加速度变化超过阈值时,自动从低功耗模式唤醒。
- 系统维护
5. 调试软件及关键代码说明
5.1 开发环境
- 编程语言:C (C11 Standard)
- 构建系统:CMake (3.22+) + Pico SDK (v2.2.0) + ARM GNU Toolchain (13.3.rel1)
- IDE:Visual Studio Code
- 调试工具:串口助手(用于打印 Log)
5.2 软件流程图
- 系统初始化:
- 配置时钟 -> 初始化 PIO (Display) -> 初始化 PWM/DMA (WS2812) -> 初始化 I2C (IMU) -> 初始化 ADC (Keys)。
- 主任务 (Air Mouse Task):
10ms周期运行一次。- Step 1: 读取 KXTJ3 加速度数据 (ax, ay, az)。
- Step 2: 读取 ADC 按键值并消抖,判断短按/长按。
- Step 3:
attitude_update()更新姿态角度。 - Step 4: 根据拨码开关计算灵敏度系数。
- Step 5: 调用
usb_hid_mouse_move(dx, dy)发送 HID 报文。 - Step 6: 根据状态更新 LED 颜色(正常:绿色/热力图;休眠:蓝色呼吸)。

5.3 关键代码解析
1. 姿态解算 (App/Attitude.c)
由于没有陀螺仪,代码核心在于将加速度分量转换为倾角,并进行滤波:
// 计算倾角 (简化版)
float pitch_accel = atan2f(ax, sqrtf(ay * ay + az * az)) * RAD_TO_DEG;
float roll_accel = atan2f(ay, sqrtf(ax * ax + az * az)) * RAD_TO_DEG;
// 低通滤波 (IIR Filter)
// alpha 为滤波系数,越小越平滑但延迟越高
filter->pitch = LOWPASS_ALPHA * pitch_accel + (1.0f - LOWPASS_ALPHA) * filter->pitch;
2. 鼠标移动控制 (App/Air_Mouse.c)
将角度转换为像素位移,并加入灵敏度控制:
// 灵敏度 = 基础值 + 拨码开关增益
float sens_factor = 0.5f + (s_sensitivity_level * 0.3f);
// 计算位移
float dx_f = pitch * sens_factor * MOUSE_SCALE_FACTOR;
// 限制最大速度并发送
usb_hid_mouse_move((int8_t)dx_f, (int8_t)dy_f);
3. PIO 驱动 74HC595 (App/Display_595)
利用 PIO 状态机自动完成移位和锁存信号的生成,CPU 仅需写入需要显示的数据字:
// PIO 程序片段
pull block // 等待 FIFO 有数据
out pins, 8 // 输出 8 位段选
set pins, 1 // 产生 Latch 上升沿
set pins, 0 // 产生 Latch 下降沿
6. 功能展示图及说明
- 灵敏度调节:
- 操作拨码开关,可以看到双位数码管显示的数值从
00变化至15。 - 同时 WS2812 LED 的颜色会从 蓝色(低灵敏度)渐变至 红色(高灵敏度),提供直观的热力图视觉反馈。
- 操作拨码开关,可以看到双位数码管显示的数值从
- 空中鼠标操作:
- 手持开发板前后倾斜,鼠标光标在屏幕上垂直移动。
- 左右倾斜,光标水平移动。
- 短按 K1 键实现鼠标左键点击,长按实现 PageUp 翻页(PPT 模式)。
- 休眠与唤醒:
- 静置设备 10 秒后,数码管熄灭,WS2812 转为蓝色呼吸灯模式(Sleep Mode)。
- 拿起设备摇晃,指示灯瞬间变绿,数码管重新点亮,恢复鼠标控制。
7. 项目中遇到的难题及解决方法
难题 1:纯加速度计的抖动与漂移
问题:KXTJ3 只有加速度计,受手部微小抖动影响严重,光标难以精确定位。
解决:
实施了强低通滤波,虽然牺牲了少许响应速度,但通过调整 LOWPASS_ALPHA 找到了平滑度与延迟的平衡点。
实现了 死区 (Deadzone) 逻辑,当倾角小于一定阈值(如 2度)时,强制输出为 0,防止静止时光标漂移。
难题 2:多外设并发导致的时序冲突
问题:WS2812 对时序要求极高(800kHz),早期使用软件 bit-banging 方式时,一旦产生 USB 中断,LED 就会闪烁乱码;反之若关闭中断驱动 LED,则 USB 连接会掉线。
解决:全面采用硬件卸载。
WS2812 改用 PWM + DMA 方式,DMA 自动搬运数据到 PWM 占空比寄存器,完全无需 CPU 干预且不关中断。
74HC595 改用 PIO,同样独立于 CPU 运行。
这确保了 USB 通信(TinyUSB)可以随时响应,互不干扰。
难题 3:USB 复合设备枚举失败
问题:同时模拟鼠标和键盘时,Windows 经常提示 "Code 43" 描述符错误。
解决:仔细检查并重写了 usb_descriptors.c,确保 Interface Number 和 Endpoint Address 不冲突,并且正确设置了 ReportID,使得系统能区分鼠标数据和键盘数据。
难题 4:R-2R网络控制8个按钮抖动冲突
问题:由于按钮和拨码使用的是R-2R网络,导致检测过程存在抖动情况
解决:放宽按钮控制阈值,限制按钮无冲突按下范围,保证多个按钮不会同时按下的情况下按键可靠
8. 心得体会
通过本次项目的开发,我深入理解了 RP2350 系列芯片独特的 PIO 架构优势。在传统 MCU 上,驱动 WS2812 和高刷新率数码管往往需要消耗大量 CPU 资源或复杂的中断管理,而 PIO 让我们能像设计 FPGA 一样定义外设行为,极大地简化了软件逻辑。