空中鼠标作为新一代人机交互设备,其硬件架构设计体现了嵌入式系统开发的精髓。整套系统采用双板分离式设计,通过2.4GHz无线通信实现数据交互,完美复现了传统鼠标的所有功能。
发射板作为动作捕捉终端,其核心器件选型经过精心考量:
STM32F103C8T6:选用这款Cortex-M3内核MCU主要基于三点考量:首先其72MHz主频足以处理运动传感器数据;其次内置12位ADC满足模拟信号采集需求;最重要的是其丰富的外设接口(I2C、SPI)完美适配周边器件连接。
MPU6050:这款六轴运动处理传感器集成了3轴陀螺仪和3轴加速度计,采用I2C接口通信。其关键参数包括:
NRF24L01+:2.4GHz无线收发模块,具有以下技术特性:
接收板作为HID设备模拟端,在硬件设计上有几个关键细节:
USB枚举处理:STM32需要正确响应主机的设备描述符请求,包括:
电源管理:USB接口提供5V/500mA供电,需通过LDO转换为3.3V供MCU和无线模块使用。实测中,选用AMS1117-3.3时需注意其最大输入电压不能超过12V。
抗干扰设计:在PCB布局时,NRF24L01+天线区域需保持净空,周边不得布置高频信号线。建议采用π型滤波电路为射频模块供电。
MPU6050通过I2C接口输出原始数据,典型初始化流程如下:
c复制#define MPU6050_ADDR 0x68
#define SMPLRT_DIV 0x19
#define CONFIG 0x1A
#define GYRO_CONFIG 0x1B
#define ACCEL_CONFIG 0x1C
#define PWR_MGMT_1 0x6B
void MPU6050_Init() {
I2C_Write(MPU6050_ADDR, PWR_MGMT_1, 0x00); // 解除休眠
I2C_Write(MPU6050_ADDR, SMPLRT_DIV, 0x07); // 采样率=1kHz/(7+1)=125Hz
I2C_Write(MPU6050_ADDR, CONFIG, 0x06); // 低通滤波带宽5Hz
I2C_Write(MPU6050_ADDR, GYRO_CONFIG, 0x18);// 陀螺仪量程±2000°/s
I2C_Write(MPU6050_ADDR, ACCEL_CONFIG, 0x10);// 加速度计量程±8g
}
注意事项:I2C通信必须严格遵循时序要求,特别是MPU6050的启动时间约50ms,过早读取数据会导致初始化失败。
原始传感器数据需要经过多重处理才能转换为鼠标移动信号:
校准阶段:
姿态解算:
采用互补滤波算法融合加速度计和陀螺仪数据:
code复制角度 = 0.98*(角度 + 陀螺仪数据*dt) + 0.02*加速度计角度
其中dt为采样间隔时间(8ms@125Hz)
移动量转换:
将角度变化量映射为屏幕像素位移:
c复制pixel_x = k * (gyro_y - bias_y) * sensitivity;
pixel_y = k * (gyro_x - bias_x) * sensitivity;
其中k为比例系数,需根据使用距离调整
发射端与接收端需保持一致的射频配置:
c复制void NRF24L01_Init(void) {
// 基本配置
SPI_Write_Reg(CONFIG, 0x0E); // 使能CRC(2字节),上电,PTX模式
SPI_Write_Reg(EN_AA, 0x01); // 使能通道0自动应答
SPI_Write_Reg(EN_RXADDR, 0x01); // 使能通道0接收
SPI_Write_Reg(SETUP_AW, 0x03); // 地址宽度5字节
SPI_Write_Reg(SETUP_RETR, 0x1A); // 自动重发延时500us+86us,重试10次
SPI_Write_Reg(RF_CH, 0x40); // 信道频率2.400GHz+0x40*1MHz=2.440GHz
SPI_Write_Reg(RF_SETUP, 0x07); // 2Mbps速率,0dBm发射功率
SPI_Write_Reg(STATUS, 0x70); // 清除状态寄存器
}
考虑到实时性要求,数据包设计为12字节固定长度:
| 偏移量 | 长度 | 内容 | 说明 |
|---|---|---|---|
| 0 | 1 | 包头 | 固定为0xAA |
| 1 | 2 | X轴角速度 | 有符号short类型 |
| 3 | 2 | Y轴角速度 | 有符号short类型 |
| 5 | 2 | Z轴角速度 | 有符号short类型 |
| 7 | 1 | 按键状态 | 位映射(左/右/中键) |
| 8 | 2 | 滚轮数据 | 有符号short类型 |
| 10 | 1 | 校验和 | 前面11字节累加和 |
| 11 | 1 | 包尾 | 固定为0x55 |
实测建议:在2Mbps速率下,建议设置重发延时为250μs,重试次数5次,可在可靠性和实时性间取得平衡。
接收板需要正确实现以下描述符:
c复制const uint8_t HID_ReportDescriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 省略其他描述符...
};
USB中断传输模式下,需每8ms上报一次数据:
c复制void USB_Send_Mouse_Report(int8_t x, int8_t y, uint8_t buttons) {
static uint8_t mouse_report[4] = {0};
mouse_report[0] = buttons;
mouse_report[1] = x;
mouse_report[2] = y;
USBD_HID_SendReport(&hUsbDeviceFS, mouse_report, 4);
}
现象:鼠标指针跳动或延迟明显
排查步骤:
解决方案:
现象:静止时鼠标指针缓慢移动
原因分析:
解决方法:
c复制// 动态校准零偏
void Dynamic_Calibration() {
static int16_t offset_x = 0, offset_y = 0;
if(++calib_cnt <= 100) {
offset_x += gyro_x;
offset_y += gyro_y;
} else if(calib_cnt == 101) {
offset_x /= 100;
offset_y /= 100;
}
gyro_x -= offset_x;
gyro_y -= offset_y;
}
典型错误:设备管理器显示"未知USB设备"
诊断方法:
关键检查点:
通过以下措施可将待机电流降至5μA以下:
唤醒流程示例:
c复制void Enter_Low_Power_Mode(void) {
MPU6050_Write_Reg(PWR_MGMT_1, 0x40); // 进入休眠
NRF24L01_Power_Down();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
SystemClock_Config(); // 唤醒后需重新配置时钟
}
为降低无线传输延迟,可采用二阶预测算法:
code复制pred_x = x + vx*dt + 0.5*ax*dt*dt;
pred_y = y + vy*dt + 0.5*ay*dt*dt;
其中vx/vy为速度,ax/ay为加速度,dt为预测时间(建议20-50ms)
通过USB DFU实现固件空中升级:
关键代码片段:
c复制void JumpToApp(void) {
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
__disable_irq();
Jump_To_Application = (pFunction)JumpAddress;
__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
Jump_To_Application();
}
| 测试项 | 标准值 | 测试方法 |
|---|---|---|
| 发射功率 | ≥0dBm | 频谱分析仪+功率计 |
| 接收灵敏度 | ≤-85dBm@2Mbps | 信号发生器+误码率测试 |
| 频偏误差 | ±50kHz以内 | 频率计数器测量载波 |
| 谐波辐射 | ≤-30dBc | 频谱分析仪扫描30MHz-1G |
运动检测测试:
按键测试:
续航测试:
建议采用六点校准法:
code复制[calib_matrix] = [raw_data]^-1 * [ideal_data]
量产时可将校准数据写入STM32的Flash最后页(防止被程序擦除)