ms5611简介:
官方给出的最大分辨率:10cm
工作电压: 1.8v ~ 3.6v
气压 AD 精度:24位
工作环境:-40 ~ +85°C,10 ~ 1200mbar(毫巴 = 百帕)
通讯接口: I2C/SPI (PS:1 - I2C ; PS:0 - SPI)
焊接条件: <250°C < 40秒
开发环境:
开发板: stm32F4discovery
气压计模块:GY-63(ms5611)
开发工具:window7 + MDK(Keil5.1)
程序依赖模块: I2C/SPI 驱动 (此处使用的i2c通讯接口)
MS5611接口及相应寄存器定义-drv_ms5611.h
#include "stdbool.h" #include <math.h> #define MS5611_ADDR 0x77 #define CMD_RESET 0x1E #define CMD_ADC_READ 0x00 #define CMD_ADC_CONV 0x40 #define CMD_ADC_D1 0x00 #define CMD_ADC_D2 0x10 #define CMD_ADC_256 0x00 #define CMD_ADC_512 0x02 #define CMD_ADC_1024 0x04 #define CMD_ADC_2048 0x06 #define CMD_ADC_4096 0x08 #define CMD_PROM_RD 0xA0 #define PROM_NB 8 #define MS5611_OSR_4096_CONV_DELAY 8220 #define MS5611_OSR_2018_CONV_DELAY 4130 #define MS5611_OSR_1024_CONV_DELAY 2080 #define MS5611_OSR_512_CONV_DELAY 1060 #define MS5611_OSR_256_CONV_DELAY 540 bool ms5611Init (void ) ; void ms5611_start_ut (void ) ;void ms5611_get_ut (void ) ;void ms5611_start_up (void ) ;void ms5611_get_up (void ) ;void ms5611_calculate (int32_t *pressure, int32_t *temperature) ;float getEstimatedAltitude (int32_t baroPressure) ;
ms5611 i2c 地址定义,由芯片管脚 CSB 决定.111011Cx
,其中C为CSB引脚的补码值(取反).
TIP:
本案例中i2c地址 0x77 并没有把i2c 的读写标志位包括,所以在I2C 读写代码实现时务必手动左移。
ms5611 官方手册 寄存器地址 说明:
ms5611 代码实现 - drv_ms5611.c #include "drv_system.h" #include "drv_i2c.h" #include "drv_ms5611.h" static uint32_t ms5611_ut; static uint32_t ms5611_up; static uint16_t ms5611_c[PROM_NB]; #define PA_OFFSET_INIT_NUM 50 static float Alt_offset_Pa=0 ; double paOffsetNum = 0 ; uint16_t paInitCnt=0 ;uint8_t paOffsetInited=0 ;static uint16_t ms5611_prom (int8_t coef_num) ; static void ms5611_reset (void ) ;static uint32_t ms5611_read_adc (void ) ;static int8_t ms5611_crc (uint16_t *prom) ;bool ms5611Init (void ) { bool ack = false ; uint8_t sig; int i; delayMs(10 ); ack = i2cRead(MS5611_ADDR, CMD_PROM_RD, 1 , &sig); if (!ack) return false ; ms5611_reset(); for (i = 0 ; i < PROM_NB; i++) ms5611_c[i] = ms5611_prom(i); if (ms5611_crc(ms5611_prom) != 0 ) return false ; return true ;} static void ms5611_reset (void ) { i2cWrite(MS5611_ADDR, CMD_RESET, 1 ); delayMs(10 ); } * 读取 ms5611 出厂校准数据 */ static uint16_t ms5611_prom (int8_t coef_num) { uint8_t rxbuf[2 ] = { 0 , 0 }; i2cRead(MS5611_ADDR, CMD_PROM_RD + coef_num * 2 , 2 , rxbuf); return rxbuf[0 ] << 8 | rxbuf[1 ];} * 读取 ms5611 采集的 温度/气压(24bit) */ static uint32_t ms5611_read_adc (void ) { uint8_t rxbuf[3 ]; i2cRead(MS5611_ADDR, CMD_ADC_READ, 3 , rxbuf); return (rxbuf[0 ] << 16 ) | (rxbuf[1 ] << 8 ) | rxbuf[2 ];} * 开始采集温度. */ void ms5611_start_ut (void ) { i2cWrite(MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096, 1 ); } * 读取出 MS5611 采集的温度AD值 */ void ms5611_get_ut (void ) { ms5611_ut = ms5611_read_adc(); } * 开始采集气压. */ void ms5611_start_up (void ) { i2cWrite(MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096, 1 ); } * 读取出 MS5611 采集的气压AD值 */ void ms5611_get_up (void ) { ms5611_up = ms5611_read_adc(); } * 读取的气压&温度AD值转换为实际值并作温度补偿(温度精度:0.01℃,气压精度:0.01mbar) */ void ms5611_calculate (int32_t *pressure, int32_t *temperature) { uint32_t press; int64_t temp; int64_t delt; int32_t dT = (int64_t )ms5611_ut - ((uint64_t )ms5611_c[5 ] * 256 ); int64_t off = ((int64_t )ms5611_c[2 ] << 16 ) + (((int64_t )ms5611_c[4 ] * dT) >> 7 ); int64_t sens = ((int64_t )ms5611_c[1 ] << 15 ) + (((int64_t )ms5611_c[3 ] * dT) >> 8 ); temp = 2000 + ((dT * (int64_t )ms5611_c[6 ]) >> 23 ); if (temp < 2000 ) { delt = temp - 2000 ; delt = 5 * delt * delt; off -= delt >> 1 ; sens -= delt >> 2 ; if (temp < -1500 ) { delt = temp + 1500 ; delt = delt * delt; off -= 7 * delt; sens -= (11 * delt) >> 1 ; } } press = ((((int64_t )ms5611_up * sens) >> 21 ) - off) >> 15 ; if (pressure) *pressure = press; if (temperature) *temperature = temp; } * ms5611 prom 数据 校验 */ static int8_t ms5611_crc (uint16_t *prom) { int32_t i, j; uint32_t res = 0 ; uint8_t zero = 1 ; uint8_t crc = prom[7 ] & 0xF ; prom[7 ] &= 0xFF00 ; for (i = 0 ; i < 8 ; i++) { if (prom[i] != 0 ) zero = 0 ; } if (zero) return -1 ; for (i = 0 ; i < 16 ; i++) { if (i & 1 ) res ^= ((prom[i >> 1 ]) & 0x00FF ); else res ^= (prom[i >> 1 ] >> 8 ); for (j = 8 ; j > 0 ; j--) { if (res & 0x8000 ) res ^= 0x1800 ; res <<= 1 ; } } prom[7 ] |= crc; if (crc == ((res >> 12 ) & 0xF )) return 0 ; return -1 ;} * 气压解算为高度值(cm) */ float getEstimatedAltitude (int32_t baroPressure) { static float Altitude; if (Alt_offset_Pa == 0 ){ if (paInitCnt > PA_OFFSET_INIT_NUM){ Alt_offset_Pa = paOffsetNum / paInitCnt; paOffsetInited=1 ; }else paOffsetNum += baroPressure; paInitCnt++; Altitude = 0 ; return Altitude; } Altitude = 4433000.0f * (1 - powf((((float ) baroPressure) / Alt_offset_Pa), 0.190295f )); return Altitude; }
由于气压受温度影响,所以需要进行温度补偿。void ms5611_calculate(int32_t *pressure, int32_t *temperature)
温度计算公式:
实际和参考温度之间的差异:
d T = D 2 − T R E F = D 2 − C 5 ∗ 2 8 dT = D2 - T_{REF} = D2 - C5*2^{8} d T = D 2 − T R E F = D 2 − C 5 ∗ 2 8
实际温度(-40…85°C / 0.01°C的分辨率):
T E M P = 2 0 + d T ∗ T E M P S E N S = 2 0 0 0 + d T ∗ C 6 / 2 2 3 TEMP = 20 + dT*TEMPSENS = 2000 + dT*C6/2^{23} T E M P = 2 0 + d T ∗ T E M P S E N S = 2 0 0 0 + d T ∗ C 6 / 2 2 3
温度补偿下气压计算公式:
实际温度抵消 :
O F F = O F F T 1 + T C O ∗ d T = C 2 ∗ 2 1 6 + ( C 4 ∗ d T ) / 2 7 OFF = OFF_{T1} + TCO*dT = C2*2^{16} + (C4*dT) / 2^{7} O F F = O F F T 1 + T C O ∗ d T = C 2 ∗ 2 1 6 + ( C 4 ∗ d T ) / 2 7
实际温度灵敏度 :
S E N S = S E N S T 1 + T C S ∗ d T = C 1 ∗ 2 1 5 + ( C 3 ∗ d T ) / 2 8 SENS = SENS_{T1} + TCS*dT = C1*2^{15} + (C3*dT) / 2^{8} S E N S = S E N S T 1 + T C S ∗ d T = C 1 ∗ 2 1 5 + ( C 3 ∗ d T ) / 2 8
温度补偿后得到的气压值:(10 ~ 1200mbar/ 0.001mbar分辨率)
P = D 1 ∗ S E N S − O F F = ( D 1 ∗ S E N S / 2 2 1 ) / 2 1 5 P = D1*SENS - OFF = (D1*SENS / 2^{21}) / 2^{15} P = D 1 ∗ S E N S − O F F = ( D 1 ∗ S E N S / 2 2 1 ) / 2 1 5
Tip
: C1 C2 .. 等值都来自芯片内置的 PROM 数据,在初始化代码时读取
Tip:
并且由于此芯片在 大于20°C下比较准,低于20°C气压误差骤增,所以还必须做二阶温度补偿
气压值到高度的解算 float getEstimatedAltitude(int32_t baroPressure)
气压转换高度公式为:A l t i t u d e = 4 4 3 3 0 0 0 ∗ [ 1 − ( p p 0 ) 1 5 . 2 5 5 ] Altitude = 4 433 000 * [1 - (\frac{p}{p_{0}})^{\frac{1}{5.255}}] A l t i t u d e = 4 4 3 3 0 0 0 ∗ [ 1 − ( p 0 p ) 5 . 2 5 5 1 ]
tip
: Altitude 为高度(cm); P 为温度补偿后的气压值; P 0 P_{0} P 0 标准大气压(101 325 Pa)或者基准气压。
完整源码,包含 测试 和 所需的I2C驱动.click here