STM32应用-第4节-震动传感器ADXL345

ADXL345传感器详解

硬件设计

ADXL345硬件原理图设计如下:

SPI接口或者I2C接口选择

当CS上拉时,设置为I2C接口。当CS未有上拉时,设置为SPI接口

STM32应用-第4节-震动传感器ADXL345_第1张图片

具体设置可以参考Datasheet

STM32应用-第4节-震动传感器ADXL345_第2张图片

自由落体

中断源为0X87

Activity检测

Activity检测可以用来检测传感器是否被触碰,或者处于活动状态。Inactivity用来检测传感器是否处于非活动状态。

Link位:当设置了Link位后,Activity和Inactivity交互进行。如果不设置Link位,而设备一直处静止状态,则将一直触发Inactivity中断。

传感器校准

ADXL345需要通过放在绝对水平的位置,进行校准。设计到校准的寄存器如下包括校准寄存器(0X1E,0X1F,0X20)。校准寄存器比例因子为15.6mg/LSB,也就是说0X7F代表2G;这个寄存器的数值会自动加到加速度值中。

加速度传感器内含MEMS机械结构,这个器件组装到PCB上之后,由于安装等各种原因,可能导致并非绝对精准,从而需要进行数据校准。通常校准时,Z轴为1G, X,Y为0G。校准时,通常采用默认的100Hz采样率连续采样10个样板(也就是对应于0.1秒采样时间),测量的值为X,Y,Z的偏移量,分别对应X,Y在0G, Z在1G的情况。

所以X,Y,Z对应实际值为:

注意:这里Z轴采样值,需要减去255,才是对应的Z0g的值,具体在下面例子中查看。

设置了偏移寄存器的好处是:输出数据将自动加上偏移寄存器的数值。

偏移寄存器的数值是用加法 计算的。因此,如果水平位置原始值为负值,则偏移寄存器数值为正,如果水平位置原始值为正,则偏移寄存器数值为负(用反码表示,反码中0XFF表示-1)

例如:水平放置时,X读数-5,y读数2, Z读数270;这时,正常值应该是0,0,255,因此需要把偏移量设置为5, -2, -15。但是这里注意了,ADXL345默认13位分辨率,16G量程时,1 LSB为1/256 = 3.9mg/LSB。

由于偏移寄存器为15.6mg/LSB,所以偏移寄存器写1个LSB,相当于偏移了4个LSB,所以偏移寄存器的值,需要除以4。例如,上面偏移量为4,则偏移寄存器写4/1 = 1即可。

所以实际偏移量应该为5/4=1, -2/4=0, -15/4=-4, 其中负数用反码表示,所以为1, 0 , FC, 分别写入off_x, off_y和off_z即可。

通过上述校准方式,可以设计自校准模式如下:

// 自动校准
// xval,yval,zval:x,y,z轴的校准值
void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)
{
	u8 i, powerCtl, dataFormat, bwRate, intEnable;
	ACCELEROMETER acc;
	short offx=0,offy=0,offz=0;
	
	assert_param(xval);
	assert_param(yval);
	assert_param(zval);
	
	// 先保存将被改写的寄存器内容
	ADXL345_RD_Reg(POWER_CTL, &powerCtl, 1);
	ADXL345_RD_Reg(DATA_FORMAT, &dataFormat, 1);
	ADXL345_RD_Reg(BW_RATE, &bwRate, 1);
	ADXL345_RD_Reg(INT_ENABLE, &intEnable, 1);
	
	// 先将ADXL设置为休眠状态
	ADXL345_WR_Reg(POWER_CTL,0x00);
	delay_ms(100);
	
	// 初始化为100Hz 16G量程
	ADXL345_WR_Reg(DATA_FORMAT,0X2B);	
	ADXL345_WR_Reg(BW_RATE,0x0A);
	ADXL345_WR_Reg(POWER_CTL,0x28);
	ADXL345_WR_Reg(INT_ENABLE,0x00);
	ADXL345_WR_Reg(OFSX,0x00);
	ADXL345_WR_Reg(OFSY,0x00);
	ADXL345_WR_Reg(OFSZ,0x00);

	delay_ms(12);
	for(i=0;i<10;i++)
	{
		ADXL345_RD_Avval(&acc);
		offx += acc.x;
		offy += acc.y;
		offz += acc.z;
	}
	offx/=10;
	offy/=10;
	offz/=10;
	*xval=-offx/4;
	*yval=-offy/4;
	*zval=-(offz-256)/4;
 	ADXL345_WR_Reg(OFSX,*xval);
	ADXL345_WR_Reg(OFSY,*yval);
	ADXL345_WR_Reg(OFSZ,*zval);
	
	// 还原被改写的寄存器内容
	ADXL345_WR_Reg(POWER_CTL, powerCtl);
	ADXL345_WR_Reg(DATA_FORMAT, dataFormat);
	ADXL345_WR_Reg(BW_RATE, bwRate);
	ADXL345_WR_Reg(INT_ENABLE, intEnable);
}

 

 

敲击检测

注意:采用中断模式,使能敲击检测时,一定要设置DATA_FORMAT.INT_INVERT位为1。通常,大部分中断中为低电平触发,将INT_INVERT设置为1,能够满足中断的低电平触发效果。

STM32应用-第4节-震动传感器ADXL345_第3张图片

 

STM32应用-第4节-震动传感器ADXL345_第4张图片

对应的,通常设置DATA_FORMAT为0X2B,也就是低电平触发,全分辨率,范围为±16G. 

THRESH_TAP(0x1D)

设置敲击检测的阈值,其单位是62.5mg/LSB,例如:设置为0x24,则敲击阈值为2.25G

TAP_AXES(0x2A)

D3:Supress位:1:如果两次敲击之间的加速度,高于THRESH_TAP,则不作为双击检测;0:取消此功能;

D2~D0: Tap_x,y,z的使能位:1:该方向敲击检测使能;0:该方向敲击检测不使能;

ACT_TAP_STATUS(0x2B)

记录敲击或者碰撞的方向。

D6~D4:ACT_XYZ source,记录碰撞的方向;

D2~D0:TAP_XYZ source,记录敲打的方向,例如,如果Z向敲打,就会记录为1;如果y向,则记录为2。如果多个方向均记录到敲打,则多个方向均会被设置。

STM32应用-第4节-震动传感器ADXL345_第5张图片

DUR(0x21) 

DUR寄存器用来设置敲击时间长度,其单位是:625us/LSB,例如:设置为0X80,对应的DUR为:128*0.625 = 80ms

Latent(0x22) 

Latent(延时)寄存器用来第一次敲击后多久,作为窗口,开始计算第二次敲击。Latent仅在双击中起到作用。其单位是1.25ms/LSB

Window(0x23) 

窗口寄存器用来设置两次敲击之间时间间隔。如果设置的端,则双击需要快一些,否则需要慢一些。其单位是1.25ms/LSB

双击测试结果:

INT_ENABLE(0x2E) 

中断使能,写1使能中断,写0禁止中断。

D7: DATA_READY D6:Single Tap; D5:Double Tap; D4:Activity; D3: Inactivity; D2: Free_Fall ; D1: WaterMark D0: Overrun;

需要注意:D7, D1, D0设置为0,并不影响输出,而仅仅影响中断输出。例如:D7设置为0,则不会产生中断,但是数据依旧会输出;

 

INT_SOURCE(0x30) 只读

Int_Source与Int_enable一一对应,用来获取中断的触发原因。经过实际测试,发现water_mark中断位总是存在。

单双及检测实例

ADXL345_WR_Reg(POWER_CTL,0x28);	   						//链接禁止,测量模式
		ADXL345_WR_Reg(INT_ENABLE, 0x20);							//singletap 0x40, single&double:0x60
		ADXL345_WR_Reg(INT_MAP, 0x00);								//中断发送到INT1
	 	ADXL345_WR_Reg(OFSX,0x00);
		ADXL345_WR_Reg(OFSY,0x00);
		ADXL345_WR_Reg(OFSZ,0x00);

ADXL345_WR_Reg(TAP_AXES,0x07);		//X,Y,Z方向均检测
		ADXL345_WR_Reg(THRESH_TAP,0x24);	//敲击阈值,62.5mg/LSB, 0x24表示2.25g
		ADXL345_WR_Reg(DUR,0x80);					//敲击时长
		ADXL345_WR_Reg(Latent,0x22);			//双击延时
		ADXL345_WR_Reg(Window,0xff);			//双击窗口

注意:INT_ENABLE.DATA_READY一定要设置为0,否则DATA_READY会不断使得MCU进入中断模式,从而影响其他中断判断。 

 

DataFormat(0X31)

D7:SelfTest

1:使能SelfTest, 0:禁止SelfTest; SelfTest主要用来测试传感器是否损坏;

D6: SPI BIT

1: 3-WIRE SPI, 0: 4-WIRE SPI, 通常使用4-WIRE SPI;

D5: INT_INVERT

1:中断低电平有效 0:中断高电平有效。这里需要设置为1, 中断低电平有效。

D4:0

D3:FULL_RES

1:全分辨率模式; 0:非全分辨率模式;

D2:JUSTIFY_BIT

1: 左对齐(MSB) 0:右对齐

D2:D0, Range_bit

00: 2G; 01: 4G; 10:8G, 11: 16G

默认设置:2B模式, 也就是:中断低电平有效, 16G满分辨率模式;

BW_RATE(0X2C)

D4:LOW_POWER

0:正常操作; 1: 低功耗模式

 

D3-D0: RATE

STM32应用-第4节-震动传感器ADXL345_第6张图片

ADXL读数分析

ADXL默认为16G模式,其读数分析如下:

1.读数为2BYTE;

2. 0FFF读数为4095,对应读数为1599(mg)

3. FFFF表示-1, 对应读数为-3.9mg

4. F000为-1600(mg)

 STM32应用-第4节-震动传感器ADXL345_第7张图片

ACTIVITY设置

THRESH_ACT(0X24)

这个寄存器用来设置监测ACTIVITY的阈值。数据是无符号的(不带正负),比例因子为62.5mg/LSB

THRESH_INACT(0X25)

同上,用来监测非活动的阈值。

TIME_INACT(0X26)

用来设置非活动状态的时间阈值,比例因子为1sec/LSB;

 

 

初始化

ADXL_GPIO_Init

GPIO初始化时,根据是否支持中断,分为两种方式。

如果不支持中断,则仅仅做到CS初始化即可。

如果支持中断,则需要做到中断先EXTI和中断分组NVIC初始化。

void ADXL_GPIO_Init(void)
{
#ifdef __ADXL_INT_FLAG_
 	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;
#endif
 	GPIO_InitTypeDef GPIO_InitStructure;

	// ADXL345 SPI通讯端口CS初始化
 	RCC_APB2PeriphClockCmd(ADXL_RCC_APB2Periph_GPIO, ENABLE);	//使能PB端口时钟
	GPIO_InitStructure.GPIO_Pin = ADXL_PIN_CS;			
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;			//推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(ADXL_PORT_CS, &GPIO_InitStructure);
 	GPIO_SetBits(ADXL_PORT_CS, ADXL_PIN_CS);					//PB0上拉

#ifdef __ADXL_INT_FLAG_
	//ADXL345中断端口初始化
 	RCC_APB2PeriphClockCmd(ADXL_RCC_APB2Periph_GPIO_INT, ENABLE);//使能PORT时钟
	GPIO_InitStructure.GPIO_Pin  = ADXL_PIN_INT1|ADXL_PIN_INT2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				//设置成上拉输入
 	GPIO_Init(ADXL_PORT_INT, &GPIO_InitStructure);

	//ADXL345中断线以及中断初始化配置   下降沿触发
  	GPIO_EXTILineConfig(ADXL_INT_SOURCE_PORT, ADXL_INT_SOURCE1);
  	EXTI_InitStructure.EXTI_Line = ADXL_EXTI_LINE1;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

	//ADXL345中断线以及中断初始化配置   下降沿触发
  	GPIO_EXTILineConfig(ADXL_INT_SOURCE_PORT, ADXL_INT_SOURCE2);
  	EXTI_InitStructure.EXTI_Line = ADXL_EXTI_LINE2;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

	// 设置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;			//使能按键KEY2所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级2
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;			//使能按键KEY0所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级0 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
 #endif
}

ADXL345_Init 

ADXL345初始化时,会完成GPIO初始化,SPI初始化,然后读出ADXL345配置信息到g_adxlSetValue中。

 

//初始化ADXL345.
//返回值:0,初始化成功;1,初始化失败.
u8 ADXL345_Init(void)
{
	u8 bRet = 1;
	u16 *pTemp;
	
	// 初始化ADXL相关的GPIO口
	ADXL_GPIO_Init();
	
	ADXL_SELECT_CS = 1;
	SPIx_Init();

	// 从后备寄存器中读取设置信息值并设置ADXL通信速率
	pTemp = (u16*)&g_adxlSetValue;   //pTemp指向全局变量地址
	*pTemp = BKP_ReadBackupRegister(BKP_R_ADXL_SET);

	ADXL345_RD_Reg(DEVICE_ID, &bRet, 1);
	if(bRet==0xE5)	//读取器件ID
	{
		ADXL345_Setup(g_adxlSetValue);
		ADXL345_WR_Reg(POWER_CTL,0x28);	   						//链接禁止,测量模式
		ADXL345_WR_Reg(INT_ENABLE, 0x00);						//使能DATA_READY中断
	 	ADXL345_WR_Reg(OFSX,0x00);
		ADXL345_WR_Reg(OFSY,0x00);
		ADXL345_WR_Reg(OFSZ,0x00);

		bRet = 0;
	}
	else
		bRet = 1;
	
	return bRet;
}

 

初始化时,写入的值为0x0a2b,其含义如下:

typedef struct _ADXL_VALUE_STRUCT_
{
	u8 data_format;			// 分辨率及量程
	u8 power_speed;			// 功耗模式及传输速率
} ADXL_VALUE_STRUCT;

其中0X31为DATA_FORMAT,写入值为0X0A

D3=1:全分辨率;

D1D0=10:对应范围±8g

STM32应用-第4节-震动传感器ADXL345_第8张图片

 

STM32应用-第4节-震动传感器ADXL345_第9张图片

 

转换速率的设置:

对应地址:0X2C

STM32应用-第4节-震动传感器ADXL345_第10张图片

 

自动休眠(AutoSleep)

一段时间没有活动后,ADXL345可以进入自动休眠模式。要使能这个功能,需要设置THRESH_INACT寄存器和TIME_INACT
寄存器。这两个寄存器分别设定一个合适的阈值,例如,都设置为0X03; 然后设置POWER_CTL寄存器的AUTO_SLEEP
和Link位。这样一段时间活动值小于阈值后,就会进入自动休眠模式

Standby模式

如果把POWER_CTL的Measure位设置为0,则ADXL345进入standby模式,此模式下,不会检测加速度信息,同时功耗最低(0.1uA)

https://wenku.baidu.com/view/3a500cfc910ef12d2af9e7d0.html

https://wenku.baidu.com/view/fb1256d3b9f3f90f76c61b1d.html

 

你可能感兴趣的:(STM32应用-第4节-震动传感器ADXL345)