你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32CubeMX ADXL345传感器经验分享

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

微信图片_20230628154408.png

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


微信图片_20230628154404.png


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


微信图片_20230628154358.png

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

微信图片_20230628154346.png

ADXL345寄存器地址映射表:

微信图片_20230628154343.png


2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来自动校准,TFTLCD模块用来显示传感器检测的三个方向加速度值和角度值
D1/D2指示灯
USART1串口
TFTLCD
ADXL345
K_UP按键


微信图片_20230628154339.png

从电路图中可以看到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

  1. /*ADXL345初始化函数:成功返回0,失败返回1*/
  2. uint8_t ADXL345_Init(void){                                  
  3.   uint8_t id,val;
  4.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DEVICE_ID,I2C_MEMADD_SIZE_8BIT,&id,1,0xff);       
  5.   if(id ==0XE5){          //读器件ID,ADXL345的器件ID为0XE5
  6.     val = 0x2B;                //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
  7.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,DATA_FORMAT,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  8.     val = 0x0A;                //数据输出速度为100Hz
  9.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,BW_RATE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  10.     val = 0x28;                //链接使能,测量模式
  11.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  12.     val = 0x00;                //不使用中断
  13.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,INT_ENABLE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  14.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  15.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  16.     HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  17.     return 0;
  18.   }                       
  19.   return 1;                                                                             
  20. }
  21. /*读取ADXL345三个轴的数据*/
  22. void ADXL345_RD_XYZ(short *x,short *y,short *z){
  23.   uint8_t buf[6];                                                                    
  24.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_X0,I2C_MEMADD_SIZE_8BIT,&buf[0],1,0xFF);
  25.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_X1,I2C_MEMADD_SIZE_8BIT,&buf[1],1,0xFF);
  26.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Y0,I2C_MEMADD_SIZE_8BIT,&buf[2],1,0xFF);
  27.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Y1,I2C_MEMADD_SIZE_8BIT,&buf[3],1,0xFF);
  28.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Z0,I2C_MEMADD_SIZE_8BIT,&buf[4],1,0xFF);
  29.   HAL_I2C_Mem_Read(&hi2c2,ADXL_READ,DATA_Z1,I2C_MEMADD_SIZE_8BIT,&buf[5],1,0xFF);       
  30.   *x=(short)(((uint16_t)buf[1]<<8)+buf[0]);         //DATA_X1为高位有效字节   
  31.   *y=(short)(((uint16_t)buf[3]<<8)+buf[2]);         //DATA_Y1为高位有效字节              
  32.   *z=(short)(((uint16_t)buf[5]<<8)+buf[4]);         //DATA_Z1为高位有效字节            
  33. }
  34. /*读取ADXL345的数据并做滤波处理,读times次再取平均值*/
  35. void ADXL345_Read_Average(short *x,short *y,short *z,uint8_t times){
  36.   uint8_t i;
  37.   short tx,ty,tz;
  38.   *x=0; *y=0; *z=0;
  39.   if(times){
  40.     for(i=0;i<times;i++){
  41.       ADXL345_RD_XYZ(&tx,&ty,&tz);
  42.       *x+=tx;        *y+=ty;        *z+=tz;
  43.       HAL_Delay(5);
  44.     }
  45.     *x/=times; *y/=times; *z/=times;
  46.   }
  47. }   
  48. /*ADXL345自动校准函数*/
  49. void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval){
  50.   short tx,ty,tz;
  51.   uint8_t i, val;
  52.   short offx=0,offy=0,offz=0;
  53.   val = 0x00;                //先进入休眠模式
  54.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  55.   HAL_Delay(100);
  56.   val = 0x2B;                //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
  57.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,DATA_FORMAT,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);       
  58.   val = 0x0A;                //数据输出速度为100Hz
  59.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,BW_RATE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  60.   val = 0x28;                //链接使能,测量模式
  61.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,POWER_CTL,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  62.   val = 0x00;                //不使用中断
  63.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,INT_ENABLE,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  64.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  65.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  66.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,&val,1,0xFF);
  67.   HAL_Delay(12);
  68.   for(i=0;i<10;i++){
  69.     ADXL345_Read_Average(&tx,&ty,&tz,10);
  70.     offx+=tx; offy+=ty; offz+=tz;
  71.   }                        
  72.   offx/=10; offy/=10; offz/=10;
  73.   *xval=-offx/4;
  74.   *yval=-offy/4;
  75.   *zval=-(offz-256)/4;
  76.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSX,I2C_MEMADD_SIZE_8BIT,(uint8_t *)xval,1,0xFF);
  77.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSY,I2C_MEMADD_SIZE_8BIT,(uint8_t *)yval,1,0xFF);
  78.   HAL_I2C_Mem_Write(&hi2c2,ADXL_WRITE,OFSZ,I2C_MEMADD_SIZE_8BIT,(uint8_t *)zval,1,0xFF);       
  79. }
  80. /*计算ADXL345角度,x/y/表示各方向上的加速度分量,dir表示要获得的角度*/
  81. short ADXL345_Get_Angle(float x,float y,float z,uint8_t dir){
  82.   float temp;
  83.   float res=0;        //弧度值
  84.   switch(dir){
  85.     case 0:        //0表示与Z轴的角度
  86.      temp=sqrt((x*x+y*y))/z;
  87.      res=atan(temp);
  88.      break;
  89.     case 1:        //1表示与X轴的角度
  90.      temp=x/sqrt((y*y+z*z));
  91.      res=atan(temp);
  92.      break;
  93.     case 2:        //2表示与Y轴的角度
  94.      temp=y/sqrt((x*x+z*z));
  95.      res=atan(temp);
  96.      break;
  97.   }
  98.   return res*180/3.14;        //返回角度值
  99. }
  100. /*屏幕显示数字函数:x/y表示LCD显示的坐标位置*/
  101. void ADXL_Show_num(uint16_t x,uint16_t y,short num,uint8_t mode){
  102.   uint8_t valbuf[3];
  103.   FRONT_COLOR=RED;
  104.        
  105.   if(mode==0){        //mode为0,表示显示加速度值
  106.     if(num<0){        //num表示要显示的数据
  107.       num=-num;
  108.       LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"-");
  109.     }
  110.     else{
  111.       LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)" ");
  112.     }
  113.     valbuf[0]=num/100+0x30;
  114.     valbuf[1]=num%100/10+0x30;
  115.     valbuf[2]=num%100%10+0x30;       
  116.     LCD_ShowString(x+10,y,tftlcd_data.width,tftlcd_data.height,16,valbuf);       
  117.   }
  118.   else{        //mode为1,表示显示角度值
  119.     if(num<0){
  120.       num=-num;
  121.       LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"-");
  122.     }
  123.     else{
  124.       LCD_ShowString(x,y,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)" ");
  125.     }
  126.        
  127.     valbuf[0]=num/10+0x30;
  128.     valbuf[1]='.';
  129.     valbuf[2]=num%10+0x30;       
  130.     LCD_ShowString(x+10,y,tftlcd_data.width,tftlcd_data.height,16,valbuf);               
  131.   }               
  132. }
  133. /*数据处理函数*/
  134. void data_pros(){
  135.   short x,y,z;
  136.   short xang,yang,zang;       
  137.   uint8_t key;
  138.   ADXL345_Read_Average(&x,&y,&z,10);
  139.   ADXL_Show_num(60,120,x,0);
  140.   ADXL_Show_num(60,140,y,0);
  141.   ADXL_Show_num(60,160,z,0);
  142.   xang=ADXL345_Get_Angle(x,y,z,1);
  143.   yang=ADXL345_Get_Angle(x,y,z,2);
  144.   zang=ADXL345_Get_Angle(x,y,z,0);
  145.   ADXL_Show_num(60,180,xang,1);
  146.   ADXL_Show_num(60,200,yang,1);
  147.   ADXL_Show_num(60,220,zang,1);

  148.   key=KEY_Scan(0);
  149.   if(key==KEY_UP_PRES){        //按下KEY_UP启动校准
  150.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);//LED2亮表示正在校准               
  151.     ADXL345_AUTO_Adjust((char*)&x,(char*)&y,(char*)&z);
  152.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);        //LED2灭表示正校准完成                  
  153.   }
  154. }
复制代码

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

  1. int main(void){
  2.   HAL_Init();
  3.   SystemClock_Config();
  4.   MX_GPIO_Init();
  5.   MX_FSMC_Init();
  6.   MX_I2C2_Init();
  7.   MX_USART1_UART_Init();
  8.   /* USER CODE BEGIN 2 */
  9.   TFTLCD_Init();
  10.   FRONT_COLOR=BLACK;
  11.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ANDYXI STM32");
  12.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Test");
  13.   LCD_ShowString(10,90,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"K_UP:ADXL345 Adjust");
  14.   LCD_ShowString(10,120,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"X Val:");
  15.   LCD_ShowString(10,140,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Y Val:");
  16.   LCD_ShowString(10,160,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Z Val:");
  17.   LCD_ShowString(10,180,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"X Ang:");
  18.   LCD_ShowString(10,200,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Y Ang:");
  19.   LCD_ShowString(10,220,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"Z Ang:");
  20.        
  21.   FRONT_COLOR=GREEN;       
  22.   while(ADXL345_Init()){
  23.     printf("ADXL345 Error!\r\n");
  24.     LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Checked failed!");
  25.     HAL_Delay(200);
  26.   }
  27.   printf("ADXL345 OK!\r\n");
  28.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"ADXL345 Checked Success!");
  29.   /* USER CODE END 2 */
  30.   while (1){
  31.     data_pros();
  32.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
  33.     HAL_Delay(200);
  34.   }
  35. }
复制代码

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

微信图片_20230628154311.png

转载自: 嵌入式攻城狮
如有侵权请联系删除


收藏 评论0 发布时间:2023-6-28 15:44

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版