第一次拿到ADIS16470或ADIS16500模块时,硬件连接是首要任务。这两个模块都采用SPI接口通信,需要连接4根基本线:SCLK(时钟)、MOSI(主机输出从机输入)、MISO(主机输入从机输出)和NSS(片选)。我建议使用杜邦线连接时给每根线贴上标签,避免接错。特别要注意的是,ADIS16470的J1接口引脚不是按顺序排列的,而是按行编号,这个细节手册里容易忽略,接错可能烧毁模块。
在STM32CubeMX中配置SPI时,关键参数要格外注意:
我遇到过因为CPHA设错导致数据全零的情况,调试了半天才发现。建议先用示波器检查SCLK波形是否符合手册时序图。另外,NSS片选线如果用硬件SPI自带的NSS功能,可能会遇到信号冲突,更稳妥的做法是用普通GPIO手动控制,配置为开漏输出模式。
Burst模式是快速获取六轴数据的捷径。实际操作中只需要三步:
c复制// 示例代码(STM32 HAL库)
uint16_t burst_data[14];
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)0x6800, (uint8_t*)burst_data, 1, 100);
HAL_SPI_Receive(&hspi1, (uint8_t*)(burst_data+1), 13, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
读取到的数据顺序对应手册中的寄存器地址:
校验算法很简单:把所有16位数据相加,低16位应该等于0xFFFF。实测发现偶尔会有校验失败的情况,建议连续读取3次取相同结果的数据帧。
当需要更高精度时,必须使用寄存器直接读取模式。ADIS16500的角速度分辨率高达32位(655360LSB/°/s),读取方法很特别:
c复制uint16_t read_reg(uint16_t addr) {
uint16_t tx = addr | 0x8000; // 读指令最高位置1
uint16_t rx;
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&tx, (uint8_t*)&rx, 1, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
return rx;
}
原始数据需要换算成物理量,以X轴角速度为例:
code复制实际值(°/s) = 原始数据 * 0.00625 / 655360
这个换算系数手册里写得比较隐晦,我实测发现ADIS16470和ADIS16500的系数不同,16500需要额外除以40。有个简单验证方法:静止时读取的角速度值应该接近0。
新模块上电后必须做零点校准。我的标准流程是:
c复制// 零点校准示例
int32_t sum_x=0;
for(int i=0; i<1000; i++){
sum_x += read_reg(0x04); // 读取X轴原始值
HAL_Delay(10);
}
uint16_t offset_x = -(sum_x/1000);
write_reg(0x0E, offset_x); // 写入偏移量
ADIS16500内置的巴特沃斯滤波器非常实用,通过SENS_AVG寄存器(0x5A)配置:
实测发现滤波过强会导致响应延迟,做无人机控制时建议设为100Hz截止频率(寄存器值0x04)。如果还出现高频噪声,可以在软件端加移动平均滤波,窗口大小5~10即可。
焊接接口时建议用热风枪而不是烙铁,因为模块对静电敏感。我曾在冬天干燥环境下烧坏过一个模块,后来都先摸下水管释放静电再操作。另外两个容易踩的坑:
时序问题:SPI时钟相位错误是最常见问题。有次调试发现数据偶尔跳变,最后发现是SCLK上升沿太缓,加了22欧姆串联电阻改善信号质量后稳定。
电源干扰:ADIS系列对电源纹波敏感。最好用LDO单独供电,并在VCC对地加10μF钽电容+0.1μF陶瓷电容。曾有用开关电源导致数据周期性波动的情况,换成LT1763后解决。
长期使用时建议每半年做一次校准,温度变化大的环境要更频繁。有个取巧的方法:在设备外壳加个温湿度传感器,当检测到环境温度变化超过5℃时自动触发校准流程。