BMP180 大气压传感器

STM32F103C8T6 · HAL库 · 软件I2C通信
+5V
工作电压
300-1100 hPa
气压量程
I2C
通信方式
0x77
I2C地址
-40~85°C
温度量程

01传感器原理与功能

BMP180 是 Bosch 旗下高精度数字气压传感器,基于 MEMS 技术实现大气压与温度的同步测量

1.1 工作原理

BMP180 内部核心是一个 MEMS 微机电气压传感器,采用压阻式原理。传感器内部有一层极薄的硅膜片,当外部大气压变化时,膜片产生微小形变,膜片上的压阻元件阻值随之改变。通过内部 ADC 将阻值变化转换为数字信号,输出未补偿的气压原始值(UP)。

同时,BMP180 内部集成了一个 温度传感器,用于测量芯片温度。温度数据不仅用于温度补偿(修正气压读数因温度漂移产生的误差),还可独立输出环境温度值。每个 BMP180 出厂时都在 EEPROM 中烧录了 11 个校准系数(AC1~AC6, B1, B2, MB, MC, MD),用户读取后按照 datasheet 规定的算法进行多步补偿计算,即可得到精确的气压和温度值。

海拔高度则通过 国际标准大气压公式计算:已知当前气压和海平面参考气压,利用气压-高度的指数关系反推海拔。公式为 h = 44330 × (1 - (P/P₀)^(1/5.255))。

1.2 核心功能

🌡️

温度测量

内置温度传感器,分辨率 0.1°C,量程 -40~85°C。用于气压补偿和独立温度输出。

📊

气压测量

压阻式 MEMS 传感器,量程 300~1100 hPa,分辨率最高 0.01 hPa(OSS3 模式)。

⛰️

海拔计算

基于标准大气压公式,由当前气压和海平面参考气压换算海拔高度,分辨率 0.1m。

⚙️

过采样可调

支持 OSS0~OSS3 四种过采样模式,在精度与功耗之间灵活平衡,转换时间 4.5~25.5ms。

1.3 引脚定义

引脚名称功能STM32 连接
1VCC电源正极(模块输入+5V,板载降压至3.3V)+5V
2GND电源地GND
3SCLI2C 时钟线PB1(软件I2C)
4SDAI2C 数据线PB0(软件I2C)

02模块外观展示

BMP180 传感器模块实物外观与尺寸

外观1
模块正面
外观2
模块背面
尺寸
模块尺寸

03原理图与PCB封装

模块电路原理图与 PCB 封装设计

原理图
PCB封装

04程序分析

基于 STM32F103C8T6 + HAL 库,软件模拟 I2C 通信,500ms 周期读取传感器数据

4.1 系统初始化

main() — 主函数入口

系统启动后依次执行:HAL 初始化 → 时钟配置(HSE 8MHz × PLL9 = 72MHz)→ GPIO 初始化 → OLED 初始化 → BMP180 初始化(I2C 初始化 + 读取校准系数)。

Core/Src/main.c
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); OLED_Init(); BMP180_Init(); while (1) { if(HAL_GetTick() - Time_Now >= 500) { BMP180_GetData(BMP180_OSS0); OLED_Clear(); OLED_CenterPrintf(0, "芯片温度:%.1f℃", bmp180.Temp/10.0); OLED_CenterPrintf(24, "气压:%.2fhPa", bmp180.Press/100.0); OLED_CenterPrintf(48, "海拔:%.1fm", bmp180.Altitude); OLED_Update(); Time_Now = HAL_GetTick(); } } }

4.2 BMP180 I2C 通信初始化

BMP180_IIC_init() — 软件 I2C GPIO 配置

使用 PB1 作为 SCL(推挽输出),PB0 作为 SDA(开漏输出),均上拉,高速模式。通过宏定义直接操作 GPIO 引脚电平,实现软件模拟 I2C 协议。

HAL/BMP180/BMP180.c
// 引脚定义 #define BMP180_SCL_GPIO_PORT GPIOB #define BMP180_SCL_GPIO_PIN GPIO_PIN_1 #define BMP180_SDA_GPIO_PORT GPIOB #define BMP180_SDA_GPIO_PIN GPIO_PIN_0 // I2C 地址:0xEE(写) / 0xEF(读) → 7位地址 0x77 static void BMP180_IIC_init(void) { GPIO_InitTypeDef gpio_init_struct; BMP180_SCL_GPIO_CLK_ENABLE(); BMP180_SDA_GPIO_CLK_ENABLE(); // SCL: 推挽输出,上拉 gpio_init_struct.Pin = BMP180_SCL_GPIO_PIN; gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; gpio_init_struct.Pull = GPIO_PULLUP; gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(BMP180_SCL_GPIO_PORT, &gpio_init_struct); // SDA: 开漏输出,上拉(支持双向通信) gpio_init_struct.Pin = BMP180_SDA_GPIO_PIN; gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD; HAL_GPIO_Init(BMP180_SDA_GPIO_PORT, &gpio_init_struct); BMP180_stop(); }

4.3 校准系数读取

BMP180_ReadCalibrationData() — 读取 EEPROM 校准数据

BMP180 出厂时在内部 EEPROM 中烧录了 11 个校准系数,地址范围 0xAA ~ 0xBE。其中 AC1/AC2/AC3/B1/B2/MB/MC/MD 为有符号 16 位,AC4/AC5/AC6 为无符号 16 位。这些系数是后续温度和气压补偿计算的基础。

HAL/BMP180/BMP180.c
static void BMP180_ReadCalibrationData(void) { bmp180.AC1 = BMP180_ReadTwoByte_S(0xAA); bmp180.AC2 = BMP180_ReadTwoByte_S(0xAC); bmp180.AC3 = BMP180_ReadTwoByte_S(0xAE); bmp180.AC4 = BMP180_ReadTwoByte_U(0xB0); bmp180.AC5 = BMP180_ReadTwoByte_U(0xB2); bmp180.AC6 = BMP180_ReadTwoByte_U(0xB4); bmp180.B1 = BMP180_ReadTwoByte_S(0xB6); bmp180.B2 = BMP180_ReadTwoByte_S(0xB8); bmp180.MB = BMP180_ReadTwoByte_S(0xBA); bmp180.MC = BMP180_ReadTwoByte_S(0xBC); bmp180.MD = BMP180_ReadTwoByte_S(0xBE); }
寄存器地址系数类型用途
0xAA / 0xABAC1int16_t气压补偿
0xAC / 0xADAC2int16_t气压补偿
0xAE / 0xAFAC3int16_t气压补偿
0xB0 / 0xB1AC4uint16_t气压补偿
0xB2 / 0xB3AC5uint16_t温度补偿
0xB4 / 0xB5AC6uint16_t温度补偿
0xB6 / 0xB7B1int16_t气压补偿
0xB8 / 0xB9B2int16_t气压补偿
0xBA / 0xBBMBint16_t保留
0xBC / 0xBDMCint16_t温度补偿
0xBE / 0xBFMDint16_t温度补偿

4.4 温度原始数据读取

BMP180_Read_UT() — 读取未补偿温度值

向控制寄存器 0xF4 写入 0x2E 启动温度转换,等待 5ms 后从数据寄存器 0xF6 读取 2 字节原始温度值(UT)。

HAL/BMP180/BMP180.c
static int32_t BMP180_Read_UT(void) { BMP180_WriteOneByte(0xF4, 0x2E); // 启动温度转换 HAL_Delay(5); // 等待转换完成 return (int32_t)BMP180_ReadTwoByte_S(0xF6); }

4.5 气压原始数据读取

BMP180_Read_UP() — 读取未补偿气压值

向控制寄存器 0xF4 写入 0x34 + (oss << 6) 启动气压转换。不同过采样等级对应不同等待时间:OSS0=5ms, OSS1=8ms, OSS2=14ms, OSS3=26ms。读取 3 字节数据(MSB, LSB, XLSB),右移 (8-oss) 位得到原始气压值(UP)。

HAL/BMP180/BMP180.c
static int32_t BMP180_Read_UP(BMP180_OSS_t oss) { uint8_t ctrl; uint32_t delay_tbl[] = {5, 8, 14, 26}; ctrl = 0x34 + (oss << 6); BMP180_WriteOneByte(0xF4, ctrl); HAL_Delay(delay_tbl[oss]); // 读取 3 字节: MSB, LSB, XLSB msb = BMP180_read_byte(1); lsb = BMP180_read_byte(1); xlsb = BMP180_read_byte(0); int32_t raw = (msb << 16) | (lsb << 8) | xlsb; raw >>= (8 - oss); return raw; }
OSS 等级模式内部采样数转换时间分辨率
OSS0Ultra Low Power14.5ms0.06 hPa
OSS1Standard27.5ms0.05 hPa
OSS2High413.5ms0.04 hPa
OSS3Ultra High825.5ms0.03 hPa

4.6 温度补偿计算

温度补偿算法

利用校准系数 AC5, AC6, MC, MD 对原始温度 UT 进行补偿计算,得到真实温度值(单位 0.1°C)。最终 bmp180.Temp 除以 10 即为摄氏度。

HAL/BMP180/BMP180.c
// 温度补偿计算 bmp180.X1 = ((bmp180.UT - bmp180.AC6) * bmp180.AC5) >> 15; bmp180.X2 = (((int32_t)bmp180.MC << 11)) / (bmp180.X1 + bmp180.MD); bmp180.B5 = bmp180.X1 + bmp180.X2; bmp180.Temp = (bmp180.B5 + 8) >> 4; // 单位 0.1℃ /* 计算公式解析: X1 = (UT - AC6) × AC5 / 2^15 X2 = MC × 2^11 / (X1 + MD) B5 = X1 + X2 T = (B5 + 8) / 2^4 → 单位 0.1℃ 实际温度(℃) = T / 10 */

4.7 气压补偿计算

气压补偿算法

气压补偿是最复杂的部分,涉及多个中间变量(B3, B4, B6, B7, X1, X2, X3)。计算过程分为:先由 B5 计算 B6,再通过 AC1/AC2/AC3/B1/B2 计算 X1/X2/X3,然后计算 B3 和 B4,接着用 B7/B4 得到初步气压值,最后进行多项式修正得到最终气压(单位 Pa)。

HAL/BMP180/BMP180.c
// 气压补偿计算 bmp180.B6 = bmp180.B5 - 4000; bmp180.X1 = ((int32_t)bmp180.B2 * ((bmp180.B6 * bmp180.B6) >> 12)) >> 11; bmp180.X2 = ((int32_t)bmp180.AC2 * bmp180.B6) >> 11; bmp180.X3 = bmp180.X1 + bmp180.X2; bmp180.B3 = ((((int32_t)bmp180.AC1 << 2) + bmp180.X3) + 2) >> 2; bmp180.X1 = ((int32_t)bmp180.AC3 * bmp180.B6) >> 13; bmp180.X2 = (((int32_t)bmp180.B1 * ((bmp180.B6 * bmp180.B6) >> 12))) >> 16; bmp180.X3 = ((bmp180.X1 + bmp180.X2) + 2) >> 2; bmp180.B4 = ((uint32_t)bmp180.AC4 * (bmp180.X3 + 32768UL)) >> 15; bmp180.B7 = ((uint32_t)(bmp180.UP - bmp180.B3)) * 50000UL; if(bmp180.B7 < 0x80000000UL) bmp180.Press = (bmp180.B7 * 2UL) / bmp180.B4; else bmp180.Press = (bmp180.B7 / bmp180.B4) * 2UL; // 多项式修正 bmp180.X1 = (bmp180.Press >> 8) * (bmp180.Press >> 8); bmp180.X1 = ((int32_t)bmp180.X1 * 3038) >> 16; bmp180.X2 = (-7357 * bmp180.Press) >> 16; bmp180.Press = bmp180.Press + ((bmp180.X1 + bmp180.X2 + 3791) >> 4);

4.8 海拔计算

海拔计算 — 国际标准大气压公式

利用当前气压和海平面参考气压(SEA_LEVEL_PRESSURE),通过气压-高度指数关系计算海拔。代码中使用 100400.0 Pa(约 1004.0 hPa)作为当地海平面气压参考值。海拔 = 44330 × (1 - (P/P₀)^(1/5.255))。

HAL/BMP180/BMP180.c
// 用户配置:当地海平面气压 (Pa) #define SEA_LEVEL_PRESSURE 100400.0f // 海拔计算 bmp180.Altitude = 44330.0f * (1.0f - powf( ((float)bmp180.Press / SEA_LEVEL_PRESSURE), (1.0f/5.255f) )); /* 公式解析: h = 44330 × (1 - (P / P0)^(1/5.255)) P : 当前实测气压 (Pa) P0 : 海平面参考气压 (Pa),需根据当地天气预报设置 h : 海拔高度 (m) 示例:P=100400Pa → h≈0m P=90000Pa → h≈914m */

4.9 主循环与 OLED 显示

while(1) — 主循环数据刷新

主循环以 500ms 为周期,通过 HAL_GetTick() 计时。每次更新调用 BMP180_GetData(OSS0) 读取并计算数据,然后清屏并在 OLED 上居中显示三行信息:芯片温度、气压、海拔。OLED 使用独立的软件 I2C(PB14=SDA, PB15=SCL)。

Core/Src/main.c
while (1) { if(HAL_GetTick() - Time_Now >= 500) // 500ms 更新一次 { BMP180_GetData(BMP180_OSS0); // 读取温压数据 OLED_Clear(); // 清屏 OLED_CenterPrintf(0, "芯片温度:%.1f℃", bmp180.Temp/10.0); OLED_CenterPrintf(24, "气压:%.2fhPa", bmp180.Press/100.0); OLED_CenterPrintf(48, "海拔:%.1fm", bmp180.Altitude); OLED_Update(); // 刷新显示 Time_Now = HAL_GetTick(); // 更新时间戳 } }

4.10 数据值对照表

参数变量单位显示转换典型值
芯片温度bmp180.Temp0.1°C÷10 → °C25.0°C
气压bmp180.PressPa÷100 → hPa1004.00 hPa
海拔bmp180.Altitudem直接显示0.0m

05程序流程图

系统启动 → 初始化 → while(1) 主循环数据采集与显示

开始 HAL_Init() SystemClock_Config() MX_GPIO_Init() OLED_Init() BMP180_Init() while(1) HAL_GetTick() - Time_Now ≥ 500? 否 是 BMP180_GetData(OSS0) OLED_Clear() OLED显示: 温度/气压/海拔 OLED_Update() Time_Now = HAL_GetTick()