由于数据采集站基本都安装在野外或者楼顶,安装位置以及震动对检测数据的准确性有一定影响。所以想要有一个位置状态数据,正好发现麒麟作上有ADXL345,这样一个数字输出的加速度传感器。如图中红框所示:
1、ADXL345概述
ADXL345是ADI公司推出的基于iMEMS技术的3轴、数字输出加速度传感器。该加速度传感器的特点如下:
- 分辨率高。最高13位分辨率。
- 量程可变。具有+/-2g,+/-4g,+/-8g,+/-16g可变的测量范围。
- 灵敏度高。最高达3.9mg/LSB,能测量不到1.0°的倾斜角度变化。
- 功耗低。 40~145uA 的超低功耗,待机模式只有 0.1uA。
- 尺寸小。整个 IC 尺寸只有 3mm*5mm*1mm, LGA 封装。
ADXL支持标准的I2C或SPI数字接口,自带32级FIFO存储,并且内部有多种运动状态检测和灵活的中断方式等特性。ADXL345传感器的检测轴如下图所示:

当 ADXL345 沿检测轴正向加速时,它对正加速度进行检测。在检测重力时用户需要注意,当检测轴的方向与重力的方向相反时检测到的是正加速度。下图所示为输出响应与相对于重力的方向的关系:

2、硬件设计
ADXL345支持SPI 和I2C两种通信方式,麒麟座采用的I2C通讯方式,具体连接如下图所示:


对于任何不使用的引脚,没有内部上拉或下拉电阻,因此,CS引脚或ALT ADDRESS引脚悬空或不连接时,任何已知状态或默认状态不存在。使用I2C时, CS引脚必须连接至VDD I/O, ALT ADDRESS引脚必须连接至任一VDD I/O或接地。
ALT ADDRESS引脚处于高电平,器件的7位I2C地址是0x1D,随后为R / W位。这转化为0x3A写入,0x3B读取。通过ALT ADDRESS引脚(引脚12)接地,可以选择备用I2C地址0x53(随后为R / W位)。这转化为0xA6写入, 0xA7读取。
由于在麒麟座中,ALT ADDRESS引脚(引脚12)接地,所以地址为0x53,也就是0xA6写入, 0xA7读取。此外2个终端信号也引入了MCU。
3、软件设计
接下来我们开始软件方面的设计。因为麒麟座中ADXL345使用I2C接口与MCU通讯,并连接到了I2C2(PB10、PB11)端口,接下来我们将逐步实现这部分软件。
(1)、I2C读写操作
因为ADXL345加速度传感器使用了标准的I2C通讯接口,所以我们来看一看I2C读写单个或多个子解释的报文格式(如下图)。

根据以上报文图示,并结合STM32F1的库函数我们封装读写字节操作的函数。封装发送命令和获取数据函数:
/*向ADXL345下发指令,指令格式均为1个字节*/ void WriteByteToADXL345(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t command) { uint16_t i2cTimeout=TimeoutPeriod; /*产生I2C起始信号*/ I2C_GenerateSTART(I2C2, ENABLE); /*检测 EV5 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if ((i2cTimeout--) == 0) return ; } /*发送ADXL345的地址*/ I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Transmitter); i2cTimeout=TimeoutPeriod; /*检测 EV6 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if ((i2cTimeout--) == 0) return ; } /*下发操作命令*/ I2C_SendData(I2Cx, command); i2cTimeout=TimeoutPeriod; /*检测 EV8 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if ((i2cTimeout--) == 0) return ; } /* 产生I2C停止信号 */ I2C_GenerateSTOP(I2Cx, ENABLE); } /*从ADXL345读取多个字节数据的值*/ void ReadBytesFromADXL345(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum) { uint16_t i2cTimeout=TimeoutPeriod; /*如果I2C总线忙,则等待一段时间*/ while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) { if ((i2cTimeout--) == 0) return ; } /* 产生 I2C 起始信号 */ I2C_GenerateSTART(I2Cx, ENABLE); /*检测 EV5 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if ((i2cTimeout--) == 0) return ; } /*发送ADXL345的地址*/ I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Receiver); i2cTimeout=TimeoutPeriod; /*检测 EV6 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if ((i2cTimeout--) == 0) return ; } while(bytesNum) { if(bytesNum==1) { I2C_AcknowledgeConfig(I2Cx, DISABLE);//关闭应答 I2C_GenerateSTOP(I2Cx, ENABLE);//停止信号 } i2cTimeout=TimeoutPeriod; /*检测 EV7 事件并清除标志*/ while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)) { if ((i2cTimeout--) == 0) return ; } /*通过 I2C,从设备中读取一个字节的数据 */ *pData=I2C_ReceiveData(I2Cx); pData++; bytesNum--; } /*使能应答,方便下一次 I2C 传输*/ I2C_AcknowledgeConfig(I2Cx, ENABLE); }
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/126190.html