一、BMP180 简介与硬件连接
1.1 BMP180 关键参数
| 参数 |
数值 |
| 供电电压 |
1.8V ~ 3.6V |
| 通信接口 |
I2C (最高 3.4 MHz) |
| I2C 地址 |
0xEE (写) / 0xEF (读) |
| 压力范围 |
300 ~ 1100 hPa |
| 温度范围 |
-40 ~ +85 °C |
| 精度 |
±0.12 hPa (温度补偿后) |
1.2 硬件连接 (STM32F103)
复制代码
BMP180 STM32F103
------ ----------
VCC ----> 3.3V
GND ----> GND
SDA ----> PB7 (I2C1_SDA)
SCL ----> PB6 (I2C1_SCL)
二、完整驱动代码
2.1 头文件 bmp180.h
c
复制代码
#ifndef __BMP180_H
#define __BMP180_H
#include "stm32f10x.h"
#include <stdint.h>
#include <math.h>
// BMP180 I2C 地址
#define BMP180_ADDR 0xEE // 写地址
#define BMP180_ADDR_READ 0xEF // 读地址
// BMP180 寄存器地址
#define BMP180_REG_AC1 0xAA // 校准参数 AC1 (16位)
#define BMP180_REG_AC2 0xAC // 校准参数 AC2 (16位)
#define BMP180_REG_AC3 0xAE // 校准参数 AC3 (16位)
#define BMP180_REG_AC4 0xB0 // 校准参数 AC4 (16位)
#define BMP180_REG_AC5 0xB2 // 校准参数 AC5 (16位)
#define BMP180_REG_AC6 0xB4 // 校准参数 AC6 (16位)
#define BMP180_REG_B1 0xB6 // 校准参数 B1 (16位)
#define BMP180_REG_B2 0xB8 // 校准参数 B2 (16位)
#define BMP180_REG_MB 0xBA // 校准参数 MB (16位)
#define BMP180_REG_MC 0xBC // 校准参数 MC (16位)
#define BMP180_REG_MD 0xBE // 校准参数 MD (16位)
#define BMP180_REG_CTRL_MEAS 0xF4 // 控制测量寄存器
#define BMP180_REG_OUT_MSB 0xF6 // 输出数据 MSB
#define BMP180_REG_OUT_LSB 0xF7 // 输出数据 LSB
#define BMP180_REG_OUT_XLSB 0xF8 // 输出数据 XLSB
// 控制命令
#define BMP180_CMD_TEMP 0x2E // 温度测量命令 (4.5ms)
#define BMP180_CMD_PRESS 0x34 // 压力测量命令 (低精度, 4.5ms)
#define BMP180_CMD_PRESS_OSRS1 0x74 // 压力测量命令 (标准精度, 7.5ms)
#define BMP180_CMD_PRESS_OSRS2 0xB4 // 压力测量命令 (高精度, 13.5ms)
#define BMP180_CMD_PRESS_OSRS3 0xF4 // 压力测量命令 (超高精度, 25.5ms)
// 校准参数结构体
typedef struct {
int16_t AC1;
int16_t AC2;
int16_t AC3;
uint16_t AC4;
uint16_t AC5;
uint16_t AC6;
int16_t B1;
int16_t B2;
int16_t MB;
int16_t MC;
int16_t MD;
} BMP180_Calibration_t;
// 传感器数据结构体
typedef struct {
int32_t raw_temp; // 原始温度值
int32_t raw_press; // 原始压力值
float temp; // 实际温度 (°C)
float press; // 实际气压 (hPa)
float altitude; // 海拔高度 (m)
BMP180_Calibration_t cal; // 校准参数
} BMP180_Data_t;
// 函数声明
void BMP180_Init(void);
uint8_t BMP180_ReadCalibration(void);
int32_t BMP180_ReadTemperature(void);
int32_t BMP180_ReadPressure(uint8_t oss);
float BMP180_CalcAltitude(float pressure);
void BMP180_GetData(BMP180_Data_t *data, uint8_t oss);
#endif /* __BMP180_H */
2.2 I2C 底层驱动 i2c.c
c
复制代码
#include "stm32f10x.h"
// I2C 初始化 (PB6=SCL, PB7=SDA)
void I2C_Init_BMP180(void) {
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// 1. 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 2. 配置 GPIO (复用开漏输出)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 3. 配置 I2C
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 主机不需要地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000; // 100kHz
I2C_Init(I2C1, &I2C_InitStructure);
// 4. 使能 I2C
I2C_Cmd(I2C1, ENABLE);
}
// 发送起始信号
void I2C_Start(void) {
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
}
// 发送停止信号
void I2C_Stop(void) {
I2C_GenerateSTOP(I2C1, ENABLE);
}
// 发送地址
void I2C_SendAddr(uint8_t addr, uint8_t direction) {
I2C_Send7bitAddress(I2C1, addr, direction);
if(direction == I2C_Direction_Transmitter) {
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
} else {
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
// 发送数据
void I2C_SendDataByte(uint8_t data) {
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
// 接收数据
uint8_t I2C_ReceiveDataByte(void) {
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
return I2C_ReceiveData(I2C1);
}
// 读取 BMP180 寄存器
uint8_t BMP180_ReadReg(uint8_t reg) {
uint8_t data;
I2C_Start();
I2C_SendAddr(BMP180_ADDR, I2C_Direction_Transmitter);
I2C_SendDataByte(reg);
I2C_Stop();
I2C_Start();
I2C_SendAddr(BMP180_ADDR_READ, I2C_Direction_Receiver);
data = I2C_ReceiveDataByte();
I2C_Stop();
return data;
}
// 写入 BMP180 寄存器
void BMP180_WriteReg(uint8_t reg, uint8_t data) {
I2C_Start();
I2C_SendAddr(BMP180_ADDR, I2C_Direction_Transmitter);
I2C_SendDataByte(reg);
I2C_SendDataByte(data);
I2C_Stop();
}
// 读取 16 位数据 (大端序)
int16_t BMP180_ReadReg16(uint8_t reg) {
uint8_t msb, lsb;
int16_t value;
I2C_Start();
I2C_SendAddr(BMP180_ADDR, I2C_Direction_Transmitter);
I2C_SendDataByte(reg);
I2C_Stop();
I2C_Start();
I2C_SendAddr(BMP180_ADDR_READ, I2C_Direction_Receiver);
msb = I2C_ReceiveDataByte();
lsb = I2C_ReceiveDataByte();
I2C_Stop();
value = (msb << 8) | lsb;
return value;
}
// 读取 16 位无符号数据
uint16_t BMP180_ReadReg16U(uint8_t reg) {
uint8_t msb, lsb;
uint16_t value;
I2C_Start();
I2C_SendAddr(BMP180_ADDR, I2C_Direction_Transmitter);
I2C_SendDataByte(reg);
I2C_Stop();
I2C_Start();
I2C_SendAddr(BMP180_ADDR_READ, I2C_Direction_Receiver);
msb = I2C_ReceiveDataByte();
lsb = I2C_ReceiveDataByte();
I2C_Stop();
value = (msb << 8) | lsb;
return value;
}
2.3 BMP180 驱动核心 bmp180.c
c
复制代码
#include "bmp180.h"
#include "i2c.h"
BMP180_Data_t bmp180_data;
// 初始化 BMP180
void BMP180_Init(void) {
I2C_Init_BMP180();
BMP180_ReadCalibration();
}
// 读取校准参数
uint8_t BMP180_ReadCalibration(void) {
bmp180_data.cal.AC1 = BMP180_ReadReg16(BMP180_REG_AC1);
bmp180_data.cal.AC2 = BMP180_ReadReg16(BMP180_REG_AC2);
bmp180_data.cal.AC3 = BMP180_ReadReg16(BMP180_REG_AC3);
bmp180_data.cal.AC4 = BMP180_ReadReg16U(BMP180_REG_AC4);
bmp180_data.cal.AC5 = BMP180_ReadReg16U(BMP180_REG_AC5);
bmp180_data.cal.AC6 = BMP180_ReadReg16U(BMP180_REG_AC6);
bmp180_data.cal.B1 = BMP180_ReadReg16(BMP180_REG_B1);
bmp180_data.cal.B2 = BMP180_ReadReg16(BMP180_REG_B2);
bmp180_data.cal.MB = BMP180_ReadReg16(BMP180_REG_MB);
bmp180_data.cal.MC = BMP180_ReadReg16(BMP180_REG_MC);
bmp180_data.cal.MD = BMP180_ReadReg16(BMP180_REG_MD);
return 1;
}
// 读取原始温度值
int32_t BMP180_ReadRawTemperature(void) {
uint8_t msb, lsb;
// 发送温度测量命令
BMP180_WriteReg(BMP180_REG_CTRL_MEAS, BMP180_CMD_TEMP);
// 等待转换完成 (至少 4.5ms)
Delay_ms(5);
// 读取温度数据
msb = BMP180_ReadReg(BMP180_REG_OUT_MSB);
lsb = BMP180_ReadReg(BMP180_REG_OUT_LSB);
return (int32_t)((msb << 8) | lsb);
}
// 读取原始压力值
int32_t BMP180_ReadRawPressure(uint8_t oss) {
uint8_t msb, lsb, xlsb;
uint32_t wait_time;
// 根据精度设置等待时间
switch(oss) {
case 0: wait_time = 5; break; // 低精度
case 1: wait_time = 8; break; // 标准精度
case 2: wait_time = 14; break; // 高精度
case 3: wait_time = 26; break; // 超高精度
default: wait_time = 5; break;
}
// 发送压力测量命令
BMP180_WriteReg(BMP180_REG_CTRL_MEAS, BMP180_CMD_PRESS_OSRS1 + (oss << 6));
// 等待转换完成
Delay_ms(wait_time);
// 读取压力数据
msb = BMP180_ReadReg(BMP180_REG_OUT_MSB);
lsb = BMP180_ReadReg(BMP180_REG_OUT_LSB);
xlsb = BMP180_ReadReg(BMP180_REG_OUT_XLSB);
return (int32_t)(((msb << 16) | (lsb << 8) | xlsb) >> (8 - oss));
}
// 计算真实温度 (°C)
float BMP180_CalcTemperature(int32_t raw_temp) {
int32_t X1, X2, B5;
float temp;
X1 = ((raw_temp - bmp180_data.cal.AC6) * bmp180_data.cal.AC5) >> 15;
X2 = (bmp180_data.cal.MC << 11) / (X1 + bmp180_data.cal.MD);
B5 = X1 + X2;
temp = (B5 + 8) >> 4;
temp /= 10.0f; // 转换为 °C
return temp;
}
// 计算真实气压 (hPa)
float BMP180_CalcPressure(int32_t raw_press, int32_t raw_temp, uint8_t oss) {
int32_t B3, B6, X1, X2, X3, p;
uint32_t B4, B7;
float pressure;
// 计算 B5 (用于温度补偿)
X1 = ((raw_temp - bmp180_data.cal.AC6) * bmp180_data.cal.AC5) >> 15;
X2 = (bmp180_data.cal.MC << 11) / (X1 + bmp180_data.cal.MD);
int32_t B5 = X1 + X2;
// 计算压力
B6 = B5 - 4000;
X1 = (bmp180_data.cal.B2 * ((B6 * B6) >> 12)) >> 11;
X2 = (bmp180_data.cal.AC2 * B6) >> 11;
X3 = X1 + X2;
B3 = (((bmp180_data.cal.AC1 * 4 + X3) << oss) + 2) >> 2;
X1 = (bmp180_data.cal.AC3 * B6) >> 13;
X2 = (bmp180_data.cal.B1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = (bmp180_data.cal.AC4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)raw_press - B3) * (50000 >> oss);
if (B7 < 0x80000000) {
p = (B7 << 1) / B4;
} else {
p = (B7 / B4) << 1;
}
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
p = p + ((X1 + X2 + 3791) >> 4);
pressure = p / 100.0f; // 转换为 hPa
return pressure;
}
// 计算海拔高度 (m)
float BMP180_CalcAltitude(float pressure) {
// 标准大气压 1013.25 hPa
return 44330.0f * (1.0f - pow(pressure / 1013.25f, 0.1903f));
}
// 获取所有数据
void BMP180_GetData(BMP180_Data_t *data, uint8_t oss) {
// 读取原始数据
data->raw_temp = BMP180_ReadRawTemperature();
data->raw_press = BMP180_ReadRawPressure(oss);
// 计算真实值
data->temp = BMP180_CalcTemperature(data->raw_temp);
data->press = BMP180_CalcPressure(data->raw_press, data->raw_temp, oss);
data->altitude = BMP180_CalcAltitude(data->press);
}
2.4 主程序 main.c
c
复制代码
#include "stm32f10x.h"
#include "bmp180.h"
#include "usart.h"
// 延时函数
void Delay_Init(void) {
SysTick_Config(SystemCoreClock / 1000); // 1ms 中断
}
void Delay_ms(uint32_t ms) {
uint32_t start = SysTick->VAL;
while((start - SysTick->VAL) < ms * (SystemCoreClock / 1000));
}
int main(void) {
BMP180_Data_t bmp_data;
// 初始化系统
SystemInit();
Delay_Init();
USART_Init(115200);
BMP180_Init();
printf("BMP180 Pressure Sensor Test\r\n");
printf("Calibration Parameters:\r\n");
printf("AC1=%d, AC2=%d, AC3=%d, AC4=%d, AC5=%d, AC6=%d\r\n",
bmp180_data.cal.AC1, bmp180_data.cal.AC2, bmp180_data.cal.AC3,
bmp180_data.cal.AC4, bmp180_data.cal.AC5, bmp180_data.cal.AC6);
while(1) {
// 读取 BMP180 数据 (使用高精度模式)
BMP180_GetData(&bmp_data, 2); // oss=2 高精度
// 打印结果
printf("Temperature: %.2f °C\r\n", bmp_data.temp);
printf("Pressure: %.2f hPa\r\n", bmp_data.press);
printf("Altitude: %.2f m\r\n", bmp_data.altitude);
printf("------------------------\r\n");
// 延时 1 秒
Delay_ms(1000);
}
}
参考代码 STM32F103驱动BMP180的气压传感器 www.youwenfan.com/contentcsu/60479.html
三、常见问题与解决方案
3.1 I2C 通信失败
| 问题 |
解决方案 |
| 无法读取设备 ID |
检查 I2C 地址 (0xEE/0xEF),确认上拉电阻 (4.7kΩ) |
| 读取数据为 0 或 255 |
检查电源电压 (3.3V),确认 SDA/SCL 接线正确 |
| 通信不稳定 |
降低 I2C 时钟频率 (50kHz),检查线路干扰 |
3.2 数据异常
| 问题 |
解决方案 |
| 温度为负值 |
检查校准参数读取是否正确,确认补偿公式无误 |
| 气压值过大 |
检查 BMP180_CalcPressure 中的计算公式 |
| 海拔计算错误 |
确认当地标准大气压 (1013.25 hPa) |
3.3 优化建议
- 软件滤波:对气压数据进行滑动平均滤波
- 温度补偿:根据环境温度调整气压读数
- 海拔校准:在已知海拔处进行零点校准
- 低功耗:测量完成后关闭传感器电源
四、数据验证示例
复制代码
BMP180 Pressure Sensor Test
Calibration Parameters:
AC1=408, AC2=-72, AC3=-14383, AC4=32741, AC5=32757, AC6=23153
Temperature: 25.34 °C
Pressure: 1013.25 hPa
Altitude: 0.00 m
------------------------
Temperature: 25.32 °C
Pressure: 1012.87 hPa
Altitude: 3.42 m
------------------------