STM32 驱动 ADXL345 三轴加速度传感器 + OLED 显示教程

AgenticCoding·十二月创作之星挑战赛 10w+人浏览 334人参与

      本文将详细讲解如何使用 STM32 单片机驱动ADXL345 三轴加速度 / 倾斜角度传感器(I2C 接口),并将采集到的三轴加速度数据、实时倾斜角度(横滚角 / 俯仰角)显示在 0.96 寸 I2C OLED 屏幕上。教程采用STM32F103C8T6最小系统板,代码基于 HAL 库开发,步骤清晰、代码可直接复用,适合新手学习和项目开发(如倾角仪、平衡车、姿态检测等场景)。

一、硬件准备与原理说明

1. 硬件清单

器件数量备注
STM32F103C8T6 最小系统板1核心控制单元
ADXL345 传感器模块1三轴加速度 / 倾斜角度检测,I2C/SPI 接口
0.96 寸 I2C 接口 OLED 屏1分辨率 128*64,SSD1306 驱动
杜邦线若干电路连接
5V 电源 / USB 数据线1给开发板供电

2. 核心原理

(1)ADXL345 传感器核心特点与原理

ADXL345 是一款低功耗、高精度的三轴加速度传感器,可检测 X/Y/Z 三个轴的加速度值,并通过算法转换为倾斜角度(横滚角 Roll、俯仰角 Pitch),核心特点如下:

  • 通信接口:支持I2C(两线串行)和SPI(三线 / 四线)。
  • 测量范围:可配置 ±2g/±4g/±8g/±16g(默认 ±2g,适合倾斜角度检测)。
  • 数据输出:10 位数字量,加速度单位为mg(1g=9.8m/s²=1000mg)。
  • 地址配置:通过ADDR引脚配置 I2C 地址(默认 7 位地址为0x53,接 VCC 为0x1D)。

倾斜角度计算原理:当传感器静止时,加速度仅受重力影响(重力加速度 g),通过三轴加速度值的比例关系,利用反正切函数可计算出倾斜角度:

  • 横滚角(Roll):绕 X 轴旋转的角度,由 Y、Z 轴加速度计算:\(Roll = arctan(Y/\sqrt{X^2 + Z^2}) × (180/π)\)
  • 俯仰角(Pitch):绕 Y 轴旋转的角度,由 X、Z 轴加速度计算:\(Pitch = arctan(X/\sqrt{Y^2 + Z^2}) × (180/π)\)
(2)OLED 显示原理

0.96 寸 OLED 屏采用 SSD1306 驱动芯片,通过 I2C 接口与 STM32 通信。由于 ADXL345 和 OLED 均为 I2C 设备(地址不同),可共用 STM32 的同一个 I2C 外设,简化硬件接线。

二、硬件接线

1. ADXL345 引脚说明

ADXL345 模块的核心引脚(I2C 模式):

  • VCC:供电(3.3V,推荐,与 STM32 电平匹配)
  • GND:接地
  • SCL:I2C 时钟线
  • SDA:I2C 数据线
  • SDO:悬空 
  • CS:  悬空 
  • INT1/INT2:中断输出脚(本教程暂不使用,悬空)

2. 整体接线表(STM32F103C8T6)

连接 ADXL345 和 OLED,接线如下:

设备引脚STM32 引脚说明
ADXL345-VCC3.3V传感器供电
ADXL345-GNDGND共地
ADXL345-SCLPA11I2C1 时钟线
ADXL345-SDAPA12I2C1 数据线
ADXL345-SDO-悬空(暂不使用)
ADXL345-CS-悬空(暂不使用)
ADXL345-INT1/2-悬空(暂不使用)
OLED-VCC3.3V屏幕供电
OLED-GNDGND共地
OLED-SCLPB6I2C1 时钟线
OLED-SDAPB7I2C1 数据线

注意事项:

  1. 务必保证所有设备共地,否则 I2C 通信会失败。
  2. 若 OLED 为 5V 供电,需添加电平转换模块(如 PC817),避免 STM32 引脚被 5V 电压损坏。

三、软件准备

1. 开发环境

  • STM32CubeMX:用于配置 STM32 外设,自动生成初始化代码。
  • Keil MDK-ARM:用于编写、编译代码,下载程序到 STM32。
  • ST-Link 调试器(或 USB 转串口):用于程序下载与调试。

四、代码编写

1. 导入 OLED 驱动代码

0.96 寸 I2C OLED 的驱动基于 SSD1306 芯片,需导入成熟的驱动文件(网络上可下载通用版):

  1. 在 Keil 工程的Src目录下新建oled.cInc目录下新建oled.h
  2. 将 SSD1306 的 I2C 驱动代码复制到这两个文件中(核心功能:OLED 初始化、清屏、显示字符 / 字符串 / 数字)。

关键提示:OLED 的 I2C 地址默认是0x78(7 位地址左移一位为 0xF0),若屏幕无显示,可尝试修改为0x7A

2. 编写 ADXL345 驱动代码

新建adxl345.c(Src 目录)和adxl345.h(Inc 目录),实现 ADXL345 的 I2C 通信、加速度读取和角度计算功能。

(1)adxl345.c 文件代码(部分)
//连读读取几次取平均值函数
//times 取平均值的次数
void adxl345_read_average(float *x,float *y,float *z,uint8_t times)
{
	uint8_t i;
	short tx,ty,tz;
	*x=0;
	*y=0;
	*z=0;
	if(times)//读取次数不为0
	{
		for(i=0;i<times;i++)//连续读取times次
		{
			adxl345_read_data(&tx,&ty,&tz);
			*x+=tx;
			*y+=ty;
			*z+=tz;
			delay_ms(5);
		}
		*x/=times;
		*y/=times;
		*z/=times;
	}
}
void get_angle(float *x_angle,float *y_angle,float *z_angle)
{
    float ax,ay,az;
    adxl345_read_average(&ax,&ay,&az,10);
    *x_angle=atan(ax/sqrt((az*az+ay*ay)))*180/3.14;
    *y_angle=atan(ay/sqrt((ax*ax+az*az)))*180/3.14;
    *z_angle=atan(sqrt((ax*ax+ay*ay)/az))*180/3.14;
}
(2)adxl345.h文件代码
/**
 ****************************************************************************************************
 * @file        adxl345.h
 * @author      送外卖的工程师
 * @version     V1.0
 * @date        2025-12-14
 * @brief       三轴加速度传感器驱动代码
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:STM32F103C8T6
 *     CSDN:送外卖的工程师
 * 技术指导VX:wmz14026
 * 淘宝店铺:小马科技
 * 闲鱼店铺:送外卖的工程师
 *
 * 修改说明
 * V1.0.0.251214
 * 第一次发布
 * 注:长期接各种项目设计,提供仿真、实物、原理图、PCB、代码工程、后期指导、操作视频、
   说明文档、各种报告、后期指导等。
 ****************************************************************************************************
 */

#ifndef __ADXL345_H
#define __ADXL345_H
#include "main.h"


/***************根据自己需求更改****************/
//ADXL345引脚宏定义						

#define ADXL345_SCL_PORT  			GPIOA
#define ADXL345_SCL_PIN				GPIO_PIN_11
#define ADXL345_SCL_GPIO_CLK  	__HAL_RCC_GPIOA_CLK_ENABLE();
#define ADXL345_SDA_PORT  			GPIOA
#define ADXL345_SDA_PIN				GPIO_PIN_12
#define ADXL345_SDA_GPIO_CLK   	__HAL_RCC_GPIOA_CLK_ENABLE();

#define ADXL345_SDA_H           HAL_GPIO_WritePin(ADXL345_SDA_PORT,ADXL345_SDA_PIN, GPIO_PIN_SET);
#define ADXL345_SDA_L           HAL_GPIO_WritePin(ADXL345_SDA_PORT,ADXL345_SDA_PIN, GPIO_PIN_RESET);
#define ADXL345_SCL_H           HAL_GPIO_WritePin(ADXL345_SCL_PORT,ADXL345_SCL_PIN, GPIO_PIN_SET);
#define ADXL345_SCL_L           HAL_GPIO_WritePin(ADXL345_SCL_PORT,ADXL345_SCL_PIN, GPIO_PIN_RESET);


/*********************END**********************/

#define X_AXLE 0   //x轴
#define Y_AXLE 1   //y轴
#define Z_AXLE 2   //z轴

#define	slaveaddress   0xA6	  //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
//                              ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A

#define THRESH_TAP     0X1D	  //敲击中断阈值(用于正常敲击检测)
//                              16g模式中,62.5mg/Bit

#define OFSX           0X1E   //X轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define OFSY           0X1F   //Y轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define OFSZ           0X20   //Z轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define DUR            0x21   //敲击阈值时间   625uS/Bit
#define LATENT         0X22   //敲击事件到时间窗口的延迟时间,在此期间
//                              可检测第二次敲击时间  1.25mg/Bit
#define WINDOW         0X23   //敲击窗口,延迟时间满后的时间量,在此期间
//                              能开始进行第二次有效敲击  1.25mg/Bit
#define THRESH_ACT     0X24   //检测活动的阈值,活动事件的幅度与该寄存器
//                              的值进行比较  62.5mg/Bit
#define	THRESH_INACT   0X25   //检测静止的阈值,静止事件的幅度与该寄存器
//                              的值进行比较  62.5mg/Bit
#define TIME_INACT     0X26   //加速度时间量小于该寄存器的值表示静止 1S/Bit

#define ACT_INACT_CTL  0X27 
//Bit  7,3  ACT交流/直流[INACT交流/直流]:0选择直流耦合;1使能交流耦合 直流时将
//                                       当前加速度值直接与THRESH_ACT和THRESH_INACT
//                                       进行比较,确定检测到的是活动还是静止
//     6,2  ACT_X使能[INACT_X使能]:设置为1,使能X轴参与检测活动或静止;活动检测时,
//                                 所有轴为逻辑"或",有任意轴超过阈值时,活动功能触发
//                                 禁止检测时,所有轴为逻辑"与",只有当所有轴低于阈值
//                                 时,静止功能触发
//     5,1  ACT_Y使能[INACT_Y使能]:与X轴类似 
//     4,0  ACT_Z使能[INACT_Z使能]:与X轴类似
#define THRESH_FF      0X28   //阈值,用于自由落体检测,所有轴加速度与该寄存器值比较
//                              ,以确定是否发生自由落体 62.5mg/Bit,建议300mg与600mg之间
#define TIME_FF        0X29   //维持THRESH_FF阈值的最小时间,以生成自由落体中断 5mS/Bit

#define TAP_AXES       0X2A   
// Bit  7:4  0
//       3   抑制  两次敲击之间出现大于THRESH_TAP值得加速度,设置抑制会抑制双击检测
//       2   TAP_X使能  设置为1时,使能X轴进行敲击检测,0时排除该轴的敲击检测
//       1   TAP_Y使能  设置为1时,使能Y轴进行敲击检测,0时排除该轴的敲击检测
//       0   TAP_Z使能  设置为1时,使能Z轴进行敲击检测,0时排除该轴的敲击检测
#define ACT_TAP_STATUS 0X2B   /*只读寄存器*/
// Bit  7   0
//     6,2  ACT_X来源,TAP_X来源:表示涉及敲击或活动事件的第一轴,设置为1时,对应事件参与
//                              设置为0时,对应未参与.不会自动清零,新数据覆盖,中断清零前
//                              应读取该寄存器
//     5,1	ACT_Y来源,TAP_Y来源:与X相似
//     4,0	ACT_Z来源,TAP_Z来源:与X相似
//      3   休眠设置为1时,器件进入休眠状态
#define BW_RATE        0X2C  
// Bit  7:5   0
//       4	 LOW_POWER 低功耗位,0选择正常模式,1进入低功耗模式
//      3:0  速率位
#define POWER_CTL      0X2D
// Bit  7,6   0
//       5    链接   设置1时,延迟活动开始,直到检测到静止.检测到活动后,禁止检测开始,活动
//                   检测停止,设置时动态链接活动和静止交替检测;设置0时静止与活动同时检测
//       4    AUTO_SLEEP  设置1时自动休眠,检测出静止后,进行休眠模式,活动使能后被唤醒
//       3    测量   0待机 1测量模式
//       2	  休眠   0普通 1休眠
//      1,0	  唤醒(休眠模式下的读取频率) "00":8HZ  "01":4HZ  "10":2HZ  "11":1HZ
#define INT_ENABLE     0X2E  //中断使能配置
// Bit  7  DATA_READY
//      6  SINGLE_TAP
//      5  DOUBLE_TAP
//      4  Activity
//      3  Inactivity
//      2  FREE_FALL   自由落体中断
//      1  Watermark
//      0  Overrun
#define INT_MAP        0X2F   //中断映射 自读寄存器
//位与INT_ENABLE对应,,设置为0,该中断映射到INT1引脚;设置为1,该中断映射到INT2引脚
#define INT_SOURCE     0X30   //中断来源
//位与INT_ENABLE对应,1表示该功能触发
#define DATA_FORMAT    0X31
// Bit   7  SELF_TEST  设置1,自测力应用至传感器,造成输出数据转换;0时禁用自测力
//       6  SPI        1设置为3线SPI模式,0时设置4线SPI模式
//       5  INT_INVERT 0时中断高电平有效,1时低电平有效
//       4	0
//       3  FULL_RES   1时设置全分辨率模式,输出以4mg/Bit增加;0时为10位模式
//       2  Justify    1为左对齐模式;8为右对齐模式,并带有符号扩展
//      1:0 范围位     "00"±2g  "01"±4g  "10"±8g  "11"±16g
#define DATAX0         0X32
#define DATAX1         0X33  //与DATAX0组成x轴输出数据(二进制补码),DATAX1为高位,4mg/Bit
#define DATAY0         0X34
#define DATAY1         0X35  //与DATAY0组成Y轴输出数据(二进制补码),DATAY1为高位,4mg/Bit
#define DATAZ0         0X36
#define DATAZ1         0X37  //与DATAZ0组成Z轴输出数据(二进制补码),DATAZ1为高位,4mg/Bit
#define FIFO_CTL       0X38
// Bit  7,6  FIFO_MODE  "00" 旁路模式
//						"01" FIFO模式 可收集最多32个值,然后停止收集数据
//						"10" 流模式   FIFO保存最后32个数据值,FIFO满时,新数据覆盖最早数据(先进先出)
//						"11" 触发器   通过触发位触发,FIFO在触发事件前保存最后的数据样本,然后
//									  继续收集数据直到填满;填满后,不再收集新数据
//		 5   触发位     0链接触发器模式下的触发事件至INT1,1链接至INT2
//		 4:0 样本		功能取决于FIFO模式:FIFO模式时,指定触发水印中断需要的FIFO条目数
//                                         流模式时,指定触发水印中断需要的FIFO条目数
//                                         触发器模式:指定触发事件之前在FIFO缓冲区要保留的FIFO样本数
//                      样本位设置为0时,不管哪种FIFO模式,立即在INT_SOURCE寄存器设置水印状态位
#define FIFO_STATUS    0X39	  /*只读寄存器*/
// Bit   7   FIFO_TRIG  FIFO_TRIG为1时表示有触发事件发生 
//       6   0
//      5:0	 条目位 报告FIFO存储的数据值的数量

//#define slaveaddress 0XA6//write
#define regaddress 0XA7//read
#define DEVICE_ID 0X00

void ADXL345_IIC_SDA_Mode(uint8_t mode);//ADXL345引脚输出模式控制
void ADXL345_IIC_SDA_OUT(void);
void ADXL345_IIC_SDA_IN(void);
void ADXL345_IIC_Init(void);
void ADXL345_IIC_Start(void);
void ADXL345_IIC_Stop(void);
void ADXL345_IIC_Ack(void);
void ADXL345_IIC_NAck(void);
uint8_t ADXL345_IIC_Wait_Ack(void);
void ADXL345_IIC_Send_Byte(uint8_t txd);
uint8_t ADXL345_IIC_Read_Byte(uint8_t ack);

void ADXL345_Init(void);
uint8_t adxl345_read_reg(uint8_t addr);
void adxl345_write_reg(uint8_t addr,uint8_t val);
void adxl345_read_data(short *x,short *y,short *z);
void adxl345_read_average(float *x,float *y,float *z,uint8_t times);
void ADXL345_Start(void);
void ADXL345_Stop(void);
void get_angle(float *x_angle,float *y_angle,float *z_angle);
#endif

五、下载与测试

1. 编译代码

  1. 在 Keil 中点击Build(编译)或Rebuild(重新编译),确保代码无错误。
  2. 若出现undefined reference to sqrtatan2错误,检查是否添加了数学库(-lm)。
  3. 若出现浮点数相关错误,检查是否开启Use MicroLIB

2. 下载程序

  1. 将 ST-Link 调试器连接到 STM32 的 SWD 接口(SWDIO、SWCLK、GND)。
  2. 在 Keil 中点击Download(下载),将程序烧录到 STM32 中。

3. 测试效果

  1. 给 STM32 供电,OLED 屏幕会显示X轴、Y轴、Z轴。
  2. 缓慢倾斜 ADXL345 传感器(如绕 X 轴 / Y 轴旋转),观察 OLED 上值是否随倾斜角度实时变化。

x轴倾斜:

y轴倾斜:

z轴倾斜:

六、常见问题解决

1. OLED 屏幕无显示

  • 检查 OLED 的 VCC/GND 是否接对,确保 3.3V 供电正常。
  • 确认 OLED 的 I2C 地址是否为0x78(可改为0x7A重试)。
  • 检查 SCL/SDA 引脚是否接反(PB6=SCL,PB7=SDA)。

2. ADXL345 初始化失败(程序卡死)

  • 检查传感器的 VCC/GND 是否接对,确保 3.3V 供电。
  • 确认ADXL345_ADDR是否与硬件配置一致。
  • 检查 I2C 引脚是否虚焊或接反。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值