文章目录
前言
这篇博客将介绍使用stm32的IIC库函数开发MS5611气压计,获取气压数据和温度数据,并对数据进行补偿。过程将结合芯片手册与代码。
手册下载地址:https://wws.lanzous.com/iZDAvf6joyd
代码仓库地址:https://gitee.com/killerp/MS5611
使用IIC接口进行数据读取。
当PS脚接高电平时,7和8引脚复用为IIC模式,否则为SPI模式;
由上图,CSB接地,则CSB非就是1了。所以MS5611的地址就是0xEE;
一、MS5611的5种命令
MS5611仅有5种基础命令:
1、RESET : 重启芯片
在读取PROM数据之前必须REST芯片,也就是在初始化的时候reset一下:
reset命令固定是0x1E;
/*
* 重启ms5611
*/
void MS5611_Rest()
{
I2C_WriteByte(I2C1,MS5611_SLAVE_ADDR,MS5611_CMD_REST);
delay_ms(4);
}
2、READ PROM:
读取PROM内存的数据,PROM存放8个16位数据,第一个16位数据包含工厂数据,第二到第七个数据用于补偿气压和温度。2-7的具体含义见图:
最后一个数据是CRC校验数据
3、D1,D2 CONVERSION
因为传感器获得的气压数据,温度数据是模拟量,需要进行模数转换。D1,D2分别对应气压和温度的模数转换精度。支持从256到4096的转换精度,精度越大,转换时间越长,具体对应关系见图:
4、READ ADC RESULT:
读取气压和温度模数转换后的数据,就是我们需要的数据。每次读取必须先进行模数转换后,延时一个转换时间后再发送此命令。
二、实现代码
需要重启芯片,然后读取保存PROM内8个数据,等会补偿数据时会用到
/*
* 读取prom的内容
*/
int MS5611_init()
{
ms5611_init();
Ms5611_Rest();
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_0,2,(unsigned char *)(ms5611_handle->reserve),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_1,2,(unsigned char *)(ms5611_handle->C),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_2,2,(unsigned char *)((ms5611_handle->C)+1),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_3,2,(unsigned char *)((ms5611_handle->C)+2),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_4,2,(unsigned char *)((ms5611_handle->C)+3),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_5,2,(unsigned char *)((ms5611_handle->C)+4),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_6,2,(unsigned char *)((ms5611_handle->C)+5),MSB);
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS5611_PROM_READ_7,2,(unsigned char *)(ms5611_handle->CRC),MSB);
}
以读取温度数据为例,先发送转换命令,等待转换时间,再去读取3个字节的温度数据
/*
* 读取温度 转换精度4096
*/
int MS5611_read_temp()
{
I2C_WriteByte(I2C1,MS5611_SLAVE_ADDR,MS5611_CMD_CONVERT_D2_4096);//发送转换命令
delay_ms(9);//等待转换完成
I2C_ReadBytes(I2C1,MS5611_SLAVE_ADDR,MS6511_ADC_READ,3,(unsigned char *)((ms5611_handle->D)+1),MSB);//读取三个字节的温度
}
计算公式来自手册,主要是为了求出P(温度补偿压力):
当温度过低时,计算过程就多了T2,OFF2等步骤:
代码上基本跟着手册的公式来,这里不考虑温度低于-15°的情况
/*
* 修正气压和温度
*/
int MS5611_calculate()
{
signed long long dT = 0,TEMP = 0,T2 = 0,OFF = 0,OFF2 = 0,SENS2 = 0,SENS = 0;
dT = ms5611_handle->D[1] - ((signed long long) (ms5611_handle->C[4])<<8);
TEMP = 2000 + ((signed long long) (dT*(ms5611_handle->C[5]))>>23);
//低于20°时:
if(TEMP < 2000 && TEMP > -1500)
{
T2 = ( dT*dT )>>31;
OFF2 = 5 * (TEMP - 2000) * (TEMP - 2000) / 2;
SENS2 = 5 * (TEMP - 2000) * (TEMP - 2000) / 4;
}
OFF = (((int64_t)(ms5611_handle->C[1])) << 16) + (((ms5611_handle->C[3]) * dT) >> 7);
SENS = (((int64_t)(ms5611_handle->C[0])) << 15) + (((ms5611_handle->C[2]) * dT) >> 8);
ms5611_handle->dT = dT;
ms5611_handle->OFF -= OFF2;
ms5611_handle->TEMP -= T2;
ms5611_handle->SENS -= SENS2;
ms5611_handle->P = ((((ms5611_handle->D[0]) * (ms5611_handle->SENS))>>21) - (ms5611_handle->OFF))>>15;
}