0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ADXL345三轴数字加速度计的驱动设计与实现

CHANBAEK 来源:木南创智 作者:尹家军 2022-12-08 15:34 次阅读

移动设备的广泛应用增加对移动过程中各种参数检测需求。ADXL345三轴数字加速度计可以用来检测加速度、进而测量倾斜角度等。在这一篇中,我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现。

1 、功能概述

ADXL345是一款小而薄的超低功耗3轴加速度计,分辨率高(13位),测量范围达±16 g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2C数字接口访问。采用SPI通讯接口时,最大SPI时钟速度为5 MHz,时序方案按照时钟极性(CPOL)= 1、时钟相位(CPHA)= 1执行。采用I2C通讯接口时,ALT ADDRESS引脚处于高电平,器件的7位I2C地址是0x1D,随后为R / W位。这转化为0x3A写入,0x3B读取。通过ALT ADDRESS引脚(引脚12)接地,可以选择备用I2C地址0x53(随后为R / W位)。这转化为0xA6写入,0xA7读取。引脚定义及封装如下:

Dingtalk_20221206154648.jpg

ADXL345非常适合移动设备应用。它可以在倾斜检测应用中测量静态重力加速度,还可以测量运动或冲击导致的动态加速度。其高分辨率(3.9 mg/LSB),能够测量不到1.0°的倾斜角度变化。

该器件提供多种特殊检测功能。活动和非活动检测功能通过比较任意轴上的加速度与用户设置的阈值来检测有无运动发生。敲击检测功能可以检测任意方向的单振和双振动作。自由落体检测功能可以检测器件是否正在掉落。这些功能可以独立映射到两个中断输出引脚中的一个。正在申请专利的集成式存储器管理系统采用一个32级先进先出(FIFO)缓冲器,可用于存储数据,从而将主机处理器负荷降至最低,并降低整体系统功耗。

低功耗模式支持基于运动的智能电源管理,从而以极低的功耗进行阈值感测和运动加速度测量。

ADXL345是一款完整的3轴加速度测量系统,可选择的测量范围有±2 g,±4 g,±8 g或±16 g。既能测量运动或冲击导致的动态加速度,也能测量静止加速度,例如重力加速度,使得器件可作为倾斜传感器使用。

2 、驱动设计与实现

我们对ADXL345驱动设计与其它设备一样。我们先抽象对象类型并考虑对对象的初始化和操作。

2.1 、对象定义

基于对象的操作至少要包括3方面内容:对象的定义,对象的初值以及对象的操作。接下来我们就从这里个方面入手设计并实现ADXL345的驱动。

2.1.1 、抽象对象类型

对于ADXL345也同时支持SPI接口通讯和I2C接口通讯。所以我们在抽象ADXL345对象类型时将接口类型作为属性以区别不同的特性。在使用I2C时,设备有地址以区别不同的设备,所以我们将I2C设备地址也定义为属性。而使用SPI时,没有设备地址但有片选信号,我们将对片选的操作定义为对象的操作函数。

/*定义ADXL345三轴数据结构*/
typedef struct Adxl345Object {
       uint8_t devAddress;
       uint8_t devID;
       Adxl345PortTypeport;
       int16_t incidence_X;
       int16_t incidence_Y;
       int16_t incidence_Z;
      
       float incidence_Xf;
       float incidence_Yf;
       float incidence_Zf;
      
       void(*ReadBytes)(struct Adxl345Object *adxl,uint8_t regAdd,uint8_t *rData,uint16_t rSize);  //读ADXL345寄存器操作
       void(*WriteBytes)(struct Adxl345Object *adxl,uint8_t regAdd,uint8_t *wData,uint16_t wSize);//写ADXL345寄存器操作
       void(*ChipSelect)(Adxl345CSType en);    //使用SPI接口时,片选操作
       void(*Delayus)(volatile uint32_t nTime);     /*实现us延时操作*/
}Adxl345ObjectType;

2.1.2 、对象初始化函数

一个对象必须赋初值方可使用,所以我们还需要一个初始化函数来对对象初始化。初始化函数除了为对象属性赋初始值和给操作指定函数指针外,还需要检测参数的合法性以及对硬件设备做必要的配置。基于此我们设计ADXL345的初始化函数如下:

/*对ADXL345进行初始化配置*/
void Adxl345Initialization(Adxl345ObjectType*adxl,uint8_t devAdd,
                           Adxl345PortTypeport,
                           Adxl345ReadBytesTyperead,
                           Adxl345WriteBytesTypewrite,
                           Adxl345ChipSelectTypecs,
                           Adxl345DelayTypedelay)
{
       uint8_t devID=0;
       uint8_t setValue=0;
      
       if((adxl==NULL)||(read==NULL)||(write=NULL)||(delay==NULL))
       {
              return;
       }
      
       if(port==SPI)
       {
              if(cs==NULL)
              {
                     return;
              }
             
              adxl->ChipSelect=cs;
              adxl->devAddress=0x00;
       }
       else
       {
              if((devAdd==0xA6)||(devAdd==0x3A))
              {
                     adxl->devAddress=devAdd;
              }
              elseif((devAdd==0x53)||(devAdd==0x1D))
              {
                     adxl->devAddress=(devAdd<<1);
              }
              else
              {
                     adxl->devAddress=0x00;
              }
              adxl->ChipSelect=NULL;
       }
      
       adxl->port=port;
       adxl->devID=0xE5;
       adxl->incidence_X=0;
       adxl->incidence_Xf=0.0;
       adxl->incidence_Y=0;
       adxl->incidence_Yf=0.0;
       adxl->incidence_Z=0;
       adxl->incidence_Zf=0.0;
      
       adxl->ReadBytes=read;
       adxl->WriteBytes=write;
       adxl->Delayus=delay;
      
       /*读取设备ID,在每次操作前读一次*/
       devID=Adxl345ReadRegister(adxl,REG_DEVID);
       if(adxl->devID!=devID)
       {
              return;
       }
       adxl->Delayus(300);
 
       /*配置数据格式*/
       setValue = 0x2B;
       Adxl345WriteRegister(adxl,REG_DATA_FORMAT,setValue);
       adxl->Delayus(50);
   
       /*配置数据速率及功率模式*/
       setValue = 0x0A;
       Adxl345WriteRegister(adxl,REG_BW_RATE,setValue);
       adxl->Delayus(50);
   
       /*配置电源特性*/
       setValue = 0x28;
       Adxl345WriteRegister(adxl,REG_POWER_CTL,setValue);
       adxl->Delayus(50);
   
       /*配置中断使能*/
       setValue = 0;
       Adxl345WriteRegister(adxl,REG_INT_ENABLE,setValue);
       adxl->Delayus(50);
 
       /*配置X轴偏移*/
       Adxl345WriteRegister(adxl,REG_OFSX,setValue);
       adxl->Delayus(50);
 
       /*配置Y轴偏移*/
       Adxl345WriteRegister(adxl,REG_OFSY,setValue);
       adxl->Delayus(50);
 
       /*配置Z轴偏移*/
       Adxl345WriteRegister(adxl,REG_OFSZ,setValue);
       adxl->Delayus(500);
}

2.2 、对象操作

我们定义一个对象的目的是操作这个对象,这也是驱动程序的主要内容。接下来我们就来实现对ADXL345对象的操作函数。

2.2.1 、写数据操作

对ADXL345对象的写操作因为使用的接口不同其数据帧格式也会有不同。使用SPI接口时,其数据帧格式如下:

Dingtalk_20221206154648.jpg

而使用I2C接口时,可以同时写多个寄存器,其数据帧格式如下:

Dingtalk_20221206154648.jpg

根据上述的数据帧格式和时序图我们可以编写写ADXL345的寄存器函数:

/* 写ADXL345的寄存器 */
static voidAdxl345WriteRegister(Adxl345ObjectType *adxl,uint8_t regAdd,uint8_t wData)
{     
       if(adxl->port==SPI)
       {
              adxl->ChipSelect(ADXL345CS_Enable);
              adxl->Delayus(50);
              adxl->WriteBytes(adxl,regAdd,&wData,1);
              adxl->Delayus(50);
              adxl->ChipSelect(ADXL345CS_Disable);
       }
       else
       {
              adxl->WriteBytes(adxl,regAdd,&wData,1);
       }
}

2.2.2 、读数据操作

对ADXL345对象的读操作也同样在使用不同的接口时拥有不同的数据帧结构。使用SPI接口时,其数据帧格式如下:

Dingtalk_20221206154648.jpg

而在使用I2C接口时,可以实现一个或多个寄存器的读操作,其数据帧格式如下:

Dingtalk_20221206154648.jpg

根据以上的数据帧格式和时序图我们可以开发读取ADXL345的寄存器操作函数:

/* 读取ADXL345的寄存器 */
static uint8_tAdxl345ReadRegister(Adxl345ObjectType *adxl,uint8_t regAdd)
{
       uint8_t regValue=0;
      
       if(adxl->port==SPI)
       {
              adxl->ChipSelect(ADXL345CS_Enable);
              adxl->Delayus(50);
              adxl->ReadBytes(adxl,regAdd,®Value,1);
              adxl->Delayus(50);
              adxl->ChipSelect(ADXL345CS_Disable);
       }
       else
       {
              adxl->ReadBytes(adxl,regAdd,®Value,1);
       }
      
       returnregValue;
}

2.2.3 、测量数据输出

我们操作ADXL345对象的目的当然是获取我们想要的数据。最基本的,我们开发从ADXL345获取3个坐标数据。

/*读取数据值,分辨率(3.9 mg/LSB)*/
voidGetValueFromAdxl345(Adxl345ObjectType *adxl)
{
 uint8_t devID = 0;
 uint8_t dataTemp[6];
 
 /*读取设备ID,在每次操作前读一次*/
 devID=Adxl345ReadRegister(adxl,REG_DEVID);
 if(adxl->devID!=devID)
 {
    return;
 }
 adxl->Delayus(200);
 
 /*读取三轴数据值*/
 Adxl345ReadMultiReg(adxl,REG_DATAX0,dataTemp,6);
 
 /*数据解析*/
 adxl->incidence_X = (int16_t)(dataTemp[0] + ((uint16_t)dataTemp[1]<< 8));
 adxl->incidence_Y = (int16_t)(dataTemp[2] + ((uint16_t)dataTemp[3]<< 8));
 adxl->incidence_Z = (int16_t)(dataTemp[4] + ((uint16_t)dataTemp[5]<< 8));
      
 adxl->incidence_Xf = (float)(adxl->incidence_X * 0.0039);
 adxl->incidence_Yf = (float)(adxl->incidence_Y * 0.0039);
 adxl->incidence_Zf = (float)(adxl->incidence_Z * 0.0039);
}

3 、驱动的使用

完成了驱动的设计开发,我们还要使用驱动实现ADXL345的应用。与其它外设一样,我们也按照实际项目的使用流程来验证之。

3.1 、声明并初始化对象

首先我们使用前面定义的Adxl345ObjectType类型声明一个ADXL345对象变量。如:Adxl345ObjectType adxl345;

声明对象变量后还需要调用Adxl345Initialization初始化函数对ADXL345对象变量进行初始化。当然在调用初始化函数前需要考虑传入的参数。特别是几个函数指针需要实现响应的函数。需要实现的函数类型如下:

typedef void(*Adxl345ReadBytesType)(struct Adxl345Object *adxl,uint8_t regAdd,uint8_t *rData,uint16_t rSize); //读ADXL345寄存器操作

typedef void(*Adxl345WriteBytesType)(struct Adxl345Object *adxl,uint8_t regAdd,uint8_t *wData,uint16_t wSize);//写ADXL345寄存器操作

typedef void(*Adxl345ChipSelectType)(Adxl345CSType en); //使用SPI接口时,片选操作

typedef void(*Adxl345DelayType)(volatile uint32_t nTime); / 实现us延时操作 /

定义这几个函数后,就可以将器函数指针作为实参传递给初始化函数。调用如下:

Adxl345Initialization(&adxl345,devAdd,port,read,write,cs,delay);

其中adxl345为需要初始化的ADXL345对象。devAdd为使用I2C通讯时的设备地址,使用SPI时无用。port为通讯端口的类型,SPI或者I2C。read读操作函数指针,是对硬件层的封装。write为写操作函数指针,是对硬件层的封装。cs为使用SPI接口时,片选操作函数指针。delay为延时函数的指针。

3.2 、基于对象进行操作

对象初始化完成后就可进行相应的操作。ADXL345的操作比较简单就是调用GetValueFromAdxl345函数获取我们需要的数据。具体的调用样式如下:

GetValueFromAdxl345(&adxl345);

这个使用比较简单,因为我们在初始化时将数据格式、数据速率及功率模式、电源特性、中断使能、各轴的数据偏移量等都按我们的需要在初始化时作了配置。如果需要不同配置则需要做相应的修改。

4 、应用总结

在我们的应用中,我们将其设置为全分辨率,±16g的测量范围,读取数据与预期一致。

使用I2C接口时,设备地址使用7位输入或8位输入都没问题,地址一共有4种可能。其他的都为非法地址,在地址输入不符合要求时,会被默认初始化为广播地址。

在使用SPI接口时,如果是通过软件操作片选信号则需要实现操作函数并将函数指针传递给初始化函数。如果硬件上采取永久选中的形式则可将NULL作为参数传入。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 加速度计
    +关注

    关注

    6

    文章

    696

    浏览量

    45840
  • 驱动设计
    +关注

    关注

    1

    文章

    110

    浏览量

    15261
  • ADXL345
    +关注

    关注

    13

    文章

    69

    浏览量

    33795
收藏 人收藏

    评论

    相关推荐

    Accessory Shield学习6:加速度计ADXL345

    本章我们讲一个具有运动风的技能——加速度计,这货能干啥?典型的就是测量加速度值、获取当前的空间姿态......原理大放送:主角ADXL345
    发表于 03-28 14:52

    ADXL354/355与ADXL345都是加速度计,请问都可以测倾角吗?

    我想请问一下ADXL354/355与ADXL345都是加速度计345可以测两个倾角,想请问
    发表于 08-02 06:22

    ADXL345:3,±2g数字加速度计

    ADXL345是一款小而薄的超低功耗3加速度计,分辨率高(13位),测量范围达&#177; 16g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2C
    发表于 11-27 16:58 210次下载
    <b class='flag-5'>ADXL345</b>:3<b class='flag-5'>轴</b>,±2g<b class='flag-5'>数字</b><b class='flag-5'>加速度计</b>

    ADXL345快速入门指南

    ADXL345加速度计。检测如图1所示。当ADXL345沿检测
    发表于 11-25 00:40 521次下载
    <b class='flag-5'>ADXL345</b>快速入门指南

    基于3加速度计ADXL345的跌倒检测应用

    基于3加速度计ADXL345的跌倒检测应用 ADXL345是ADI公司的
    发表于 11-28 15:20 359次下载
    基于3<b class='flag-5'>轴</b><b class='flag-5'>加速度计</b><b class='flag-5'>ADXL345</b>的跌倒检测应用

    利用精密模拟微控制器ADuC7024和数字加速度计ADXL345检测低g加速度

    ADXL345是一款小巧纤薄的低功耗加速度计,可以对高达16 g的加速度进行高分辨率(13位)测量。
    发表于 02-01 15:52 127次下载
    利用精密模拟微控制器ADuC7024和<b class='flag-5'>数字</b><b class='flag-5'>加速度计</b><b class='flag-5'>ADXL345</b>检测低g<b class='flag-5'>加速度</b>

    ADI公司MEMS加速度计ADXL345简介与例程

    ADI公司MEMS加速度计ADXL345简介与例程
    发表于 12-29 10:36 0次下载

    ADXL345 MEMS加速度计开发板的设置和使用方法

    ADXL345 MEMS加速度计开发板。由ADI公司的Nitzan Gadish说明如何设置和使用ADXL345开发板。该板能够捕捉3在时间上的数据,并以excel表格和图形的方式显
    的头像 发表于 07-16 06:06 4932次阅读

    GY-291 ADXL345数字重力加速度倾斜度模块的资料合集免费下载

    程序,ADXL345 AVR单片机通信程序),ADXL345数字加速度计中英文数据手册,ADXL345
    发表于 04-23 08:00 34次下载
    GY-291 <b class='flag-5'>ADXL345</b><b class='flag-5'>数字</b><b class='flag-5'>三</b><b class='flag-5'>轴</b>重力<b class='flag-5'>加速度</b>倾斜度模块的资料合集免费下载

    ADXL345超低功耗3数字加速度计的中文数据手册免费下载

    ADXL345是一款小而薄的超低功耗3加速度计,分辨率高(13位),测量范围达± 16g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2 C
    发表于 04-22 08:00 13次下载
    <b class='flag-5'>ADXL345</b>超低功耗3<b class='flag-5'>轴</b><b class='flag-5'>数字</b><b class='flag-5'>加速度计</b>的中文数据手册免费下载

    ADXL345数字加速度计的数据手册免费下载

    ADXL345是一款小而薄的超低功耗3加速度计,分辨率高(13位),测量范围达± 16g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2 C
    发表于 05-18 08:00 23次下载
    <b class='flag-5'>ADXL345</b><b class='flag-5'>数字</b><b class='flag-5'>加速度计</b>的数据手册免费下载

    ADXL362输入数字加速度计Linux驱动程序

    ADXL362输入数字加速度计Linux驱动程序
    发表于 04-21 09:59 12次下载
    <b class='flag-5'>ADXL</b>362输入<b class='flag-5'>三</b><b class='flag-5'>轴</b><b class='flag-5'>数字</b><b class='flag-5'>加速度计</b>Linux<b class='flag-5'>驱动</b>程序

    ADXL345加速度计与Arduino UNO连接的方法

    在这里,我们讨论的是ADXL345 加速度计,它用于测量 x、y 和 z 加速度速度变化。这些小型传感器用于汽车和自行车以检测事故以展
    的头像 发表于 08-18 17:15 4815次阅读
    将<b class='flag-5'>ADXL345</b><b class='flag-5'>加速度计</b>与Arduino UNO连接的方法

    ADXL345加速度计屏幕方向开源

    电子发烧友网站提供《ADXL345加速度计屏幕方向开源.zip》资料免费下载
    发表于 11-01 11:38 0次下载
    <b class='flag-5'>ADXL345</b><b class='flag-5'>加速度计</b>屏幕方向开源

    ADXL345超低功耗3加速度计应用

    电子发烧友网站提供《ADXL345超低功耗3加速度计应用.pdf》资料免费下载
    发表于 10-20 16:57 3次下载
    <b class='flag-5'>ADXL345</b>超低功耗3<b class='flag-5'>轴</b><b class='flag-5'>加速度计</b>应用