根据以上报文图示,并结合
STM32F1的库函数我们封装读写字节操作的函数。封装发送命令和获取数据函数:
/*向ADXL345下发指令,指令格式均为1个字节*/
void WriteByteToADXL345(I2C_TypeDef* I2Cx,uint8_tdeviceAddress,uint8_t command)
{
uint16_
ti2cTimeout=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_ti2cTimeout=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);
}
(2)ADXL寄存器及操作
ADXL345传感器拥有29个用户可见的寄存器,如下图所示。但是我们不对其进行具体的介绍,在数据手册上有非常详细的说明。这些寄存器我们并不会全部使用,事实上通常我们只是用配置寄存器和部分数据寄存器。
在使用ADXL345读取我们想要的数居前,我们先使用相关寄存器对传感器进行必要的配置,以期获取我们想要得到的值。如下初始化配置过程:
void ADXL345_Init_Configuration(void)
{
uint8_tdevid = 0, val = 0;
Delayus(300);
ReadByteFromADXL345(ADXL345_ADDRESS, 0x00, &devid); //获取设备ID
Delayus(300);
val =0x2B;
WriteByteToADXL345(ADXL345_ADDRESS, DATA_FORMAT_REG, &val); //数据格式控制
Delayus(50);
val =0x0A;
WriteByteToADXL345(ADXL345_ADDRESS, BW_RATE, &val); //数据速率及功率模式控制
Delayus(50);
val =0x28;
WriteByteToADXL345(ADXL345_ADDRESS, POWER_CTL, &val); //上电特性控制
Delayus(50);
val =0;
WriteByteToADXL345(ADXL345_ADDRESS, INT_ENABLE, &val); //中断使能控制
Delayus(50);
WriteByteToADXL345(ADXL345_ADDRESS, OFSX, &val); //X轴偏移
Delayus(50);
WriteByteToADXL345(ADXL345_ADDRESS, OFSY, &val); //Y轴偏移
Delayus(50);
WriteByteToADXL345(ADXL345_ADDRESS, OFSZ, &val); //Z轴偏移
Delayus(500);
}
(3)ADXL345数据获取
接下来我们就可以读取数据了,获取和解析数据前我们先来了解一下数据的格式。分别在寄存器0x2C中进行速率控制,在寄存器0x31中进行数据格式控制。ADXL345的输出数据可以采用右对齐和左对齐两种方式。
数据右对齐方式:
数据左对齐方式:
此外,ADXL345通过VS = 2.5 V
电源电压的测试且以其为额定电压;然而, VS可高至3.6 V或低至2.0 V。在麒麟座中解释使用的3.3VDC供源,偏移、灵敏度、噪声、自测和电源电流等参数随着电源电压变化而变化。随着电源电压的改变,静电力也发生细微变化,因此,偏移和灵敏度也有细微变化。在电源电压VS = 3.3 V下运行时, x轴和y轴偏移通常比VS= 2.5 V运行时高25 m
g。在电源电压3.3 V下运行与在VS = 2.5V时比较, z轴偏移一般低20 m
g。VS = 2.5V时, x轴和y轴的灵敏度为标称256 LSB/g(全分辨率或±2
g, 10位运行),而电源电压为3.3V时,其灵敏度转换为265 LSB/
g。 z轴灵敏度不受电源电压影响, 2.5 V时或3.3 V时都相同。可以用简单的线性插值来确定其他电源电压下的偏移和灵敏度的典型转换。
搞清楚了以上问题就可以读取正确的数据了:
void GetValue FromADXL345 (void)
{
unsignedchar devid = 0;
unsignedchar dataTemp[6];
Delayus(200);
ReadByteFromADXL345(ADXL345_ADDRESS, 0x00, &devid); //读取设备ID
Delayus(200);
ReadBytesFromADXL345 (ADXL345_ADDRESS, 0x32, dataTemp, 6); //获取原始数据(4mg/LSB)
adxlInfo.incidence_X= (short)(dataTemp[0] + ((unsigned short)dataTemp[1] << 8));
adxlInfo.incidence_Y = (short)(dataTemp[2] + ((unsignedshort)dataTemp[3] << 8));
adxlInfo.incidence_Z = (short)(dataTemp[4] + ((unsignedshort)dataTemp[5] << 8));
adxlInfo.incidence_Xf= (float)adxlInfo.incidence_X * 0.0039; //换算为物理量值
adxlInfo.incidence_Yf= (float)adxlInfo.incidence_Y * 0.0039; //换算为物理量值
adxlInfo.incidence_Zf= (float)adxlInfo.incidence_Z * 0.0039; //换算为物理量值
}
至此软件编写完成。
4、结果验证
完成编写后,编译无误。我们查看最终的运行结果如何。首先我们登录到OneNET,并组态好设备和应用,然后下载程序重新上电,就可以看到Xg、Yg、Zg的数据以及上次我们读取的温湿度数据:
我们再看一下显示屏中显示的数据是什么样的。因显示精度不同有些差异,但基本是一致的。
至此,我们完成了ADXL345数据的获取以及上传到OneNET,在后续我们将继续各种OneNET以及麒麟座开发板的研究。OneNET真的是越用越有意思。