基于STM32的ADXL345加速度计IIC读写程序(HAL库实现)
一、系统概述
ADXL345是一款低功耗、3轴MEMS加速度计,支持±2g/±4g/±8g/±16g量程,通过I2C/SPI接口通信。本程序基于STM32F103C8T6(或兼容型号)和HAL库,实现ADXL345的I2C驱动,包括初始化配置、寄存器读写、三轴加速度数据采集与数据转换,适用于姿态检测、运动监测、振动分析等场景。
二、硬件设计
2.1 核心组件
| 模块 | 型号/参数 | 功能说明 |
|---|---|---|
| 主控 | STM32F103C8T6(72MHz,I2C1) | I2C通信、数据处理、加速度值转换 |
| 加速度计 | ADXL345(I2C接口,3轴,±2g~±16g) | 采集X/Y/Z轴加速度(分辨率13位) |
| I2C接口 | PB6(SCL)、PB7(SDA)(I2C1) | 连接ADXL345的SCL/SDA引脚 |
| 电源 | 3.3V供电(ADXL345兼容3.3V/5V) | 为传感器和STM32供电 |
2.2 硬件连接
| ADXL345引脚 | STM32引脚(F103C8T6) | 说明 |
|---|---|---|
| VCC | 3.3V | 电源正极 |
| GND | GND | 电源负极 |
| SCL | PB6(I2C1_SCL) | I2C时钟线 |
| SDA | PB7(I2C1_SDA) | I2C数据线 |
| SDO | GND(或VCC) | I2C地址选择(GND→0x53,VCC→0x1D) |
三、软件设计(STM32 HAL库)
3.1 开发环境
- IDE:STM32CubeIDE 1.13.0+
- 库:STM32Cube_FW_F1_V1.8.0(HAL库)
- 工具链:GCC ARM Embedded
3.2 核心代码实现
3.2.1 头文件 adxl345.h(寄存器定义与函数声明)
#ifndef __ADXL345_H
#define __ADXL345_H
#include "stm32f1xx_hal.h"
// ==================== ADXL345 I2C地址(SDO接地=0x53,接VCC=0x1D) ====================
#define ADXL345_ADDR 0x53 << 1 // I2C设备地址(7位地址左移1位,HAL库要求)
// ==================== ADXL345寄存器地址 ====================
#define DEVID 0x00 // 设备ID(固定0xE5)
#define POWER_CTL 0x2D // 电源控制寄存器
#define DATA_FORMAT 0x31 // 数据格式寄存器
#define DATAX0 0x32 // X轴数据低8位
#define DATAX1 0x33 // X轴数据高8位
#define DATAY0 0x34 // Y轴数据低8位
#define DATAY1 0x35 // Y轴数据高8位
#define DATAZ0 0x36 // Z轴数据低8位
#define DATAZ1 0x37 // Z轴数据高8位
#define BW_RATE 0x2C // 带宽速率寄存器(采样率)
// ==================== 函数声明 ====================
HAL_StatusTypeDef ADXL345_Init(I2C_HandleTypeDef *hi2c); // 初始化ADXL345
HAL_StatusTypeDef ADXL345_WriteReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t data); // 写寄存器
HAL_StatusTypeDef ADXL345_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data); // 读单个寄存器
HAL_StatusTypeDef ADXL345_ReadRegs(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *buf, uint8_t len); // 读多个寄存器
HAL_StatusTypeDef ADXL345_ReadAccel(I2C_HandleTypeDef *hi2c, float *ax, float *ay, float *az); // 读取三轴加速度(g)
#endif
3.2.2 源文件 adxl345.c(驱动逻辑实现)
#include "adxl345.h"
// ==================== 初始化ADXL345(配置测量模式、数据格式) ====================
HAL_StatusTypeDef ADXL345_Init(I2C_HandleTypeDef *hi2c) {
uint8_t dev_id;
HAL_StatusTypeDef status;
// 1. 验证设备ID(应返回0xE5)
status = ADXL345_ReadReg(hi2c, DEVID, &dev_id);
if (status != HAL_OK || dev_id != 0xE5) {
return HAL_ERROR; // 设备未连接或ID错误
}
// 2. 配置电源控制寄存器(POWER_CTL):启动测量模式(bit3=1)
status = ADXL345_WriteReg(hi2c, POWER_CTL, 0x08); // 0x08=00001000(测量模式)
if (status != HAL_OK) return status;
// 3. 配置数据格式寄存器(DATA_FORMAT):±2g量程,全分辨率,右对齐
status = ADXL345_WriteReg(hi2c, DATA_FORMAT, 0x00); // 0x00=±2g,13位分辨率
if (status != HAL_OK) return status;
// 4. 配置带宽速率寄存器(BW_RATE):100Hz采样率(0x0A=100Hz)
status = ADXL345_WriteReg(hi2c, BW_RATE, 0x0A);
return status;
}
// ==================== 写单个寄存器 ====================
HAL_StatusTypeDef ADXL345_WriteReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t data) {
return HAL_I2C_Mem_Write(hi2c, ADXL345_ADDR, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 100);
}
// ==================== 读单个寄存器 ====================
HAL_StatusTypeDef ADXL345_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data) {
return HAL_I2C_Mem_Read(hi2c, ADXL345_ADDR, reg, I2C_MEMADD_SIZE_8BIT, data, 1, 100);
}
// ==================== 读多个寄存器(批量读取加速度数据) ====================
HAL_StatusTypeDef ADXL345_ReadRegs(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *buf, uint8_t len) {
return HAL_I2C_Mem_Read(hi2c, ADXL345_ADDR, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 100);
}
// ==================== 读取三轴加速度(转换为g单位) ====================
HAL_StatusTypeDef ADXL345_ReadAccel(I2C_HandleTypeDef *hi2c, float *ax, float *ay, float *az) {
uint8_t data[6];
int16_t raw_x, raw_y, raw_z;
HAL_StatusTypeDef status;
// 1. 读取6字节数据(X低8+X高8+Y低8+Y高8+Z低8+Z高8)
status = ADXL345_ReadRegs(hi2c, DATAX0, data, 6);
if (status != HAL_OK) return status;
// 2. 组合16位有符号整数(ADXL345数据右对齐,13位有效)
raw_x = (int16_t)((data[1] << 8) | data[0]); // X轴原始值
raw_y = (int16_t)((data[3] << 8) | data[2]); // Y轴原始值
raw_z = (int16_t)((data[5] << 8) | data[4]); // Z轴原始值
// 3. 转换为加速度(g):±2g量程时,灵敏度=3.9mg/LSB=0.0039g/LSB
*ax = raw_x * 0.0039f; // X轴加速度(g)
*ay = raw_y * 0.0039f; // Y轴加速度(g)
*az = raw_z * 0.0039f; // Z轴加速度(g)
return HAL_OK;
}
3.2.3 I2C初始化与主函数(CubeMX配置+示例)
CubeMX配置步骤:
- 启用I2C1(PB6=SCL,PB7=SDA),模式为I2C,速率100kHz(标准模式);
- 启用USART1(PA9=TX,PA10=RX),用于打印加速度数据(调试用);
- 生成代码(含HAL库初始化)。
主函数示例:
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "adxl345.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
int main(void) {
HAL_Init();
SystemClock_Config(); // 72MHz时钟配置
MX_I2C1_Init(); // I2C1初始化(100kHz)
MX_USART1_UART_Init(); // USART1初始化(115200bps)
// 初始化ADXL345
if (ADXL345_Init(&hi2c1) != HAL_OK) {
printf("ADXL345初始化失败!\r\n");
while (1);
}
printf("ADXL345初始化成功!\r\n");
float ax, ay, az;
while (1) {
// 读取三轴加速度
if (ADXL345_ReadAccel(&hi2c1, &ax, &ay, &az) == HAL_OK) {
printf("加速度:X=%.2fg, Y=%.2fg, Z=%.2fg\r\n", ax, ay, az);
} else {
printf("读取加速度失败!\r\n");
}
HAL_Delay(500); // 500ms刷新一次
}
}
// printf重定向到USART1(需实现fputc)
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);
return ch;
}
四、关键问题与解决方案
4.1 I2C通信失败
-
原因:引脚配置错误(如SCL/SDA接反)、地址错误(SDO引脚电平未确认)、时序不匹配(速率过高)。
-
解决:
- 用示波器测量SCL/SDA波形,确认ACK信号;
- 确认ADXL345地址(SDO接地时用0x53,左移1位后为0xA6);
- 降低I2C速率至100kHz(标准模式)。
4.2 加速度数据异常
-
原因:未初始化测量模式(POWER_CTL未设0x08)、量程配置错误(DATA_FORMAT设置不当)。
-
解决:
- 确保
ADXL345_Init中已写入POWER_CTL=0x08启动测量; - 若需±4g/±8g量程,修改
DATA_FORMAT寄存器(如±4g=0x01,±8g=0x02)。
- 确保
4.3 数据抖动
- 原因:传感器噪声或未滤波。
- 解决:软件添加滑动平均滤波(如连续采样5次取平均)。
参考代码 基于STM32单片机ADXL345加速度计IIC读写程序 www.youwenfan.com/contentcst/182726.html
五、测试与验证
- 硬件连接:按2.2节连接STM32与ADXL345,确保I2C引脚上拉电阻(4.7kΩ)已接;
- 功能测试:读取设备ID(0xE5),确认初始化成功;
- 数据验证:将传感器静止放置,Z轴加速度应≈1g(±0.1g),X/Y轴≈0g;倾斜传感器,观察加速度变化。
六、总结
基于STM32 HAL库实现了ADXL345的I2C驱动,核心是寄存器配置、I2C读写与数据转换。通过模块化设计,可扩展支持SPI接口、中断唤醒、自由落体检测等功能,适用于嵌入式运动监测场景。