您的位置:首页 > 其它

19-《电子入门趣谈》第三章_电子世界中的五官---传感器-3.2.4加速度传感器

2015-12-30 18:20 330 查看
3.2.4 加速度传感器

(1)加速度传感器简介

加速度检测是基于测试仪器检测质量敏感加速度产生惯性力的测量,是一种全自主的惯性测量,加速度检测广泛应用于航天、航空和航海的惯性导航系统及运载武器的制导系统中,在振动试验、地震监测、爆破工程、地基测量、地矿勘测等领域也有广泛的应用。

测量加速度,目前主要是通过加速度传感器(俗称加速度计),并配以适当的检测电路进行的,在(1~64)Hz的设备频率下典型的加速度测量范围为(0.1~10)g。。加速度传感器的种类繁多,依据对加速度计内检测质量所产生的惯性力的检测方式来分,加速度计可分为压电式、压阻式、应变式、电容式、振梁式、磁电感应式、隧道电流式、热电式等;按检测质量的支承方式来分,则可分为悬臂梁式、摆式、折叠梁式、简支承梁式等。多数加速度传感器是根据压电效应的原理来工作的,当输入加速度时,加速度通过质量块形成的惯性力加在压电材料上,压电材料产生的变形和由此产生的电荷与加速度成正比,输出电量经放大后就可检测出加速度大小。

加速度传感器是一种惯性传感器,一般由敏感元件、转换元件、测量电路三部分组成,可用如下框图表示:



下面举一个加速度传感器应用实例。我们选择的是ADXL345加速度传感器。ADXL345是一款小而薄的低功耗3轴加速度计,分辨率高(最高13位),测量范围达±16g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2C数字接口访问。ADXL345非常适合移动设备应用。它可以在倾斜检测应用中测量静态重力加速度,还可以测量运动或冲击导致的动态加速度。其高分辨率(4 mg/LSB),能够测量不到1.0°的倾斜角度变化。该器件提供多种特殊检测功能。活动和非活动检测功能检测有无运动发生,以及任意轴上的加速度是否超过用户设置的限值。敲击检测功能可以检测单击和双击动作。自由落体检测功能可以检测器件是否正在掉落。这些功能可以映射到两个中断输出引脚中的一个。正在申请专利的32级先进先出(FIFO)缓冲器可用于存储数据,最大程度地减少主机处理器的干预。低功耗模式支持基于运动的智能电源管理,从而以极低的功耗进行阈值感测和运动加速度测量。

ADXL345采用3 mm × 5 mm × 1 mm、14引脚小型超薄塑料封装。主要应用于手机、游戏设备、仪器仪表、个人导航设备中。

(2)ADXL345主要特点(来自数据手册):

用户可选的分辨率;

10位固定分辨率;

单击/双击检测;

活动/非活动监控;

嵌入式FIFO技术可最大程度地减少主机处理器的负荷;

全分辨率,分辨率随g范围提高而提高,±16 g时达到最高分辨率13位(在所有g范围内保持4 mg/LSB的比例系数)

超低功耗:VS = 2.5 V时(典型值),测量模式下低至40 μA,待机模式下为0.1 μA

功耗随带宽自动按比例变化;

(3)ADXL345引脚图、管脚说明、寄存器映射表格:



引脚说明:



寄存器映射表格:这就相当于命令代号,和上文中的DS18B20一样,想要对ADXL345进行操作就必须先往芯片里发指令,指令代码全都列在了下表中。比如我们想改变X轴的偏移量,只需将将指针直到芯片的0x1F位置,然后往里面写数就行了。当然,如何指定位置,如何写数这都是程序要做的事,该芯片支持SPI和I2C两种通信方式,它们之间的不同我们曾在第一章提过,无非是见面之后的口令不同,下面我们会用I2C方式进行单片机和芯片之间的通信。

这里我们更关心的几个“寄存器”是0X32~0X37,因为它们6个正是我们要取得的数据,分别是X轴数据0、X轴数据1、Y轴数据0、Y轴数据1、Z轴数据0、Z轴数据1。你可能会纳闷,一个方向的加速度值就一个就完了呗,为啥还分数据0和数据1呢?不用纠结这个,想想前面遇到的一些情况,比如定时器的TH和TL您应该就能理解了。



(4)ADXL345应用电路图:

下图是ADXL345加速度计利用I2C模式传数据的外围电路。SCL、SDA分别接到单片机的两个I/O口上,INT1和INT2两个中断输出也可以按需求接到单片机中断输入口上。



(5)参考程序(用途:ADXL345模块I2C测试程序)

下面这段程序的作用是将加速度计的输出值保存到BUF寄存器中。这里的I2C程序,使用软件模拟的,有的单片机本身集成了I2C功能,自然不用这么麻烦,不过如果您能用软件自己写出I2C的驱动来会显得更加的“高大上”,而且这些程序也可以直接用在其他I2C通信协议的器件上。关于I2C的时序(也就是口令了),查查别的资料看看就行,不是我们这些凡人需要太操心的东西。咋样?赶紧先收下吧!

#include  <reg52.h>

uchar  BUF[6]={0,0,0,0,0,0};

sbit SCL=P2^0; //I2C时钟引脚定义

sbit SDA=P2^1; //I2C数据引脚定义

#define SlaveAddress   0xA6   //定义器件在I2C总线中的从地址,根据ALT  ADDRESS地址引脚不同修改

void delayms(int ms);

void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据

uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据

void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据

//------------------------------------

void Init_ADXL345();

void ADXL345_Start();

void ADXL345_Stop();

void ADXL345_SendACK(bit ack);

bit  ADXL345_RecvACK();

void ADXL345_SendByte(uchar dat);

uchar ADXL345_RecvByte();

void ADXL345_ReadPage();

void ADXL345_WritePage();

//-----------------------------------

void main()

{

uchar devid;

delayms(500);                     //上电延时

Init_ADXL345();                  //初始化ADXL345

devid=Single_Read_ADXL345(0X00); //读出的数据为0XE5,表示正确

while(1)                          //循环

{

Multiple_Read_ADXL345();        //连续读出数据,存储在BUF中

delayms(1000);                     //延时

}

}

/**************************************

延时函数

**************************************/

void delayms(int ms)

{

int i,j;

for(i=0;i<ms;i++)

for(j=0;j<110;j++);

}

/**************************************

I2C起始信号

**************************************/

void ADXL345_Start()

{

uchar i;

SDA = 1;                    //拉高数据线

SCL = 1;                    //拉高时钟线

for(i=2;i>0;i--);           //延时   5us

SDA = 0;                    //产生下降沿

for(i=2;i>0;i--);           //延时   5us

SCL = 0;                    //拉低时钟线

}

/**************************************

I2C停止信号

**************************************/

void ADXL345_Stop()

{

uchar i;

SDA = 0;                    //拉低数据线

SCL = 1;                    //拉高时钟线

for(i=2;i>0;i--);           //延时   5us

SDA = 1;                    //产生上升沿

for(i=2;i>0;i--);           //延时   5us

}

/**************************************

I2C发送应答信号

入口参数:ack (0:ACK 1:NAK)

**************************************/

void ADXL345_SendACK(bit ack)

{

uchar i;

SDA = ack;                  //写应答信号

SCL = 1;                    //拉高时钟线

for(i=2;i>0;i--);           //延时   5us

SCL = 0;                    //拉低时钟线

for(i=2;i>0;i--);           //延时   5us

}

/**************************************

I2C接收应答信号

**************************************/

bit ADXL345_RecvACK()

{

uchar i;

SCL = 1;                    //拉高时钟线

for(i=2;i>0;i--);           //延时   5us

CY = SDA;                   //读应答信号

SCL = 0;                    //拉低时钟线

for(i=2;i>0;i--);           //延时   5us

return CY;

}

/**************************************

向I2C总线发送一个字节数据

**************************************/

void ADXL345_SendByte(uchar dat)

{

uchar i,j;

for (i=0; i<8; i++)         //8位计数器

{

dat <<= 1;              //移出数据的最高位

SDA = CY;               //送数据口

SCL = 1;                //拉高时钟线

for(j=2;j>0;j--);           //延时   5us

SCL = 0;                //拉低时钟线

for(j=2;j>0;j--);           //延时   5us

}

ADXL345_RecvACK();

}

/**************************************

从I2C总线接收一个字节数据

**************************************/

uchar ADXL345_RecvByte()

{

uchar i,j;

uchar dat = 0;

SDA = 1;                    //使能内部上拉,准备读取数据,

for (i=0; i<8; i++)         //8位计数器

{

dat <<= 1;

SCL = 1;                //拉高时钟线

for(j=2;j>0;j--);       //延时   5us

dat |= SDA;             //读数据

SCL = 0;                //拉低时钟线

for(j=2;j>0;j--);       //延时   5us

}

return dat;

}

//******I2C单字节写入*******************************************

void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)

{

ADXL345_Start();                  //起始信号

ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号

ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页

ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页

ADXL345_Stop();                   //发送停止信号

}

//********I2C单字节读取*****************************************

uchar Single_Read_ADXL345(uchar REG_Address)

{   uchar REG_data;

ADXL345_Start();                          //起始信号

ADXL345_SendByte(SlaveAddress);

ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始

ADXL345_Start();                          //起始信号

ADXL345_SendByte(SlaveAddress+1);

REG_data=ADXL345_RecvByte();              //读出寄存器数据

ADXL345_SendACK(1);

ADXL345_Stop();                           //停止信号

return REG_data;

}

//*********************************************************

//连续读出ADXL345内部加速度数据,地址范围0x32~0x37

//*********************************************************

void Multiple_read_ADXL345(void)

{   uchar i;

ADXL345_Start();                          //起始信号

ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号

ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始

ADXL345_Start();                          //起始信号

ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号

for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF

{

BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据

if (i == 5)

{

ADXL345_SendACK(1);                //最后一个数据需要回NOACK

}

else

{

ADXL345_SendACK(0);                //回应ACK

}

}

ADXL345_Stop();                          //停止信号

for(i=2;i>0;i--);           //延时5us

}

//*****************************************************************

//******初始化ADXL345,根据需要请参考数据手册进行修改**************

void Init_ADXL345()

{

Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式

Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页

Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页

Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断

Single_Write_ADXL345(0x1E,0x00);   //X 偏移量

Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量

Single_Write_ADXL345(0x20,0x05);   //Z 偏移量

}


未完待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: