yanniwang

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

0
阅读(4651)

ADXL345是ADI公司生产的一款超低功耗3轴加速度计,广泛应用于手机、医疗仪器、游戏和定点设备、工业仪器仪表及个人导航设备领域,他的分辨率高达13位,测量范围达± 16g。数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2C数字接口访问。ADXL345非常适合移动设备应用。它可以在倾斜检测应用中测量静态重力加速度,还可以测量运动或冲击导致的动态加速度。其高分辨率(3.9mg/LSB),能够测量不到1.0°的倾斜角度变化。该器件提供多种特殊检测功能。活动和非活动检测功能通过比较任意轴上的加速度与用户设置的阈值来检测有无运动发生。敲击检测功能可以检测任意方向的单振和双振动作。自由落体检测功能可以检测器件是否正在掉落。这些功能可以独立映射到两个中断输出引脚中的一个。正在申请专利的集成式存储器管理系统采用一个32级先进先出(FIFO)缓冲器,可用于存储数据,从而将主机处理器负荷降至最低,并降低整体系统功耗。低功耗模式支持基于运动的智能电源管理,从而以极低的功耗进行阈值感测和运动加速度测量。ADXL345采用3 mm × 5 mm × 1 mm,14引脚小型超薄塑料封装。功能框图如下:

下面是它的引脚图

 

 

通信方式:可采用和SPI数字通信。上述两种情况下,ADXL345作为从机运行。CS引脚上拉至VDD I/O,I2C模式使能。CS引脚应始终上拉至VDD I/O或由外部控制器驱动,因为CS引脚无连接时,默认模式不存在。因此,如果没有采取这些措施,可能会导致该器件无法通信。SPI模式下,CS引脚由总线主机控制。SPI和I2C两种操作模式下,ADXL345写入期间,应忽略从ADXL345传输到主器件的数据。

 

 SPI通信程序如下:

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

 Author        : Neil Zhao - CAST

 Date          : Sep 25th, 2009

 File          : SPI.c

 Hardware      : ADuC7026 and ADXL345

 Description   : Use the GPIO to simulate the 4-Wire SPI Interface of ADXL345

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

#include	
#include	

void delay (signed int length)
{
	while (length >0)
    	length--;
}

//---------------------------------
//WriteToADXL345ViaSpi();
//---------------------------------
//Function that writes to the ADXL345 via the SPI port. It sends first the control
//word that includes the start address and then the data to write.
//--------------------------------------------------------------------------------
void WriteToADXL345ViaSpi(unsigned char RegisterAddress, unsigned char NumberofRegisters, unsigned char *RegisterData)
{
	unsigned	char	ControlValue = 0;
	unsigned	char	ValueToWrite = 0;
	signed		char	RegisterIndex = 0;
	unsigned	char	i = 0;

	//Create the 8-bit header
	ControlValue = RegisterAddress;

//	SET_SCL();
//	delay(1);	
	SET_CS();
	SET_SCL();
	delay(3);
	CLR_CS();	 //bring CS low
	delay(3);

	CLR_SCL();
	CLR_SDO();	 //set WRITE bit
	delay(3);
	SET_SCL();
	delay(3);
	ControlValue <<= 1;

	CLR_SCL();
	SET_SDO();	//set MB bit
	delay(3);
	SET_SCL();
	delay(3);
	ControlValue <<= 1;

	//Write out the control word
	for(i=0; i<6; i++)
	{
		CLR_SCL();
		if(0x80 == (ControlValue & 0x80))
		{
			SET_SDO();	  //Send one to SDO pin
		}
		else
		{
			CLR_SDO();	  //Send zero to SDO pin
		}
		delay(3);
		SET_SCL();
		delay(3);
		ControlValue <<= 1;	//Rotate data
	}

	//And then the data
	for (RegisterIndex=NumberofRegisters; RegisterIndex>0; RegisterIndex--)
	{
		ValueToWrite = *(RegisterData + RegisterIndex - 1);
		for (i=0; i<8; i++)
		{
			CLR_SCL();
			if(0x80 == (ValueToWrite & 0x80))
			{
				SET_SDO();	  //Send one to SDO pin
			}
			else
			{
				CLR_SDO();	  //Send zero to SDO pin
			}
			delay(3);
			SET_SCL();
			delay(3);
			ValueToWrite <<= 1;	//Rotate data
		}
	}
	SET_CS();	//bring CS high again
}

//---------------------------------
//ReadFromADXL345ViaSpi();
//---------------------------------
//Function that reads from the ADXL345 via the SPI port. It first send the control word
//that includes the start address and then 8 clocks for each register to read.
//--------------------------------------------------------------------------------
void ReadFromADXL345ViaSpi(unsigned char RegisterAddress, unsigned char NumberofRegisters, unsigned char *RegisterData)
{
	unsigned	char	ControlValue = 0;
	signed		char	RegisterIndex = 0;
	unsigned	char	ReceiveData = 0;
	unsigned	char	i = 0;
	unsigned	int		iTemp = 0;

	//Create the 8-bit header
	ControlValue = RegisterAddress;

//	SET_SCL();
//	delay(1);	
	SET_CS();
	SET_SCL();
	delay(3);
	CLR_CS();	 //bring CS low
	delay(3);

	CLR_SCL();
	SET_SDO();	 //set READ bit
	delay(3);
	SET_SCL();
	delay(3);
	ControlValue <<= 1;

	CLR_SCL();
	SET_SDO();	//set MB bit
	delay(3);
	SET_SCL();
	delay(3);
	ControlValue <<= 1;

	//Write out the control word
	for(i=0; i<6; i++)
	{
		CLR_SCL();
		if(0x80 == (ControlValue & 0x80))
		{
			SET_SDO();	  //Send one to SDO pin
		}
		else
		{
			CLR_SDO();	  //Send zero to SDO pin
		}
		delay(3);
		SET_SCL();
		delay(3);
		ControlValue <<= 1;	//Rotate data
	}

	//Read data in
	for (RegisterIndex=NumberofRegisters; RegisterIndex>0; RegisterIndex--)
	{
		for(i=0; i<8; i++)
		{
			CLR_SCL();
			ReceiveData <<= 1;		//Rotate data
			delay(3);
			SET_SCL();
			iTemp = GP1DAT;			//Read SDI of ADXL345
			if(0x00000020 == (iTemp & 0x00000020))			   //SDI  P1.5
			{
				ReceiveData |= 1;	
			}
			delay(2);
		}
		*(RegisterData + RegisterIndex - 1) = ReceiveData;
	}
	SET_CS();	//bring CS high again
}