一、MS5611模块简介
MS5611是一款高分辨率高度计传感器,配备 SPI 和 I2C 总线接口。这款气压传感器针对高度计和变高仪进行了优化,高度分辨率可达 10 厘米。MS5611包含一个高线性度压力传感器和一个超低功耗的 24 位 ΔΣ ADC,并内置出厂校准系数。它可提供精确的 24 位数字压力和温度值,并提供多种工作模式,用户可根据需求优化转换速度和功耗。高分辨率温度输出无需额外传感器即可实现高度计/温度计功能。

参数特性
- 供电电压:DC 3.3V / 5V
- 通讯方式:I2C / SPI通讯
- ADC:24位
- 气压量程:10~1200mbar
- 分辨率:0.065 / 0.042 / 0.027 / 0.018 / 0.012 mbar
- 精度:
Accuracy 25°C, 750 mbar(准确度,理想环境):±1.5mbar。
Error band -20°C to +85°C, 450~1100 mbar(误差带,最大允许偏离范围):±2.5mbar。 - 响应时间:0.5 / 1.1 / 2.1 / 4.1 / 8.22 ms
- 温度量程:-40 ~ 85℃
- 分辨率:<0.01℃
- 精度:±0.8℃
应用场景
- 移动式高度计/气压计系统
- 自行车码表
- 变距仪
- 用于医疗警报的高度感应
- 室内导航
二、MS5611引脚说明

| VCC | 电源正 |
|---|---|
| GND | 电源负 |
| SCL | I2C / SPI时钟 |
| SDA | I2C / SPI 串行数据输入 |
| CSB | 芯片选择,反补码,接低电平:7位器件地址为1110111,接高电平:7位器件地址为1110110,模块默认低电平 |
| SDO | SPI串行数据输出 |
| PS | 通讯协议选择,高电平为I2C通讯,低电平为SPI通讯,模块默认高电平 |
三、MS5611气压与温度读取流程与补偿分析说明
气压与温度读取流程图
第一步:读取校准参数(PROM),这些是工厂标定的补偿系数,决定精度。
C1:压力灵敏度(SENS)
C2:压力偏移(OFF)
C3:温度对SENS影响
C4:温度对OFF影响
C5:参考温度
C6:温度系数
第二步:读取原始ADC数据
D1:气压原始值(24bit)
D2:温度原始值(24bit)
第三步:计算温度
温差 dT = D2 − C5 * 2^8,dT是指当前温度 vs 参考温度 的差值。
实际温度 TEMP = 2000 + (dT * C6)/ 2^23,单位:0.01℃,如TEMP = 2007 → 20.07°C。
第四步:计算压力补偿参数
OFF(偏移)= C2 * 2^16 + (C4 * dT)/ 2^7
SENS(灵敏度)= C1 * 2^15 + (C3 * dT)/ 2^8
OFF零点偏移和SENS增益(温度会影响),这一步就是把温度误差带入气压模型修正。
第五步:计算最终气压
P = D1 * SENS - OFF = [(D1 * SENS)/ 2^21 - OFF] / 2^15,输出单位:0.01 mbar,如10009 → 100.09 mbar
上面的流程只是基础版,数据只在20℃以上准确,低温时会出现严重非线性误差,这时就需要手动补偿。补偿流程图如下:
情况1:温度 ≥ 20°C,T2,OFF2,SENS2为0,高温区已经比较线性,不需要补偿。
情况2:温度 < 20°C(低温)
温度补偿:T2 = dT^2 / 2^31
压力补偿:OFF2 = 5 * (TEMP − 2000)^2 / 2
SENS2 = 5 * (TEMP−2000)^2 / 4
情况3:温度 < -15°C(极低温)进一步补偿
OFF2 = OFF2 + 7 * (TEMP + 1500)^2
SENS2 = SENS2 + 11 * (TEMP + 1500)^2 / 2
最终修正补偿:
TEMP = TEMP - T2
OFF = OFF - OFF2
SENS = SENS - SENS2
四、MS5611主要寄存器说明

Reset(0x1E):复位寄存器
Convert D1(0x40~0x48):气压配置寄存器
Convert D2(0x50~0x58):温度配置寄存器
ADC Read(0x00):ADC读取寄存器
PROM Read(0xA0~0xAE):只读校准存储器
其中PROM Read只读校准存储器,MS5611在出厂时进行了校准,校准的6个系数存储 在PROM寄存器,PROM 一共 8个地址(每个16bit),从0xA0到0XAE, 一共8 * 16 = 128位,其中每两个字节为一个地址:
第0个地址:厂家保留,不用在意
第1到第6个地址:我们需要读取,后面用于气压计算
第7个地址:CRC
| 地址 | 命令 | 内容 |
|---|---|---|
| 0 | 0xA0 | 厂家保留 |
| 1 | 0xA2 | C1压力灵敏度 |
| 2 | 0xA4 | C2压力偏移 |
| 3 | 0xA6 | C3压力灵敏度温度系数 |
| 4 | 0xA8 | C4压力偏移温度系数 |
| 5 | 0xAA | C5参考温度 |
| 6 | 0xAC | C6温度系数 |
| 7 | 0xAE | 4位 CRC 校验,检测C1~C6 是否读取正确 |
其中,CRC校验如下

五、STM32F103驱动MS5611读取气压与温度数据
准备工作
STM32F103C8T6最小系统板,MS5611传感器模块,OLED模块,导线若干等。
接线说明
| STM32F103C8T6 | MS5611 |
|---|---|
| 3.3V | VCC |
| GND | GND |
| PA0 | SCL |
| PA1 | SDA |
| PB8 | OLED -> SCL |
| PB9 | OLED -> SDA |
代码示例
MS5611.c
#include "ms5611.h"
uint16_t Cal_C1_6[8];
uint32_t D1 = 0, D2 = 0, dT = 0;
void MS5611_W_SCL(uint8_t BitValue)
{
GPIO_WriteBit(PORT_MS5611, MS5611_SCL, (BitAction)BitValue);
Delay_us(10);
}
void MS5611_W_SDA(uint8_t BitValue)
{
GPIO_WriteBit(PORT_MS5611, MS5611_SDA, (BitAction)BitValue);
Delay_us(10);
}
uint8_t MS5611_R_SDA(void)
{
uint8_t BitValue;
BitValue = GPIO_ReadInputDataBit(PORT_MS5611, MS5611_SDA);
Delay_us(10);
return BitValue;
}
void MS5611_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_MS5611, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = MS5611_SCL | MS5611_SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(PORT_MS5611, &GPIO_InitStructure);
GPIO_SetBits(PORT_MS5611, MS5611_SCL|MS5611_SDA);
}
void MyI2C_Start(void)
{
MS5611_W_SDA(1);
MS5611_W_SCL(1);
MS5611_W_SDA(0);
MS5611_W_SCL(0);
}
void MyI2C_Stop(void)
{
MS5611_W_SDA(0);
MS5611_W_SCL(1);
MS5611_W_SDA(1);
}
void MyI2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i ++)
{
MS5611_W_SDA(Byte & (0x80 > > i));
MS5611_W_SCL(1);
MS5611_W_SCL(0);
}
}
uint8_t MyI2C_ReceiveByte(void)
{
uint8_t i, Byte = 0x00;
MS5611_W_SDA(1);
for (i = 0; i < 8; i ++)
{
MS5611_W_SCL(1);
if (MS5611_R_SDA() == 1){Byte |= (0x80 > > i);}
MS5611_W_SCL(0);
}
return Byte;
}
void MyI2C_SendAck(uint8_t AckBit)
{
MS5611_W_SDA(AckBit);
MS5611_W_SCL(1);
MS5611_W_SCL(0);
}
uint8_t MyI2C_ReceiveAck(void)
{
uint8_t AckBit;
MS5611_W_SDA(1);
MS5611_W_SCL(1);
AckBit = MS5611_R_SDA();
MS5611_W_SCL(0);
return AckBit;
}
uint8_t MS5611_Reset(void)
{
MyI2C_Start();
MyI2C_SendByte(MS5611_ADDR|0);
if(MyI2C_ReceiveAck() == 1) return 1;
MyI2C_SendByte(MS5611_RESET);
if(MyI2C_ReceiveAck() == 1) return 2;
MyI2C_Stop();
return 0;
}
void MS5611_Read_PROM(void)
{
uint8_t data_H=0,data_L=0;
uint8_t i = 0;
for( i = 0; i < 8; i++ )
{
MyI2C_Start();//起始信号
MyI2C_SendByte(MS5611_ADDR|0); //器件地址+写
MyI2C_ReceiveAck();
MyI2C_SendByte( MS5611_PROM + i * 2 ); //寄存器地址
MyI2C_ReceiveAck();
MyI2C_Stop();
Delay_us(200);
MyI2C_Start();//起始信号
MyI2C_SendByte(MS5611_ADDR|1); //器件地址+读
MyI2C_ReceiveAck();
data_H = MyI2C_ReceiveByte();//读取的数据高8位
MyI2C_SendByte(0);
data_L = MyI2C_ReceiveByte();//读取的数据低8位
MyI2C_SendByte(1);
MyI2C_Stop();
//保存出厂校准数据
Cal_C1_6[i] = (data_H< < 8) | data_L;
}
}
uint32_t MS5611_Read_D1_D2(uint8_t regaddr)
{
uint32_t dat = 0;
uint8_t buff[3] ={0};
MyI2C_Start();//起始信号
MyI2C_SendByte(MS5611_ADDR|0); //器件地址+写
if( MyI2C_ReceiveAck() == 1 )printf("D1 NACK -1rn");
MyI2C_SendByte(regaddr); //OSR = 4096
if( MyI2C_ReceiveAck() == 1 )printf("D1 NACK -2rn");
MyI2C_Stop();
Delay_ms(10);
MyI2C_Start();//起始信号
MyI2C_SendByte(MS5611_ADDR|0); //器件地址+写
if( MyI2C_ReceiveAck() == 1 )printf("D1 NACK -3rn");
MyI2C_SendByte(MS5611_ADC);
if( MyI2C_ReceiveAck() == 1 )printf("D1 NACK -4rn");
MyI2C_Stop();
Delay_ms(10);
MyI2C_Start();//起始信号
MyI2C_SendByte(MS5611_ADDR|1); //器件地址+读
if( MyI2C_ReceiveAck() == 1 )printf("D1 NACK -5rn");
buff[0] = MyI2C_ReceiveByte();
MyI2C_SendByte(0);
buff[1] = MyI2C_ReceiveByte();
MyI2C_SendByte(0);
buff[2] = MyI2C_ReceiveByte();
MyI2C_SendByte(1);
MyI2C_Stop();
dat = (((buff[0]< < 16) | ( buff[1]< < 8)) | buff[2]);
return dat;
}
float Get_TEMP(void)
{
int64_t TEMP;
int64_t T2 = 0;
D2 = MS5611_Read_D1_D2(MS5611_CONVERT_D2);
dT = (int64_t)D2 - ((int64_t)Cal_C1_6[5] < < 8);
TEMP = 2000 + ((dT * (int64_t)Cal_C1_6[6]) > > 23);
if(TEMP < 2000)
{
T2 = (dT * dT) > > 31;
TEMP -= T2;
}
return TEMP / 100.0f;
}
float Get_pressure(void)
{
int64_t TEMP;
int64_t OFF, SENS;
int64_t OFF2 = 0, SENS2 = 0;
int64_t T2 = 0;
int64_t P;
D1 = MS5611_Read_D1_D2(MS5611_CONVERT_D1);
Delay_ms(10);
D2 = MS5611_Read_D1_D2(MS5611_CONVERT_D2);
Delay_ms(10);
dT = (int64_t)D2 - ((int64_t)Cal_C1_6[5] < < 8);
TEMP = 2000 + ((dT * (int64_t)Cal_C1_6[6]) > > 23);
OFF = ((int64_t)Cal_C1_6[2] < < 16) +
((int64_t)Cal_C1_6[4] * dT > > 7);
SENS = ((int64_t)Cal_C1_6[1] < < 15) +
((int64_t)Cal_C1_6[3] * dT > > 8);
if(TEMP < 2000)
{
T2 = (dT * dT) > > 31;
OFF2 = (5 * (TEMP - 2000) * (TEMP - 2000)) > > 1;
SENS2 = (5 * (TEMP - 2000) * (TEMP - 2000)) > > 2;
if(TEMP < -1500)
{
OFF2 += 7 * (TEMP + 1500) * (TEMP + 1500);
SENS2 += (11 * (TEMP + 1500) * (TEMP + 1500)) > > 1;
}
TEMP -= T2;
OFF -= OFF2;
SENS -= SENS2;
}
P = (((D1 * SENS) > > 21) - OFF) > > 15;
return P / 100.0f - 10.0f;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Serial.h"
#include "ms5611.h"
#include "oled.h"
float temp, pressure;
int main(void)
{
Serial_Init();
MS5611_Init();
MS5611_Reset();
Delay_ms(300);
MS5611_Read_PROM();
OLED_Init();
OLED_ShowString(0,0,"MS5611",16,1);
OLED_ShowChinese(0,18,0,16,1);
OLED_ShowChinese(18,18,1,16,1);
OLED_ShowString(34,18,": ",16,1);
OLED_ShowChinese(70,18,2,16,1);
OLED_ShowChinese(0,36,3,16,1);
OLED_ShowChinese(18,36,4,16,1);
OLED_ShowString(34,36,": ",16,1);
OLED_ShowString(100,36,"HPa",16,1);
OLED_Refresh();
printf("MS5611rn");
while (1)
{
temp = Get_TEMP();
pressure = Get_pressure();
OLED_ShowNum(46,18,temp,2,16,1);
OLED_ShowNum(46,36,pressure,4,16,1);
OLED_ShowString(80,36,".",16,1);
OLED_ShowNum(86,36,(uint32_t)(pressure*10)/10,1,16,1);
OLED_Refresh();
//输出温度
printf("温度 = %.0f℃rn",temp );
//输出气压
printf("气压 = %.2fHParn",pressure );
printf("n");
Delay_ms(1000);
}
}
效果展示

-
传感器
+关注
关注
2578文章
55894浏览量
795824 -
接口
+关注
关注
33文章
9648浏览量
157849 -
STM32F103
+关注
关注
34文章
501浏览量
68426
发布评论请先 登录
一文看懂ms5611性能参数及典型应用
【经验交流】使用MS5611高精度气压计之后的感想
STM32F10X + MS5611 + JLink 测气压温度例程详解
使用IIC调试MS5611时读取压力值和温度值发送地址后芯片就没响应了
STM32+MS5611测气压温度例程详解
气压传感器bmp280与ms5611哪个好
STM32F0+MPU9250(with MS5611)的姿态解析算法移植(MahonyAHRS)
STM32F0+MPU9250(with MS5611)的姿态解析算法移植(MahonyAHRS)
MS5607与MS5611气压传感器怎么选择
基于STM32F103驱动MS5611读取气压与温度数据
评论