STM32F103 驱动 BMP180 气压传感器源码

一、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 优化建议

  1. 软件滤波:对气压数据进行滑动平均滤波
  2. 温度补偿:根据环境温度调整气压读数
  3. 海拔校准:在已知海拔处进行零点校准
  4. 低功耗:测量完成后关闭传感器电源

四、数据验证示例

复制代码
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
------------------------
相关推荐
踏着七彩祥云的小丑1 小时前
嵌入式测试学习第 5 天:电阻分类、色环电阻读数、贴片电阻
单片机·嵌入式硬件
济6171 小时前
MonitorTask 系统监控任务(下篇)---完善堆内存 、任务栈监控
单片机·嵌入式·freertos
代码又报错la2 小时前
5、电源保护板
单片机·嵌入式硬件
leo__52010 小时前
STM32 MAX30102 心率血氧测量代码
stm32·单片机·嵌入式硬件
金色光环14 小时前
【DSP学习】DSP28335 点亮LED
嵌入式硬件·学习·dsp开发
yuan1999714 小时前
STM32 IAP 电量计源码
stm32·单片机·嵌入式硬件
学不懂飞行器14 小时前
从小白到国奖:全国大学生电子设计竞赛(电赛)高质量备赛全攻略
stm32·单片机·嵌入式硬件
perseverance5215 小时前
STM32F405 ADC+DMA双缓冲规则组采集
stm32·adc
高翔·权衡之境15 小时前
缓存一致性——多核系统的默契之约
驱动开发·嵌入式硬件·安全·缓存·系统安全·信息与通信