1. 如上图所示,通过IIC协议,cpu可以读取adxl中测量得到的三个方向的加速度值。
2.重点:初始化配置ADXL,设置高低阈值和低于低阈值的判断时间,使得adxl自行判断自身的状态。
模式配置要求如下:
(1)当adxl 处于运动状态时,只检测静止事件(即,判断是否低于低阈值,以及持续的时间是否达到设定时间),当检测到低阈值时,向INT1引脚 发送一个脉冲信号。
(2)当adxl处于静止状态时,只检测运动事件,一旦某一个方向的加速度大于指定的高阈值,即向INT2发送一个脉冲信号。
(3)上述的判断是对三个方向独立同时检测的。不是某一个,也不是三者之和.
(4)stm32通过上升沿检测外部中断。中断号EXTI15_10_IRQHandler,在中断服务函数内部区分是PB10还是PB11,用以决定是否置位休眠标志(注意,不可以在中断中直接进入休眠模式,原因大概是优先级等问题,会导致无法被唤醒)。
(5)我使用的低功耗模式是 停止模式,即关闭时钟和内核,任何外部中断都可以唤醒的模式。这个模式的好处自己可以百度了解。我的功耗从27毫安降到了3毫安。我试过将大多数引脚在睡眠前设置成模拟输入,别人说可以把功耗降的更低,但是发现并没有什么用。按照别人的说法,停止模式下,功耗在几十微安。我想这应该是指控制器的功耗(即stm32)。我的设备有一些外围模拟电路。有功耗也是很自然的。这也提醒我,以后在设计电路的时候一定要考虑到低功耗时,可以关断部分模块的供电。
3、不多说,发一下我的adxl的配置(部分注释写的有问题):
//加速度传感器,一段时间内低于某值,自动睡眠,高于某值自动苏醒
/*
ADXL345是一种三轴加速度计。
具有+/-2g,+/-4g,+/-8g,+/-16g可变的测量范围;
最高13bit分辨率;
固定的4mg/LSB灵敏度;
3mm*5mm*1mm超小封装;
40-145uA超低功耗;
标准的 I2C或SPI数字接口;
32级FIFO存储;
以及内部多种运动状态检测和灵活的中断方式等特性
*/
void ADXL345_init_sleep_wakeup()
{
unsigned char devid = 0, val = 0;
u8 i=0;
short offx=0,offy=0,offz=0;
ADXL345_Data_t temp;
delay_us(300);
//读ID 且每次读写之前都需要读ID
//Device_ReadBytes( &devid,ADXL345_ADDRESS,ADXL_R_ID);
//delay_us(300);
/*
寄存器0x31—DATA_FORMAT(读/写)
D7 D6 D5 D4 D3 D2 D1 D0
SELF_TEST SPI INT_INVERT 0 FULL_RES Justify Range
自测力使能位 1 3线式spi 0中断高有效 1 13分辨率 0右对齐 范围
0 4线式spi 1中断低有效 0 10分辨率 1左对齐
//-------------------------------------------------------
0x2B
0 0 0 1 1 0 1 1(16g)
1 0(8g)
0 1 (4g) 0 0 (2g)
*/
//低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
Device_WriteBytes(0x1B,ADXL345_ADDRESS,DATA_FORMAT);
delay_us(50);
/*
寄存器0x2C—BW_RATE(读/写)
D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 LOW_POWER (速率)
0 正常操作
1低功耗(噪声有增加)
//-------------------------------------------------------
0 0 0 0 1010
*/
//数据输出速度为100Hz
Device_WriteBytes(0x0A,ADXL345_ADDRESS,BW_RATE);
delay_us(50);
/*
寄存器0x2D—POWER_CTL(读/写)
D7 D6 D5 D4 D3 D2 D1 D0
0 0 链接 AUTO_SLEEP 测量 休眠 (休眠模式下的读取频率)
//-------------------------------------------------------
0 0 0 0 1 1 0 0(8HZ)
*/
//自动休眠模式,休眠时以8HZ的频率采样
Device_WriteBytes(0x38,ADXL345_ADDRESS,POWER_CTL);
delay_us(50);
/*
寄存器0x2E—INT_ENABLE(读/写)
D7 D6 D5 D4 D3 D2 D1 D0
DATA_READY SINGLE_TAP DOUBLE_TAP Activity Inactivity FREE_FALL Watermark Overrun
*/
//先关中断
Device_WriteBytes(0,ADXL345_ADDRESS,INT_ENABLE);
//无符号,阈值寄存器比例因子62.5mg/LSB
//睡眠激活activity阈值,当大于这个值的时候唤醒,其中10代表1g 16*62.5=1000mg
Device_WriteBytes(0x12,ADXL345_ADDRESS,THRESH_ACT);
//睡眠开始inactivity阈值,当小于这个值的时候睡眠,其中02代表0.2g
Device_WriteBytes(0x02,ADXL345_ADDRESS,THRESH_INACT);
//比例因子为1 sec /LSB
//当小于inactivity值时间超过这个值的时候进入睡眠,其中02代表2秒
Device_WriteBytes(0x05,ADXL345_ADDRESS,TIME_INACT);
//直流交流触发配置,XYZ使能触发配置,此处选用X交流触发
Device_WriteBytes(0xFF,ADXL345_ADDRESS,ACT_INACT_CTL);
/*
D7 D6 D5 D4 D3 D2 D1 D0
DATA_READY SINGLE_TAP DOUBLE_TAP Activity Inactivity FREE_FALL Watermark Overrun
*/
//中断引脚选择,此处我们将activity映射到INT2,inact到INT1
Device_WriteBytes(0x10,ADXL345_ADDRESS,INT_MAP);
delay_us(50);
//打开中断(这里只需要 动作和静止的事件)
Device_WriteBytes(0x18,ADXL345_ADDRESS,INT_ENABLE);
delay_ms(20);
//软件偏移校准,视上电时为平放状态,x=0,y=0,z=1=====================(本设备,姿态不是固定的)
// for(i=0; i<10; i++)
// {
// Get_ADXL345_data(&temp);
// offx+=temp.x_axis;
// offy+=temp.y_axis;
// offz+=temp.z_axis;
// }
// offx/=10;
// offy/=10;
// offz/=10;
// Device_WriteBytes(-offx/4,ADXL345_ADDRESS,OFSX);
// Device_WriteBytes(-offy/4,ADXL345_ADDRESS,OFSY);
// Device_WriteBytes(-(offz-256)/4,ADXL345_ADDRESS,OFSZ);
}