【免费开源】基于STM32的ADXL345三轴加速度传感器姿态检测倾角测量完整项目源码分享

一、项目背景

ADXL345 是 ADI 公司出品的一款经典 ±2g/±4g/±8g/±16g 量程的三轴数字加速度计,分辨率高达 13 位,支持 SPI 与 IIC 接口,被广泛用于人体动作识别、电子计步器、防摔报警、无人机姿态、车载倾角仪等场景。本项目"基于 STM32 ADXL345 三轴加速度传感器"提供完整的硬件接线方案、IIC/SPI 双驱动实现、姿态解算算法(Roll/Pitch)以及上位机数据可视化代码,是学习数字传感器和惯性测量入门的优质工程。

二、项目流程图

否

是

是

STM32 上电

IIC/SPI 初始化

读取 DEVID 寄存器

DEVID = 0xE5?

报错: 通信失败

配置量程 ±4g, 数据率 100Hz

使能 MEASURE 模式

启动 10ms 定时器

定时器中断?

突发读 DATAX0~DATAZ1
共 6 字节

合并 LSB+MSB → int16

原始值 × 灵敏度 = g

低通滤波: y=0.8y+0.2x

计算 Roll/Pitch
Roll=atan2 Y,Z
Pitch=atan2 -X,sqrt Y²+Z²

串口发送数据帧

OLED 显示倾角

三、硬件接线(IIC 模式)

ADXL345STM32
VCC3.3V
GNDGND
SDAPB7
SCLPB6
CS3.3V (固定高)
SDOGND (设地址 0x53)

四、核心代码

4.1 ADXL345 初始化与读取

#include "adxl345.h"
#include "main.h"
extern I2C_HandleTypeDef hi2c1;
#define ADDR (0x53<<1)

uint8_t ADXL345_Init(void){
    uint8_t id=0;
    HAL_I2C_Mem_Read(&hi2c1,ADDR,0x00,1,&id,1,100);
    if(id!=0xE5) return 0;
    uint8_t v=0x0B;     /* full_res, ±16g */
    HAL_I2C_Mem_Write(&hi2c1,ADDR,0x31,1,&v,1,100);
    v=0x0A;             /* 100Hz */
    HAL_I2C_Mem_Write(&hi2c1,ADDR,0x2C,1,&v,1,100);
    v=0x08;             /* MEASURE */
    HAL_I2C_Mem_Write(&hi2c1,ADDR,0x2D,1,&v,1,100);
    return 1;
}

void ADXL345_ReadXYZ(int16_t *x,int16_t *y,int16_t *z){
    uint8_t b[6];
    HAL_I2C_Mem_Read(&hi2c1,ADDR,0x32,1,b,6,100);
    *x=(int16_t)(b[1]<<8|b[0]);
    *y=(int16_t)(b[3]<<8|b[2]);
    *z=(int16_t)(b[5]<<8|b[4]);
}

4.2 姿态解算

#include <math.h>
typedef struct { float roll, pitch; } Att_t;

Att_t ADXL_Pose(int16_t x,int16_t y,int16_t z){
    float gx=x*0.0039f, gy=y*0.0039f, gz=z*0.0039f;
    Att_t a;
    a.roll  = atan2f(gy, gz) * 57.2958f;
    a.pitch = atan2f(-gx, sqrtf(gy*gy+gz*gz)) * 57.2958f;
    return a;
}

4.3 主程序

extern UART_HandleTypeDef huart1;
int main(void){
    HAL_Init(); SystemClock_Config();
    MX_GPIO_Init(); MX_I2C1_Init(); MX_USART1_UART_Init();
    if(!ADXL345_Init()){ while(1); }

    int16_t x,y,z; char buf[64];
    while(1){
        ADXL345_ReadXYZ(&x,&y,&z);
        Att_t a = ADXL_Pose(x,y,z);
        int n = snprintf(buf,sizeof(buf),"R=%.1f P=%.1f\r\n",a.roll,a.pitch);
        HAL_UART_Transmit(&huart1,(uint8_t*)buf,n,100);
        HAL_Delay(10);
    }
}

五、关键技术点

5.1 量程与灵敏度

ADXL345 在 FULL_RES 模式下,每 LSB = 3.9mg;本工程使用 ±16g 量程对应 13 位有效。如果是体感识别建议使用 ±4g 量程提高分辨率。

5.2 中断与 FIFO

ADXL345 有 32 级 FIFO 和 2 路硬件中断输出(INT1/INT2),可以配置 Activity/Inactivity/Tap/DoubleTap/FreeFall/Overrun 等中断,实现低功耗下的"事件驱动"采样。

5.3 滤波

加速度信号高频噪声大,建议软件加一阶低通滤波(IIR)或滑动平均(窗口 8)。如果项目对实时性要求很高,可以直接使用 ADXL345 内部的高通/低通滤波寄存器。

5.4 倾角解算

仅靠加速度计计算倾角在静态时精度高,但动态情况下会有线性加速度干扰。可以与陀螺仪数据通过互补滤波或卡尔曼滤波融合,获得稳定 Roll/Pitch/Yaw。

六、应用案例

  • 智能手环/手表的步数检测;
  • 防摔检测的老人监护设备;
  • 数控机床、电梯倾角监测;
  • DIY 平衡车、四轴飞行器;
  • 工业振动监测(泵、电机、轴承)。

七、调试经验

  1. DEVID 必须为 0xE5,否则就是接线问题或上电时序问题;
  2. CS 必须接 3.3V,否则芯片进入 SPI 模式无法被 IIC 读取;
  3. SDO 决定 IIC 地址:接 GND 是 0x53,接 VCC 是 0x1D;
  4. 量程切换后需重置 MEASURE,否则采样数据可能错乱;
  5. 板子贴近金属时灵敏度会下降,注意安装结构。

八、总结

本项目用清晰的代码与硬件方案完整实现了 ADXL345 在 STM32 上的应用全流程,从底层 IIC 通信、寄存器配置到上层倾角解算和数据上报,麻雀虽小五脏俱全。完整工程已开源在压缩包中,方便读者直接编译运行并扩展为更复杂的姿态测量系统。

在这里插入图片描述

更多推荐