ADXL355 STM32 HAL 库 SPI 驱动实战:从零构建高精度加速度数据采集系统

发布时间:2026/7/15 22:44:11
ADXL355 STM32 HAL 库 SPI 驱动实战:从零构建高精度加速度数据采集系统 1. ADXL355加速度计与STM32 SPI驱动基础ADXL355是ADI公司推出的超低噪声数字加速度计工业级振动监测项目的理想选择。相比常见的ADXL345它的噪声密度低至25μg/√Hz分辨率更高特别适合需要微振动检测的场景。我第一次在风机状态监测项目中使用它时就被其数据稳定性惊艳到了——即使放在桌面上也能清晰捕捉到空调气流引起的微小振动。硬件连接要点SPI模式选择ADXL355支持模式0和模式3实测两种模式在STM32上都能稳定工作。我的习惯是统一用模式0CPOL0CPHA0引脚连接SCKPB13SPI2时钟MISOPB14主入从出MOSIPB15主出从入CSPB12软件控制片选DRDY可接中断引脚实现事件触发// STM32CubeMX生成的SPI初始化代码片段 hspi2.Instance SPI2; hspi2.Init.Mode SPI_MODE_MASTER; hspi2.Init.Direction SPI_DIRECTION_2LINES; hspi2.Init.DataSize SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity SPI_POLARITY_LOW; // 模式0 hspi2.Init.CLKPhase SPI_PHASE_1EDGE; hspi2.Init.NSS SPI_NSS_SOFT; // 软件控制片选 HAL_SPI_Init(hspi2);通信速率实测在STM32F407上测试SPI时钟设为10MHz时通信稳定超过15MHz会出现数据错位。建议工业环境保守设置为5MHz毕竟ADXL355的最大输出数据率也只有4kHz。2. HAL库SPI驱动实现细节2.1 寄存器读写核心函数ADXL355的寄存器操作需要严格遵循时序规范。这里分享一个我优化过的寄存器读写方案加入了超时检测和错误重试机制#define ADXL355_SPI_TIMEOUT 100 // 100ms超时 // 写寄存器函数带重试 HAL_StatusTypeDef ADXL355_WriteReg(SPI_HandleTypeDef *hspi, uint8_t reg, uint8_t value) { uint8_t txData[2] {(reg 1) | 0x00, value}; // 写命令地址左移1位 HAL_StatusTypeDef status; uint8_t retry 3; do { ADXL355_CS_Enable(); status HAL_SPI_Transmit(hspi, txData, 2, ADXL355_SPI_TIMEOUT); ADXL355_CS_Disable(); if(status HAL_OK) { // 验证写入值 uint8_t readBack ADXL355_ReadReg(hspi, reg); if(readBack value) return HAL_OK; } retry--; } while(retry 0); return HAL_ERROR; } // 读寄存器函数支持多字节读取 uint32_t ADXL355_ReadReg(SPI_HandleTypeDef *hspi, uint8_t reg, uint8_t len) { uint8_t txBuf (reg 1) | 0x01; // 读命令 uint8_t rxBuf[3] {0}; ADXL355_CS_Enable(); HAL_SPI_Transmit(hspi, txBuf, 1, ADXL355_SPI_TIMEOUT); HAL_SPI_Receive(hspi, rxBuf, len, ADXL355_SPI_TIMEOUT); ADXL355_CS_Disable(); // 组合多字节数据 uint32_t result 0; for(int i0; ilen; i) { result (result 8) | rxBuf[i]; } return result; }避坑经验每次读写前必须确保CS信号先拉低操作完成后立即拉高读取加速度数据时建议关闭中断避免SPI时序被打断温度传感器数据需要特殊处理转换公式为温度(℃) (RAW - 1852) / (-9.05) 252.2 关键寄存器配置ADXL355有这几个关键寄存器需要特别注意寄存器地址名称配置建议典型值0x2DPOWER_CTL测量模式选择0x000x2CRANGE量程设置(2g/4g/8g)0x01(4g)0x28FILTER设置ODR和HPF0x02(1kHz)0x2FRESET写0x52触发软复位0x52初始化代码示例void ADXL355_Init(SPI_HandleTypeDef *hspi) { // 复位设备 ADXL355_WriteReg(hspi, ADXL355_RESET, 0x52); HAL_Delay(100); // 等待复位完成 // 配置测量范围±4g ADXL355_WriteReg(hspi, ADXL355_RANGE, 0x01); // 设置输出数据率1kHz禁用高通滤波 ADXL355_WriteReg(hspi, ADXL355_FILTER, 0x02); // 进入测量模式 ADXL355_WriteReg(hspi, ADXL355_POWER_CTL, 0x00); }3. 加速度数据采集与处理3.1 原始数据读取与转换ADXL355的加速度数据以20位补码形式存储需要特殊处理// 读取三轴加速度数据带符号扩展 void ADXL355_ReadAccel(SPI_HandleTypeDef *hspi, float *accel) { uint32_t rawX ADXL355_ReadReg(hspi, ADXL355_XDATA3, 3); uint32_t rawY ADXL355_ReadReg(hspi, ADXL355_YDATA3, 3); uint32_t rawZ ADXL355_ReadReg(hspi, ADXL355_ZDATA3, 3); // 符号扩展处理 int32_t signedX (int32_t)(rawX 12) 12; int32_t signedY (int32_t)(rawY 12) 12; int32_t signedZ (int32_t)(rawZ 12) 12; // 转换为g单位以±4g量程为例 accel[0] (float)signedX / 128000.0f; accel[1] (float)signedY / 128000.0f; accel[2] (float)signedZ / 128000.0f; }数据验证技巧静止状态下Z轴读数应接近1g地球重力快速翻转传感器时各轴数据应在±量程范围内温度数据变化应与环境温度趋势一致3.2 数据滤波与降噪工业现场常见的高频干扰可以通过软件滤波改善#define FILTER_WINDOW_SIZE 5 // 滑动平均滤波实现 void MovingAverageFilter(float *input, float *output) { static float buffer[FILTER_WINDOW_SIZE][3] {0}; static uint8_t index 0; // 更新缓冲区 for(int i0; i3; i) { buffer[index][i] input[i]; } index (index 1) % FILTER_WINDOW_SIZE; // 计算平均值 for(int axis0; axis3; axis) { float sum 0; for(int j0; jFILTER_WINDOW_SIZE; j) { sum buffer[j][axis]; } output[axis] sum / FILTER_WINDOW_SIZE; } }对于振动分析场景可以结合ADXL355内置的高通滤波配置FILTER寄存器去除直流分量突出振动特征。4. 工业级应用优化技巧4.1 传感器校准方法即使高精度如ADXL355在实际安装后也需要校准零偏校准将传感器静止放置在水平面记录各轴输出平均值作为偏移量后续读数减去对应偏移量// 简易校准函数 void ADXL355_Calibrate(SPI_HandleTypeDef *hspi, float *offsets) { float accel[3], sum[3] {0}; uint16_t samples 100; for(int i0; isamples; i) { ADXL355_ReadAccel(hspi, accel); for(int j0; j3; j) sum[j] accel[j]; HAL_Delay(10); } // Z轴减去1g重力影响 offsets[0] sum[0]/samples; offsets[1] sum[1]/samples; offsets[2] sum[2]/samples - 1.0f; }4.2 低功耗优化对于电池供电设备可以通过以下方式降低功耗降低ODR到最低需求频率如从4kHz降到250Hz不使用温度传感器时关闭相关电路利用FIFO功能批量读取减少SPI唤醒次数长时间不采集时进入待机模式// 低功耗模式切换 void ADXL355_SetLowPower(SPI_HandleTypeDef *hspi, bool enable) { if(enable) { // 设置ODR31.25Hz ADXL355_WriteReg(hspi, ADXL355_FILTER, 0x07); } else { // 恢复1kHz采样率 ADXL355_WriteReg(hspi, ADXL355_FILTER, 0x02); } }5. 典型问题排查指南问题1读取的数据全为0xFF或0x00检查SPI线序是否正确特别是MISO/MOSI是否接反用逻辑分析仪抓取SPI波形确认CS信号正常验证电源电压是否稳定3.3V±5%问题2数据跳动过大检查PCB布局确保传感器远离电机等干扰源尝试降低SPI时钟频率如从10MHz降到1MHz在电源引脚添加0.1μF去耦电容问题3温度读数异常确认温度转换公式正确检查是否开启了自发热模式不建议长期开启与其他温度传感器对比验证在最近的一个煤矿设备监测项目中我们遇到SPI数据不稳定的情况最终发现是电机启停导致电源波动。通过在传感器电源端增加LC滤波电路并改用屏蔽电缆问题得到彻底解决。这也提醒我们工业环境下的电磁兼容设计同样重要。