基于STM32CubeMX ADXL345传感器经验分享

🏰 Microsoft365个人版 📅 2025-10-01 03:00:42 👤 admin 👁️ 985 👑 865
基于STM32CubeMX ADXL345传感器经验分享

1.ADXL345传感器简介

ADXL345是ADI公司推出的基于iMEMS技术的3轴、数字输出加速度传感器。该传感器有最高13位的分辨率、具有±2/4/8/16g可变的测量范围、能测量不到1.0°的倾斜角度变化等特点。ADXL345支持标准的I2C或SPI数字接口,自带32级FIFO存储,并且内部有多种状态检测和灵活的中断方式等特性,ADXL345的检测轴如下图示:

微信图片_20230628154408.png (11.27 KB, 下载次数: 17)

下载附件

保存到相册

2023-6-28 15:45 上传

当ADXL345沿检测轴正向加速时,它对正加速度进行检测。在检测重力时需要注意当检测轴的方向与重力的方向相反时检测到的是正加速度。下图列出了ADXL345在不同摆放方式时的输出对重力的影响:

微信图片_20230628154404.png (27.56 KB, 下载次数: 21)

下载附件

保存到相册

2023-6-28 15:45 上传

ADXL345支持SPI和I2C两种通讯方式,本例程采用的是I2C方式连接,官方推荐的I2C连接电路如下图示:从图中可以看出ADXL345的连接比较简单,外围器件只需要2个电容。若SDO/ALTADDRESS接地,则ADXL345的地址为0x53(不含最低位);若SDO/ALTADDRESS接高,则ADXL345的地址为0x1D(不含最低位);

微信图片_20230628154358.png (141.87 KB, 下载次数: 14)

下载附件

保存到相册

2023-6-28 15:45 上传

ADXL345的初始化步骤为:上电 --> 等待1.1ms --> 初始化命令序列 --> 结束,ADXL345正常工作;初始化序列最简单的只需要配置3个寄存器(如下图示),发送下图中的序列给ADXL345后,ADXL345即开始正常工作

微信图片_20230628154346.png (71.9 KB, 下载次数: 16)

下载附件

保存到相册

2023-6-28 15:45 上传

ADXL345寄存器地址映射表:

微信图片_20230628154343.png (135.24 KB, 下载次数: 13)

下载附件

保存到相册

2023-6-28 15:45 上传

2.硬件设计

D1指示灯用来提示系统运行状态,K_UP按键用来自动校准,TFTLCD模块用来显示传感器检测的三个方向加速度值和角度值

D1/D2指示灯

USART1串口

TFTLCD

ADXL345

K_UP按键

微信图片_20230628154339.png (158.12 KB, 下载次数: 12)

下载附件

保存到相册

2023-6-28 15:45 上传

从电路图中可以看到ADXL345芯片的ADDR地址线接在3.3V上,所以ADXL345的器件地址是:0x1D(不包含最低位),因此写入为:0x3A,读取为:0x3B

3.软件设计

3.1 STM32CubeMX设置

➡️ RCC设置外接HSE,时钟设置为72M

➡️ PC0/PC1设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

➡️ PA0/PA8设置为GPIO输入模式、下拉模式

➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

➡️ 激活I2C2,选择标准传输模式,选择7位寻址地址,其余默认设置

➡️ 激活FSMC,详细请参考TFTLCD显示章节的设置

➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM软件编程

➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程

➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程

➡️ 创建ADXL345芯片驱动文件adxl345.c和adxl345.h

/*ADXL345初始化函数:成功返回0,失败返回1*/

uint8_t ADXL345_Init(void){

uint8_t id,val;

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DEVICE_ID,I2C_MEMADD_SIZE_8BIT,&id,1,0xff);

if(id ==0XE5){ //读器件ID,ADXL345的器件ID为0XE5

val = 0x2B; //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,DATA_FORMAT,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x0A; //数据输出速度为100Hz

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,BW_RATE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x28; //链接使能,测量模式

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x00; //不使用中断

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,INT_ENABLE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

return 0;

}

return 1;

}

/*读取ADXL345三个轴的数据*/

void ADXL345_RD_XYZ(short *x,short *y,short *z){

uint8_t buf[6];

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_X0,I2C_MEMADD_SIZE_8BIT,&buf[0],1,0xFF);

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_X1,I2C_MEMADD_SIZE_8BIT,&buf[1],1,0xFF);

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Y0,I2C_MEMADD_SIZE_8BIT,&buf[2],1,0xFF);

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Y1,I2C_MEMADD_SIZE_8BIT,&buf[3],1,0xFF);

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Z0,I2C_MEMADD_SIZE_8BIT,&buf[4],1,0xFF);

HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Z1,I2C_MEMADD_SIZE_8BIT,&buf[5],1,0xFF);

*x=(short)(((uint16_t)buf[1]<<8)+buf[0]); //DATA_X1为高位有效字节

*y=(short)(((uint16_t)buf[3]<<8)+buf[2]); //DATA_Y1为高位有效字节

*z=(short)(((uint16_t)buf[5]<<8)+buf[4]); //DATA_Z1为高位有效字节

}

/*读取ADXL345的数据并做滤波处理,读times次再取平均值*/

void ADXL345_Read_Average(short *x,short *y,short *z,uint8_t times){

uint8_t i;

short tx,ty,tz;

*x=0; *y=0; *z=0;

if(times){

for(i=0;i

ADXL345_RD_XYZ(&tx,&ty,&tz);

*x+=tx; *y+=ty; *z+=tz;

HAL_Delay(5);

}

*x/=times; *y/=times; *z/=times;

}

}

/*ADXL345自动校准函数*/

void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval){

short tx,ty,tz;

uint8_t i, val;

short offx=0,offy=0,offz=0;

val = 0x00; //先进入休眠模式

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_Delay(100);

val = 0x2B; //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,DATA_FORMAT,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x0A; //数据输出速度为100Hz

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,BW_RATE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x28; //链接使能,测量模式

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

val = 0x00; //不使用中断

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,INT_ENABLE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);

HAL_Delay(12);

for(i=0;i<10;i++){

ADXL345_Read_Average(&tx,&ty,&tz,10);

offx+=tx; offy+=ty; offz+=tz;

}

offx/=10; offy/=10; offz/=10;

*xval=-offx/4;

*yval=-offy/4;

*zval=-(offz-256)/4;

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,(uint8_t *)xval,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,(uint8_t *)yval,1,0xFF);

HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,(uint8_t *)zval,1,0xFF);

}

/*计算ADXL345角度,x/y/表示各方向上的加速度分量,dir表示要获得的角度*/

short ADXL345_Get_Angle(float x,float y,float z,uint8_t dir){

float temp;

float res=0; //弧度值

switch(dir){

case 0: //0表示与Z轴的角度

temp=sqrt((x*x+y*y))/z;

res=atan(temp);

break;

case 1: //1表示与X轴的角度

temp=x/sqrt((y*y+z*z));

res=atan(temp);

break;

case 2: //2表示与Y轴的角度

temp=y/sqrt((x*x+z*z));

res=atan(temp);

break;

}

return res*180/3.14; //返回角度值

}

/*屏幕显示数字函数:x/y表示LCD显示的坐标位置*/

void ADXL_Show_num(uint16_t x,uint16_t y,short num,uint8_t mode){

uint8_t valbuf[3];

FRONT_COLOR=RED;

if(mode==0){ //mode为0,表示显示加速度值

if(num<0){ //num表示要显示的数据

num=-num;

LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"-");

}

else{

LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)" ");

}

valbuf[0]=num/100+0x30;

valbuf[1]=num%100/10+0x30;

valbuf[2]=num%100%10+0x30;

LCD_ShowString(x+10,y,tftlcd_data.width,tftlcd_data.height,16,valbuf);

}

else{ //mode为1,表示显示角度值

if(num<0){

num=-num;

LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"-");

}

else{

LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)" ");

}

valbuf[0]=num/10+0x30;

valbuf[1]='.';

valbuf[2]=num%10+0x30;

LCD_ShowString(x+10,y,tftlcd_data.width,tftlcd_data.height,16,valbuf);

}

}

/*数据处理函数*/

void data_pros(){

short x,y,z;

short xang,yang,zang;

uint8_t key;

ADXL345_Read_Average(&x,&y,&z,10);

ADXL_Show_num(60,120,x,0);

ADXL_Show_num(60,140,y,0);

ADXL_Show_num(60,160,z,0);

xang=ADXL345_Get_Angle(x,y,z,1);

yang=ADXL345_Get_Angle(x,y,z,2);

zang=ADXL345_Get_Angle(x,y,z,0);

ADXL_Show_num(60,180,xang,1);

ADXL_Show_num(60,200,yang,1);

ADXL_Show_num(60,220,zang,1);

key=KEY_Scan(0);

if(key==KEY_UP_PRES){ //按下KEY_UP启动校准

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);//LED2亮表示正在校准

ADXL345_AUTO_Adjust((char*)&x,(char*)&y,(char*)&z);

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); //LED2灭表示正校准完成

}

}复制代码

➡️ 在main.c文件下编写ADXL345测试代码

int main(void){

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_FSMC_Init();

MX_I2C2_Init();

MX_USART1_UART_Init();

/* USER CODE BEGIN 2 */

TFTLCD_Init();

FRONT_COLOR=BLACK;

LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ANDYXI STM32");

LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Test");

LCD_ShowString(10,90,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"K_UP:ADXL345 Adjust");

LCD_ShowString(10,120,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"X Val:");

LCD_ShowString(10,140,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Y Val:");

LCD_ShowString(10,160,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Z Val:");

LCD_ShowString(10,180,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"X Ang:");

LCD_ShowString(10,200,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Y Ang:");

LCD_ShowString(10,220,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Z Ang:");

FRONT_COLOR=GREEN;

while(ADXL345_Init()){

printf("ADXL345 Error!\r\n");

LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Checked failed!");

HAL_Delay(200);

}

printf("ADXL345 OK!\r\n");

LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Checked Success!");

/* USER CODE END 2 */

while (1){

data_pros();

HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);

HAL_Delay(200);

}

}复制代码

4.下载验证

编译无误下载到开发板后,可以看到D1指示灯不断闪烁,触摸屏显示三个轴的加速度值和角度值

微信图片_20230628154311.png (164.18 KB, 下载次数: 18)

下载附件

保存到相册

2023-6-28 15:45 上传

转载自: 嵌入式攻城狮

如有侵权请联系删除

皇家推荐

注会哪个培训机构好?上了一年,谈谈我的真实感受
如何掌握不同的系鞋带方法与技巧?
365bet手机在线投注

如何掌握不同的系鞋带方法与技巧?

📅 09-02 👁️ 5196
如何在 Windows 中以多种方式打开命令提示符 (CMD)
Microsoft365个人版

如何在 Windows 中以多种方式打开命令提示符 (CMD)

📅 07-20 👁️ 2807
冰岛世界杯大名单,冰岛世界杯球员介绍
365足球规则

冰岛世界杯大名单,冰岛世界杯球员介绍

📅 08-16 👁️ 8112
cf战队徽章在哪买-战队徽章设置与获取方式
Microsoft365个人版

cf战队徽章在哪买-战队徽章设置与获取方式

📅 09-26 👁️ 8028
Qt connect传参方式及lambda函数传参方式详解
Microsoft365个人版

Qt connect传参方式及lambda函数传参方式详解

📅 09-23 👁️ 9081