欢迎使用CSDN-markdown编辑器
来源:互联网 发布:网页过滤软件 编辑:程序博客网 时间:2024/06/13 21:43
ms5611简介:
官方给出的最大分辨率:10cm
工作电压: 1.8v ~ 3.6v
气压 AD 精度:24位
工作环境:-40 ~ +85°C,10 ~ 1200mbar(毫巴 = 百帕)
通讯接口: I2C/SPI (PS:1 - I2C ; PS:0 - SPI)
焊接条件: <250°C < 40秒
开发环境:
#### MS5611接口及相应寄存器定义-drv_ms5611.h开发板: stm32F4discovery
气压计模块:GY-63(ms5611)
开发工具:window7 + MDK(Keil5.1)
程序依赖模块: I2C/SPI 驱动 (此处使用的i2c通讯接口)
#include "stdbool.h"#include <math.h>// MS5611, Standard address 0x77#define MS5611_ADDR 0x77#define CMD_RESET 0x1E // ADC reset command#define CMD_ADC_READ 0x00 // ADC read command#define CMD_ADC_CONV 0x40 // ADC conversion command#define CMD_ADC_D1 0x00 // ADC D1 conversion#define CMD_ADC_D2 0x10 // ADC D2 conversion#define CMD_ADC_256 0x00 // ADC OSR=256#define CMD_ADC_512 0x02 // ADC OSR=512#define CMD_ADC_1024 0x04 // ADC OSR=1024#define CMD_ADC_2048 0x06 // ADC OSR=2048#define CMD_ADC_4096 0x08 // ADC OSR=4096#define CMD_PROM_RD 0xA0 // Prom read command#define PROM_NB 8#define MS5611_OSR_4096_CONV_DELAY 8220 // 8.22ms#define MS5611_OSR_2018_CONV_DELAY 4130 // 4.13ms#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引脚的补码值(取反).![ms5611_addr](/resource/fly/ms5611_addr.png) `TIP:` **本案例中i2c地址 0x77 并没有把i2c 的读写标志位包括,所以在I2C 读写代码实现时务必手动左移。** - ms5611 官方手册 寄存器地址 说明:![ms5611reg](/resource/fly/ms5611reg.png)#### ms5611 代码实现 - drv_ms5611.c#include "drv_system.h"#include "drv_i2c.h"#include "drv_ms5611.h"static uint32_t ms5611_ut; // static result of temperature measurementstatic uint32_t ms5611_up; // static result of pressure measurementstatic uint16_t ms5611_c[PROM_NB]; // on-chip ROM//static uint8_t ms5611_osr = CMD_ADC_4096;#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); // No idea how long the chip takes to power-up, but let's make it 10ms ack = i2cRead(MS5611_ADDR, CMD_PROM_RD, 1, &sig); if (!ack) return false; ms5611_reset(); // read all coefficients 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); // send PROM READ commandreturn 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); // read ADCreturn (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); // D2 (temperature) conversion start!} /* * 读取出 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); // D1 (pressure) conversion start!} /* * 读取出 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) { // temperature lower than 20degC delt = temp - 2000; delt = 5 * delt * delt; off -= delt >> 1; sens -= delt >> 2; if (temp < -1500) { // temperature lower than -15degC 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; // if eeprom is all zeros, we're probably fucked - BUT this will return valid CRC lol 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)`**温度计算公式:**实际和参考温度之间的差异:{% katex [displayMode] %}dT = D2 - T_{REF} = D2 - C5*2^{8}{% endkatex %}
实际温度(-40…85°C / 0.01°C的分辨率):
{% katex [displayMode] %}TEMP = 20 + dT*TEMPSENS = 2000 + dT*C6/2^{23}{% endkatex %}
温度补偿下气压计算公式:
实际温度抵消 :
{% katex [displayMode] %}OFF = OFF_{T1} + TCO*dT = C2*2^{16} + (C4*dT) / 2^{7}{% endkatex %}
实际温度灵敏度 :
{% katex [displayMode] %}SENS = SENS_{T1} + TCS*dT = C1*2^{15} + (C3*dT) / 2^{8}{% endkatex %}
温度补偿后得到的气压值:(10 ~ 1200mbar/ 0.001mbar分辨率)
{% katex [displayMode] %}P = D1*SENS - OFF = (D1*SENS / 2^{21}) / 2^{15}{% endkatex %}
Tip
: C1 C2 .. 等值都来自芯片内置的 PROM 数据,在初始化代码时读取
Tip:
并且由于此芯片在 大于20°C下比较准,低于20°C气压误差骤增,所以还必须做二阶温度补偿
- 气压值到高度的解算
float getEstimatedAltitude(int32_t baroPressure)
气压转换高度公式为:
{% katex [displayMode] %}Altitude = 4 433 000 * [1 - (\frac{p}{p_{0}})^{\frac{1}{5.255}}]{% endkatex %}
tip
: Altitude 为高度(cm); P 为温度补偿后的气压值; {% katex [displayMode] %}P_{0} {% endkatex %}标准大气压(101 325 Pa)或者基准气压。
完整源码,包含 测试 和 所需的I2C驱动.click here
0 0
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- python 的常用时间操作,取得当前时间等
- R语言中的逐步回归函数
- CSS学习(十九)-CSS伸缩布局盒
- Linux(三)——ubuntu系统的网络配置
- FZU 2218 Simple String Problem(状态压缩DP)
- 欢迎使用CSDN-markdown编辑器
- 圣思园张龙-Java SE 第三讲(原生数据类型使用陷阱 Pitfall of Primitive Data Type)
- OOD - blackjack
- 在centos上建个google镜像站
- c语言在gcc中编译时使用sqrt报错的解决
- Partition List
- Android网络编程之HttpURLConnection
- OOD - blackjack design
- SDL学习(3)图像运动处理