STM32 BMP280 I2C通信驱动程序

BMP280气压温度传感器的I2C通信驱动程序,包含高精度测量、温度补偿、数据滤波、多种工作模式等功能。

一、硬件连接与配置

1.1 BMP280引脚定义

复制代码
BMP280 (LGA-8封装)
├── VCC  → 3.3V
├── GND  → GND
├── SCL  → I2C时钟线
├── SDA  → I2C数据线
└── CSB  → 接VCC (I2C模式)
    SDO  → 接地(地址0x76) 或 接VCC(地址0x77)

1.2 STM32连接

复制代码
STM32F103C8T6
├── I2C1
│   ├── SCL → PB6
│   └── SDA → PB7
├── 或 I2C2
│   ├── SCL → PB10
│   └── SDA → PB11
└── 电源
    ├── 3.3V → BMP280 VCC
    └── GND  → BMP280 GND

二、核心驱动代码

2.1 BMP280驱动头文件

c 复制代码
/**
 * @file bmp280.h
 * @brief BMP280气压温度传感器驱动
 */

#ifndef __BMP280_H
#define __BMP280_H

#include "stm32f1xx_hal.h"
#include <stdint.h>
#include <stdbool.h>
#include <math.h>

/* BMP280 I2C地址 */
#define BMP280_I2C_ADDR_WRITE      0xEC  // 写地址 (0x76 << 1)
#define BMP280_I2C_ADDR_READ       0xED  // 读地址 (0x76 << 1 | 1)
#define BMP280_I2C_ADDR_WRITE_2    0xEE  // 备用写地址 (0x77 << 1)
#define BMP280_I2C_ADDR_READ_2     0xEF  // 备用读地址 (0x77 << 1 | 1)

/* BMP280寄存器定义 */
#define BMP280_REG_ID              0xD0
#define BMP280_REG_RESET           0xE0
#define BMP280_REG_STATUS          0xF3
#define BMP280_REG_CTRL_MEAS       0xF4
#define BMP280_REG_CONFIG          0xF5
#define BMP280_REG_PRESS_MSB       0xF7
#define BMP280_REG_PRESS_LSB       0xF8
#define BMP280_REG_PRESS_XLSB      0xF9
#define BMP280_REG_TEMP_MSB        0xFA
#define BMP280_REG_TEMP_LSB        0xFB
#define BMP280_REG_TEMP_XLSB       0xFC
#define BMP280_REG_CALIB_START     0x88
#define BMP280_REG_CALIB_END       0xA1

/* BMP280复位值 */
#define BMP280_RESET_VALUE         0xB6

/* BMP280芯片ID */
#define BMP280_CHIP_ID             0x58

/* 工作模式 */
typedef enum {
    BMP280_MODE_SLEEP = 0,      // 睡眠模式
    BMP280_MODE_FORCED = 1,     // 强制模式
    BMP280_MODE_FORCED_2 = 2,   // 强制模式2
    BMP280_MODE_NORMAL = 3      // 正常模式
} BMP280_Mode;

/* 过采样率 */
typedef enum {
    BMP280_OSR_SKIP = 0,        // 跳过
    BMP280_OSR_X1 = 1,          // 1倍
    BMP280_OSR_X2 = 2,          // 2倍
    BMP280_OSR_X4 = 3,          // 4倍
    BMP280_OSR_X8 = 4,          // 8倍
    BMP280_OSR_X16 = 5          // 16倍
} BMP280_Oversampling;

/* 滤波器系数 */
typedef enum {
    BMP280_FILTER_OFF = 0,      // 关闭滤波器
    BMP280_FILTER_2 = 1,        // 系数2
    BMP280_FILTER_4 = 2,        // 系数4
    BMP280_FILTER_8 = 3,        // 系数8
    BMP280_FILTER_16 = 4        // 系数16
} BMP280_Filter;

/* 待机时间 (ms) */
typedef enum {
    BMP280_STANDBY_0_5 = 0,     // 0.5ms
    BMP280_STANDBY_62_5 = 1,    // 62.5ms
    BMP280_STANDBY_125 = 2,     // 125ms
    BMP280_STANDBY_250 = 3,     // 250ms
    BMP280_STANDBY_500 = 4,     // 500ms
    BMP280_STANDBY_1000 = 5,    // 1000ms
    BMP280_STANDBY_2000 = 6,    // 2000ms
    BMP280_STANDBY_4000 = 7     // 4000ms
} BMP280_StandbyTime;

/* 校准参数结构体 */
typedef struct {
    uint16_t dig_T1;    // 温度校准参数1
    int16_t  dig_T2;    // 温度校准参数2
    int16_t  dig_T3;    // 温度校准参数3
    
    uint16_t dig_P1;    // 气压校准参数1
    int16_t  dig_P2;    // 气压校准参数2
    int16_t  dig_P3;    // 气压校准参数3
    int16_t  dig_P4;    // 气压校准参数4
    int16_t  dig_P5;    // 气压校准参数5
    int16_t  dig_P6;    // 气压校准参数6
    int16_t  dig_P7;    // 气压校准参数7
    int16_t  dig_P8;    // 气压校准参数8
    int16_t  dig_P9;    // 气压校准参数9
    
    int32_t  t_fine;    // 精细温度值
} BMP280_CalibData;

/* BMP280设备结构体 */
typedef struct {
    I2C_HandleTypeDef *hi2c;        // I2C句柄
    uint8_t i2c_addr;               // I2C地址
    BMP280_CalibData calib_data;    // 校准数据
    BMP280_Mode mode;               // 工作模式
    BMP280_Oversampling osr_temp;   // 温度过采样
    BMP280_Oversampling osr_press;  // 气压过采样
    BMP280_Filter filter;           // 滤波器系数
    BMP280_StandbyTime standby;     // 待机时间
    uint8_t chip_id;                // 芯片ID
    uint8_t initialized;            // 初始化标志
} BMP280_Handle;

/* 测量结果结构体 */
typedef struct {
    float temperature;      // 温度 (°C)
    float pressure;         // 气压 (hPa)
    float altitude;         // 海拔高度 (m)
    uint32_t timestamp;     // 时间戳
} BMP280_Data;

/* 函数声明 */
uint8_t BMP280_Init(BMP280_Handle *bmp, I2C_HandleTypeDef *hi2c, uint8_t addr);
uint8_t BMP280_ReadID(BMP280_Handle *bmp);
uint8_t BMP280_Reset(BMP280_Handle *bmp);
uint8_t BMP280_ReadCalibration(BMP280_Handle *bmp);
uint8_t BMP280_SetConfig(BMP280_Handle *bmp);
uint8_t BMP280_StartMeasurement(BMP280_Handle *bmp);
uint8_t BMP280_IsMeasurementReady(BMP280_Handle *bmp);
uint8_t BMP280_ReadData(BMP280_Handle *bmp, BMP280_Data *data);
float BMP280_CalculateAltitude(float pressure, float sea_level_hpa);
float BMP280_CalculateSeaLevelPressure(float pressure, float altitude);
void BMP280_SetMode(BMP280_Handle *bmp, BMP280_Mode mode);
void BMP280_SetOversampling(BMP280_Handle *bmp, BMP280_Oversampling osr_temp, 
                           BMP280_Oversampling osr_press);
void BMP280_SetFilter(BMP280_Handle *bmp, BMP280_Filter filter);
void BMP280_SetStandby(BMP280_Handle *bmp, BMP280_StandbyTime standby);
void BMP280_PrintCalibration(BMP280_CalibData *calib);
void BMP280_PrintConfig(BMP280_Handle *bmp);

/* 海平面标准气压 */
#define SEA_LEVEL_PRESSURE_HPA     1013.25f

#endif /* __BMP280_H */

2.2 BMP280驱动实现

c 复制代码
/**
 * @file bmp280.c
 * @brief BMP280驱动实现
 */

#include "bmp280.h"

/* 全局变量 */
static uint8_t bmp280_buffer[24];
static BMP280_Data bmp280_data;

/**
 * @brief I2C写入一个字节
 */
static uint8_t BMP280_WriteByte(BMP280_Handle *bmp, uint8_t reg, uint8_t data)
{
    uint8_t tx_data[2] = {reg, data};
    
    if(HAL_I2C_Master_Transmit(bmp->hi2c, bmp->i2c_addr, tx_data, 2, 100) != HAL_OK)
    {
        return 1;  // 传输失败
    }
    
    return 0;  // 成功
}

/**
 * @brief I2C读取多个字节
 */
static uint8_t BMP280_ReadBytes(BMP280_Handle *bmp, uint8_t reg, uint8_t *data, uint8_t len)
{
    /* 先发送寄存器地址 */
    if(HAL_I2C_Master_Transmit(bmp->hi2c, bmp->i2c_addr, &reg, 1, 100) != HAL_OK)
    {
        return 1;
    }
    
    /* 然后读取数据 */
    if(HAL_I2C_Master_Receive(bmp->hi2c, bmp->i2c_addr, data, len, 100) != HAL_OK)
    {
        return 1;
    }
    
    return 0;
}

/**
 * @brief 初始化BMP280
 */
uint8_t BMP280_Init(BMP280_Handle *bmp, I2C_HandleTypeDef *hi2c, uint8_t addr)
{
    if(bmp == NULL || hi2c == NULL)
        return 1;
    
    /* 初始化结构体 */
    bmp->hi2c = hi2c;
    bmp->i2c_addr = addr;
    bmp->mode = BMP280_MODE_SLEEP;
    bmp->osr_temp = BMP280_OSR_X2;
    bmp->osr_press = BMP280_OSR_X16;
    bmp->filter = BMP280_FILTER_4;
    bmp->standby = BMP280_STANDBY_1000;
    bmp->initialized = 0;
    
    /* 1. 读取芯片ID */
    if(BMP280_ReadID(bmp) != 0)
    {
        printf("BMP280: Failed to read chip ID\n");
        return 2;
    }
    
    if(bmp->chip_id != BMP280_CHIP_ID)
    {
        printf("BMP280: Invalid chip ID: 0x%02X\n", bmp->chip_id);
        return 3;
    }
    
    printf("BMP280: Chip ID: 0x%02X\n", bmp->chip_id);
    
    /* 2. 复位芯片 */
    if(BMP280_Reset(bmp) != 0)
    {
        printf("BMP280: Reset failed\n");
        return 4;
    }
    
    HAL_Delay(10);  // 等待复位完成
    
    /* 3. 读取校准参数 */
    if(BMP280_ReadCalibration(bmp) != 0)
    {
        printf("BMP280: Failed to read calibration data\n");
        return 5;
    }
    
    /* 4. 配置传感器 */
    if(BMP280_SetConfig(bmp) != 0)
    {
        printf("BMP280: Failed to set configuration\n");
        return 6;
    }
    
    bmp->initialized = 1;
    printf("BMP280: Initialized successfully\n");
    
    return 0;
}

/**
 * @brief 读取芯片ID
 */
uint8_t BMP280_ReadID(BMP280_Handle *bmp)
{
    if(BMP280_ReadBytes(bmp, BMP280_REG_ID, &bmp->chip_id, 1) != 0)
    {
        return 1;
    }
    
    return 0;
}

/**
 * @brief 复位芯片
 */
uint8_t BMP280_Reset(BMP280_Handle *bmp)
{
    return BMP280_WriteByte(bmp, BMP280_REG_RESET, BMP280_RESET_VALUE);
}

/**
 * @brief 读取校准参数
 */
uint8_t BMP280_ReadCalibration(BMP280_Handle *bmp)
{
    uint8_t calib_data[24];
    
    /* 读取24字节的校准数据 */
    if(BMP280_ReadBytes(bmp, BMP280_REG_CALIB_START, calib_data, 24) != 0)
    {
        return 1;
    }
    
    /* 解析温度校准参数 */
    bmp->calib_data.dig_T1 = (calib_data[1] << 8) | calib_data[0];
    bmp->calib_data.dig_T2 = (calib_data[3] << 8) | calib_data[2];
    bmp->calib_data.dig_T3 = (calib_data[5] << 8) | calib_data[4];
    
    /* 解析气压校准参数 */
    bmp->calib_data.dig_P1 = (calib_data[7] << 8) | calib_data[6];
    bmp->calib_data.dig_P2 = (calib_data[9] << 8) | calib_data[8];
    bmp->calib_data.dig_P3 = (calib_data[11] << 8) | calib_data[10];
    bmp->calib_data.dig_P4 = (calib_data[13] << 8) | calib_data[12];
    bmp->calib_data.dig_P5 = (calib_data[15] << 8) | calib_data[14];
    bmp->calib_data.dig_P6 = (calib_data[17] << 8) | calib_data[16];
    bmp->calib_data.dig_P7 = (calib_data[19] << 8) | calib_data[18];
    bmp->calib_data.dig_P8 = (calib_data[21] << 8) | calib_data[20];
    bmp->calib_data.dig_P9 = (calib_data[23] << 8) | calib_data[22];
    
    /* 调试输出 */
    printf("BMP280: Calibration data loaded\n");
    printf("  T1=%u, T2=%d, T3=%d\n", 
           bmp->calib_data.dig_T1, bmp->calib_data.dig_T2, bmp->calib_data.dig_T3);
    printf("  P1=%u, P2=%d, P3=%d\n", 
           bmp->calib_data.dig_P1, bmp->calib_data.dig_P2, bmp->calib_data.dig_P3);
    
    return 0;
}

/**
 * @brief 配置传感器
 */
uint8_t BMP280_SetConfig(BMP280_Handle *bmp)
{
    uint8_t ctrl_meas = 0;
    uint8_t config = 0;
    
    /* 配置控制测量寄存器 */
    ctrl_meas = (bmp->osr_temp << 5) | (bmp->osr_press << 2) | bmp->mode;
    
    /* 配置寄存器 */
    config = (bmp->standby << 5) | (bmp->filter << 2);
    
    /* 写入配置 */
    if(BMP280_WriteByte(bmp, BMP280_REG_CTRL_MEAS, ctrl_meas) != 0)
    {
        return 1;
    }
    
    if(BMP280_WriteByte(bmp, BMP280_REG_CONFIG, config) != 0)
    {
        return 2;
    }
    
    return 0;
}

/**
 * @brief 启动测量
 */
uint8_t BMP280_StartMeasurement(BMP280_Handle *bmp)
{
    uint8_t ctrl_meas = 0;
    
    /* 读取当前配置 */
    if(BMP280_ReadBytes(bmp, BMP280_REG_CTRL_MEAS, &ctrl_meas, 1) != 0)
    {
        return 1;
    }
    
    /* 设置为强制模式或正常模式 */
    ctrl_meas &= ~0x03;  // 清除模式位
    ctrl_meas |= bmp->mode;
    
    /* 写回寄存器 */
    if(BMP280_WriteByte(bmp, BMP280_REG_CTRL_MEAS, ctrl_meas) != 0)
    {
        return 2;
    }
    
    return 0;
}

/**
 * @brief 检查测量是否完成
 */
uint8_t BMP280_IsMeasurementReady(BMP280_Handle *bmp)
{
    uint8_t status = 0;
    
    /* 读取状态寄存器 */
    if(BMP280_ReadBytes(bmp, BMP280_REG_STATUS, &status, 1) != 0)
    {
        return 0;  // 读取失败,认为未完成
    }
    
    /* 检查bit3 (measuring) 是否为0 */
    if((status & 0x08) == 0)
    {
        return 1;  // 测量完成
    }
    
    return 0;  // 测量中
}

/**
 * @brief 读取原始数据
 */
static uint8_t BMP280_ReadRawData(BMP280_Handle *bmp, int32_t *raw_temp, int32_t *raw_press)
{
    uint8_t data[6];
    
    /* 读取6字节数据 (3字节气压 + 3字节温度) */
    if(BMP280_ReadBytes(bmp, BMP280_REG_PRESS_MSB, data, 6) != 0)
    {
        return 1;
    }
    
    /* 解析原始气压数据 */
    *raw_press = (int32_t)(((uint32_t)data[0] << 12) | ((uint32_t)data[1] << 4) | ((uint32_t)data[2] >> 4));
    
    /* 解析原始温度数据 */
    *raw_temp = (int32_t)(((uint32_t)data[3] << 12) | ((uint32_t)data[4] << 4) | ((uint32_t)data[5] >> 4));
    
    return 0;
}

/**
 * @brief 补偿温度计算
 * @param raw_temp 原始温度值
 * @param calib 校准数据指针
 * @return 补偿后的温度 (°C)
 */
static float BMP280_CompensateTemperature(int32_t raw_temp, BMP280_CalibData *calib)
{
    int32_t var1, var2, T;
    float temp = 0.0f;
    
    var1 = ((((raw_temp >> 3) - ((int32_t)calib->dig_T1 << 1))) * ((int32_t)calib->dig_T2)) >> 11;
    var2 = (((((raw_temp >> 4) - ((int32_t)calib->dig_T1)) * 
              ((raw_temp >> 4) - ((int32_t)calib->dig_T1))) >> 12) * 
            ((int32_t)calib->dig_T3)) >> 14;
    
    calib->t_fine = var1 + var2;
    T = (calib->t_fine * 5 + 128) >> 8;
    temp = (float)T / 100.0f;
    
    return temp;
}

/**
 * @brief 补偿气压计算
 * @param raw_press 原始气压值
 * @param calib 校准数据指针
 * @return 补偿后的气压 (Pa)
 */
static float BMP280_CompensatePressure(int32_t raw_press, BMP280_CalibData *calib)
{
    int64_t var1, var2, p;
    float pressure = 0.0f;
    
    var1 = ((int64_t)calib->t_fine) - 128000;
    var2 = var1 * var1 * (int64_t)calib->dig_P6;
    var2 = var2 + ((var1 * (int64_t)calib->dig_P5) << 17);
    var2 = var2 + (((int64_t)calib->dig_P4) << 35);
    var1 = ((var1 * var1 * (int64_t)calib->dig_P3) >> 8) + ((var1 * (int64_t)calib->dig_P2) << 12);
    var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)calib->dig_P1) >> 33;
    
    if(var1 == 0)
    {
        return 0;  // 避免除零错误
    }
    
    p = 1048576 - raw_press;
    p = (((p << 31) - var2) * 3125) / var1;
    var1 = (((int64_t)calib->dig_P9) * (p >> 13) * (p >> 13)) >> 25;
    var2 = (((int64_t)calib->dig_P8) * p) >> 19;
    
    p = ((p + var1 + var2) >> 8) + (((int64_t)calib->dig_P7) << 4);
    pressure = (float)p / 256.0f;
    
    return pressure;
}

/**
 * @brief 读取补偿后的数据
 */
uint8_t BMP280_ReadData(BMP280_Handle *bmp, BMP280_Data *data)
{
    int32_t raw_temp, raw_press;
    float temperature, pressure;
    
    /* 检查是否初始化 */
    if(!bmp->initialized)
    {
        return 1;
    }
    
    /* 检查测量是否完成 */
    if(!BMP280_IsMeasurementReady(bmp))
    {
        return 2;  // 测量未完成
    }
    
    /* 读取原始数据 */
    if(BMP280_ReadRawData(bmp, &raw_temp, &raw_press) != 0)
    {
        return 3;
    }
    
    /* 补偿温度计算 */
    temperature = BMP280_CompensateTemperature(raw_temp, &bmp->calib_data);
    
    /* 补偿气压计算 */
    pressure = BMP280_CompensatePressure(raw_press, &bmp->calib_data);
    
    /* 转换为hPa */
    pressure = pressure / 100.0f;
    
    /* 计算海拔高度 (标准海平面压力1013.25hPa) */
    float altitude = BMP280_CalculateAltitude(pressure, SEA_LEVEL_PRESSURE_HPA);
    
    /* 保存数据 */
    data->temperature = temperature;
    data->pressure = pressure;
    data->altitude = altitude;
    data->timestamp = HAL_GetTick();
    
    /* 如果是在强制模式,切换回睡眠模式 */
    if(bmp->mode == BMP280_MODE_FORCED || bmp->mode == BMP280_MODE_FORCED_2)
    {
        BMP280_SetMode(bmp, BMP280_MODE_SLEEP);
    }
    
    return 0;
}

/**
 * @brief 计算海拔高度
 * @param pressure 当前气压 (hPa)
 * @param sea_level_hpa 海平面气压 (hPa)
 * @return 海拔高度 (m)
 */
float BMP280_CalculateAltitude(float pressure, float sea_level_hpa)
{
    if(pressure <= 0 || sea_level_hpa <= 0)
        return 0.0f;
    
    return 44330.0f * (1.0f - powf(pressure / sea_level_hpa, 0.190295f));
}

/**
 * @brief 计算海平面气压
 * @param pressure 当前气压 (hPa)
 * @param altitude 当前海拔 (m)
 * @return 海平面气压 (hPa)
 */
float BMP280_CalculateSeaLevelPressure(float pressure, float altitude)
{
    if(pressure <= 0)
        return 0.0f;
    
    return pressure / powf(1.0f - (altitude / 44330.0f), 5.255f);
}

/**
 * @brief 设置工作模式
 */
void BMP280_SetMode(BMP280_Handle *bmp, BMP280_Mode mode)
{
    bmp->mode = mode;
    BMP280_SetConfig(bmp);
}

/**
 * @brief 设置过采样率
 */
void BMP280_SetOversampling(BMP280_Handle *bmp, BMP280_Oversampling osr_temp, 
                           BMP280_Oversampling osr_press)
{
    bmp->osr_temp = osr_temp;
    bmp->osr_press = osr_press;
    BMP280_SetConfig(bmp);
}

/**
 * @brief 设置滤波器
 */
void BMP280_SetFilter(BMP280_Handle *bmp, BMP280_Filter filter)
{
    bmp->filter = filter;
    BMP280_SetConfig(bmp);
}

/**
 * @brief 设置待机时间
 */
void BMP280_SetStandby(BMP280_Handle *bmp, BMP280_StandbyTime standby)
{
    bmp->standby = standby;
    BMP280_SetConfig(bmp);
}

/**
 * @brief 打印校准参数
 */
void BMP280_PrintCalibration(BMP280_CalibData *calib)
{
    printf("=== BMP280 Calibration Data ===\n");
    printf("Temperature:\n");
    printf("  T1: %u\n", calib->dig_T1);
    printf("  T2: %d\n", calib->dig_T2);
    printf("  T3: %d\n", calib->dig_T3);
    printf("Pressure:\n");
    printf("  P1: %u\n", calib->dig_P1);
    printf("  P2: %d\n", calib->dig_P2);
    printf("  P3: %d\n", calib->dig_P3);
    printf("  P4: %d\n", calib->dig_P4);
    printf("  P5: %d\n", calib->dig_P5);
    printf("  P6: %d\n", calib->dig_P6);
    printf("  P7: %d\n", calib->dig_P7);
    printf("  P8: %d\n", calib->dig_P8);
    printf("  P9: %d\n", calib->dig_P9);
    printf("t_fine: %ld\n", calib->t_fine);
    printf("===============================\n");
}

/**
 * @brief 打印配置
 */
void BMP280_PrintConfig(BMP280_Handle *bmp)
{
    printf("=== BMP280 Configuration ===\n");
    printf("I2C Address: 0x%02X\n", bmp->i2c_addr);
    printf("Chip ID: 0x%02X\n", bmp->chip_id);
    printf("Mode: %d\n", bmp->mode);
    printf("Temperature OSR: %d\n", bmp->osr_temp);
    printf("Pressure OSR: %d\n", bmp->osr_press);
    printf("Filter: %d\n", bmp->filter);
    printf("Standby Time: %d\n", bmp->standby);
    printf("Initialized: %s\n", bmp->initialized ? "Yes" : "No");
    printf("============================\n");
}

三、I2C配置与主程序

3.1 I2C配置

c 复制代码
/**
 * @file i2c_config.c
 * @brief I2C配置
 */

#include "main.h"

I2C_HandleTypeDef hi2c1;

/**
 * @brief I2C1初始化
 */
void MX_I2C1_Init(void)
{
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 100000;  // 100kHz
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    HAL_I2C_Init(&hi2c1);
}

/**
 * @brief I2C GPIO初始化
 */
void MX_I2C1_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* GPIO时钟使能 */
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_AFIO_CLK_ENABLE();
    
    /* PB6 - I2C1_SCL */
    /* PB7 - I2C1_SDA */
    GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;  // 开漏输出
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    /* 引脚重映射 (如果需要) */
    // __HAL_AFIO_REMAP_I2C1_ENABLE();
}

/**
 * @brief I2C错误处理回调
 */
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
    printf("I2C Error: 0x%08lX\n", hi2c->ErrorCode);
    
    /* 重新初始化I2C */
    HAL_I2C_DeInit(hi2c);
    MX_I2C1_Init();
}

3.2 主程序示例

c 复制代码
/**
 * @file main.c
 * @brief BMP280主程序
 */

#include "main.h"
#include "bmp280.h"
#include <stdio.h>
#include <string.h>

/* 全局变量 */
BMP280_Handle bmp280;
BMP280_Data bmp_data;
UART_HandleTypeDef huart1;

/* 函数声明 */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_USART1_UART_Init(void);
void Error_Handler(void);
void BMP280_Test(void);
void BMP280_ContinousRead(void);
void BMP280_HighPrecisionTest(void);

/* 重定向printf到串口 */
int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 1000);
    return len;
}

/**
 * @brief 主函数
 */
int main(void)
{
    /* HAL库初始化 */
    HAL_Init();
    
    /* 系统时钟配置 */
    SystemClock_Config();
    
    /* 外设初始化 */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_GPIO_Init();
    MX_I2C1_Init();
    
    printf("\nSTM32 BMP280 I2C Driver\n");
    printf("=======================\n");
    
    /* 初始化BMP280 */
    printf("Initializing BMP280...\n");
    if(BMP280_Init(&bmp280, &hi2c1, BMP280_I2C_ADDR_WRITE) != 0)
    {
        printf("BMP280 initialization failed!\n");
        
        /* 尝试备用地址 */
        printf("Trying alternative address...\n");
        if(BMP280_Init(&bmp280, &hi2c1, BMP280_I2C_ADDR_WRITE_2) != 0)
        {
            printf("BMP280 not found at any address!\n");
            Error_Handler();
        }
    }
    
    /* 打印配置信息 */
    BMP280_PrintConfig(&bmp280);
    BMP280_PrintCalibration(&bmp280.calib_data);
    
    /* 设置高精度模式 */
    BMP280_SetOversampling(&bmp280, BMP280_OSR_X2, BMP280_OSR_X16);
    BMP280_SetFilter(&bmp280, BMP280_FILTER_16);
    BMP280_SetStandby(&bmp280, BMP280_STANDBY_1000);
    BMP280_SetMode(&bmp280, BMP280_MODE_NORMAL);
    
    printf("\nConfiguration updated for high precision mode\n");
    
    /* 主循环 */
    while(1)
    {
        static uint32_t last_read = 0;
        uint32_t current_time = HAL_GetTick();
        
        /* 每1秒读取一次 */
        if(current_time - last_read >= 1000)
        {
            last_read = current_time;
            
            /* 读取数据 */
            if(BMP280_ReadData(&bmp280, &bmp_data) == 0)
            {
                printf("Temperature: %.2f C, Pressure: %.2f hPa, Altitude: %.2f m\n",
                       bmp_data.temperature, bmp_data.pressure, bmp_data.altitude);
                
                /* 控制LED (温度指示) */
                if(bmp_data.temperature > 30.0f)
                {
                    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);  // LED亮
                }
                else
                {
                    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // LED灭
                }
            }
            else
            {
                printf("Failed to read BMP280 data\n");
            }
        }
        
        HAL_Delay(10);
    }
}

/**
 * @brief 系统时钟配置
 */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    /* 配置HSE 8MHz */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RMP_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 8MHz * 9 = 72MHz
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    /* 配置系统时钟 */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;     // HCLK = 72MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;      // PCLK1 = 36MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;      // PCLK2 = 72MHz
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}

/**
 * @brief GPIO初始化
 */
void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* GPIO时钟使能 */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    /* LED引脚配置 */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);  // 默认关闭
}

/**
 * @brief 错误处理
 */
void Error_Handler(void)
{
    __disable_irq();
    while(1)
    {
        /* LED快速闪烁表示错误 */
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        HAL_Delay(100);
    }
}

四、高级功能扩展

4.1 数据滤波与平均

c 复制代码
/**
 * @file bmp280_filter.c
 * @brief BMP280数据滤波
 */

#include "bmp280.h"

#define FILTER_WINDOW_SIZE 10

/* 滑动窗口滤波器 */
typedef struct {
    float buffer[FILTER_WINDOW_SIZE];
    uint8_t index;
    uint8_t count;
    float sum;
} MovingAverageFilter;

static MovingAverageFilter temp_filter = {0};
static MovingAverageFilter press_filter = {0};
static MovingAverageFilter alt_filter = {0};

/**
 * @brief 初始化滤波器
 */
void BMP280_Filter_Init(void)
{
    memset(&temp_filter, 0, sizeof(temp_filter));
    memset(&press_filter, 0, sizeof(press_filter));
    memset(&alt_filter, 0, sizeof(alt_filter));
}

/**
 * @brief 滑动平均滤波
 */
float BMP280_MovingAverage(MovingAverageFilter *filter, float new_value)
{
    /* 减去最旧的值 */
    if(filter->count >= FILTER_WINDOW_SIZE)
    {
        filter->sum -= filter->buffer[filter->index];
    }
    
    /* 添加新值 */
    filter->buffer[filter->index] = new_value;
    filter->sum += new_value;
    filter->index = (filter->index + 1) % FILTER_WINDOW_SIZE;
    
    /* 更新计数 */
    if(filter->count < FILTER_WINDOW_SIZE)
    {
        filter->count++;
    }
    
    /* 计算平均值 */
    return filter->sum / filter->count;
}

/**
 * @brief 卡尔曼滤波
 */
typedef struct {
    float q;    // 过程噪声协方差
    float r;    // 测量噪声协方差
    float x;    // 估计值
    float p;    // 估计误差协方差
    float k;    // 卡尔曼增益
} KalmanFilter;

static KalmanFilter temp_kalman = {0.001, 0.1, 25.0, 1.0, 0.0};
static KalmanFilter press_kalman = {0.001, 0.1, 1013.25, 1.0, 0.0};

float BMP280_KalmanFilter(KalmanFilter *kf, float measurement)
{
    /* 预测 */
    kf->p = kf->p + kf->q;
    
    /* 更新 */
    kf->k = kf->p / (kf->p + kf->r);
    kf->x = kf->x + kf->k * (measurement - kf->x);
    kf->p = (1 - kf->k) * kf->p;
    
    return kf->x;
}

/**
 * @brief 读取滤波后的数据
 */
uint8_t BMP280_ReadFilteredData(BMP280_Handle *bmp, BMP280_Data *data, uint8_t filter_type)
{
    BMP280_Data raw_data;
    
    /* 读取原始数据 */
    if(BMP280_ReadData(bmp, &raw_data) != 0)
    {
        return 1;
    }
    
    /* 应用滤波 */
    switch(filter_type)
    {
        case 0:  // 无滤波
            *data = raw_data;
            break;
            
        case 1:  // 滑动平均
            data->temperature = BMP280_MovingAverage(&temp_filter, raw_data.temperature);
            data->pressure = BMP280_MovingAverage(&press_filter, raw_data.pressure);
            data->altitude = BMP280_MovingAverage(&alt_filter, raw_data.altitude);
            data->timestamp = raw_data.timestamp;
            break;
            
        case 2:  // 卡尔曼滤波
            data->temperature = BMP280_KalmanFilter(&temp_kalman, raw_data.temperature);
            data->pressure = BMP280_KalmanFilter(&press_kalman, raw_data.pressure);
            data->altitude = raw_data.altitude;  // 海拔使用原始值
            data->timestamp = raw_data.timestamp;
            break;
    }
    
    return 0;
}

4.2 气象站功能

c 复制代码
/**
 * @file weather_station.c
 * @brief 简单气象站功能
 */

#include "bmp280.h"

/* 气象数据记录 */
typedef struct {
    float min_temp;
    float max_temp;
    float avg_temp;
    float min_press;
    float max_press;
    float avg_press;
    uint32_t sample_count;
    uint32_t start_time;
} WeatherStats;

static WeatherStats weather_stats = {0};
static BMP280_Data history[24 * 60];  // 24小时历史数据,每分钟一个点
static uint8_t history_index = 0;

/**
 * @brief 初始化气象统计
 */
void Weather_InitStats(void)
{
    memset(&weather_stats, 0, sizeof(weather_stats));
    weather_stats.min_temp = 100.0f;
    weather_stats.max_temp = -100.0f;
    weather_stats.min_press = 2000.0f;
    weather_stats.max_press = 0.0f;
    weather_stats.start_time = HAL_GetTick();
}

/**
 * @brief 更新气象统计
 */
void Weather_UpdateStats(float temperature, float pressure)
{
    weather_stats.sample_count++;
    
    /* 温度统计 */
    if(temperature < weather_stats.min_temp)
        weather_stats.min_temp = temperature;
    if(temperature > weather_stats.max_temp)
        weather_stats.max_temp = temperature;
    weather_stats.avg_temp += (temperature - weather_stats.avg_temp) / weather_stats.sample_count;
    
    /* 气压统计 */
    if(pressure < weather_stats.min_press)
        weather_stats.min_press = pressure;
    if(pressure > weather_stats.max_press)
        weather_stats.max_press = pressure;
    weather_stats.avg_press += (pressure - weather_stats.avg_press) / weather_stats.sample_count;
    
    /* 保存历史数据 (每分钟) */
    static uint32_t last_minute = 0;
    uint32_t current_minute = HAL_GetTick() / 60000;  // 转换为分钟
    
    if(current_minute != last_minute)
    {
        last_minute = current_minute;
        history[history_index].temperature = temperature;
        history[history_index].pressure = pressure;
        history[history_index].timestamp = HAL_GetTick();
        history_index = (history_index + 1) % (24 * 60);
    }
}

/**
 * @brief 打印气象报告
 */
void Weather_PrintReport(void)
{
    uint32_t uptime = (HAL_GetTick() - weather_stats.start_time) / 1000;  // 秒
    
    printf("\n=== Weather Station Report ===\n");
    printf("Uptime: %lu seconds\n", uptime);
    printf("Samples: %lu\n", weather_stats.sample_count);
    printf("\nTemperature Statistics:\n");
    printf("  Current: %.2f C\n", bmp_data.temperature);
    printf("  Minimum: %.2f C\n", weather_stats.min_temp);
    printf("  Maximum: %.2f C\n", weather_stats.max_temp);
    printf("  Average: %.2f C\n", weather_stats.avg_temp);
    printf("\nPressure Statistics:\n");
    printf("  Current: %.2f hPa\n", bmp_data.pressure);
    printf("  Minimum: %.2f hPa\n", weather_stats.min_press);
    printf("  Maximum: %.2f hPa\n", weather_stats.max_press);
    printf("  Average: %.2f hPa\n", weather_stats.avg_press);
    printf("\nAltitude: %.2f m\n", bmp_data.altitude);
    printf("==============================\n");
}

/**
 * @brief 气压趋势分析
 * @return 0:稳定, 1:上升, 2:下降, 3:快速变化
 */
uint8_t Weather_AnalyzePressureTrend(void)
{
    static float last_pressure[3] = {0};
    static uint8_t index = 0;
    uint8_t trend = 0;
    
    /* 保存最近3个压力值 */
    last_pressure[index] = bmp_data.pressure;
    index = (index + 1) % 3;
    
    /* 计算变化率 */
    if(last_pressure[0] != 0 && last_pressure[1] != 0 && last_pressure[2] != 0)
    {
        float change_1h = (last_pressure[2] - last_pressure[0]) / 2.0f;
        
        if(change_1h > 0.5f)
        {
            trend = 1;  // 上升
        }
        else if(change_1h < -0.5f)
        {
            trend = 2;  // 下降
        }
        
        if(fabs(change_1h) > 2.0f)
        {
            trend = 3;  // 快速变化
        }
    }
    
    return trend;
}

/**
 * @brief 天气预报
 */
const char* Weather_Forecast(void)
{
    float pressure = bmp_data.pressure;
    uint8_t trend = Weather_AnalyzePressureTrend();
    
    if(pressure > 1022.0f && trend == 0)  // 高压稳定
    {
        return "Clear/Sunny";
    }
    else if(pressure > 1013.0f && trend == 2)  // 高压下降
    {
        return "Cloudy/Rain possible";
    }
    else if(pressure < 1000.0f && trend == 2)  // 低压下降
    {
        return "Rain/Stormy";
    }
    else if(pressure < 1013.0f && trend == 1)  // 低压上升
    {
        return "Clearing/Improving";
    }
    else
    {
        return "Fair/Partly cloudy";
    }
}

参考代码 BMP280的i2c通信程序 www.youwenfan.com/contentcsv/70777.html

五、测试程序

5.1 完整测试程序

c 复制代码
/**
 * @file bmp280_test.c
 * @brief BMP280测试程序
 */

#include "bmp280.h"

/**
 * @brief 测试I2C扫描
 */
void Test_I2C_Scan(void)
{
    printf("Scanning I2C bus...\n");
    
    for(uint8_t addr = 0x08; addr < 0x78; addr++)
    {
        uint8_t result = HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 3, 10);
        
        if(result == HAL_OK)
        {
            printf("Device found at address: 0x%02X\n", addr);
        }
    }
    
    printf("Scan complete.\n");
}

/**
 * @brief 测试BMP280基本功能
 */
void Test_BMP280_Basic(void)
{
    printf("\n=== BMP280 Basic Test ===\n");
    
    BMP280_Handle bmp;
    BMP280_Data data;
    
    /* 初始化 */
    if(BMP280_Init(&bmp, &hi2c1, BMP280_I2C_ADDR_WRITE) != 0)
    {
        printf("Initialization failed!\n");
        return;
    }
    
    /* 设置正常模式 */
    BMP280_SetMode(&bmp, BMP280_MODE_NORMAL);
    
    /* 连续读取10次 */
    for(int i = 0; i < 10; i++)
    {
        if(BMP280_ReadData(&bmp, &data) == 0)
        {
            printf("Read %d: %.2f C, %.2f hPa, %.2f m\n", 
                   i+1, data.temperature, data.pressure, data.altitude);
        }
        else
        {
            printf("Read %d: Failed\n", i+1);
        }
        
        HAL_Delay(1000);
    }
    
    printf("Test complete.\n");
}

/**
 * @brief 测试不同过采样率
 */
void Test_Oversampling_Rates(void)
{
    printf("\n=== Testing Oversampling Rates ===\n");
    
    BMP280_Handle bmp;
    BMP280_Data data;
    
    /* 初始化 */
    BMP280_Init(&bmp, &hi2c1, BMP280_I2C_ADDR_WRITE);
    
    /* 测试温度过采样率 */
    BMP280_Oversampling temp_osr[] = {
        BMP280_OSR_SKIP, BMP280_OSR_X1, BMP280_OSR_X2, 
        BMP280_OSR_X4, BMP280_OSR_X8, BMP280_OSR_X16
    };
    
    const char* temp_osr_names[] = {
        "SKIP", "X1", "X2", "X4", "X8", "X16"
    };
    
    for(int i = 0; i < 6; i++)
    {
        printf("\nTemperature OSR: %s\n", temp_osr_names[i]);
        BMP280_SetOversampling(&bmp, temp_osr[i], BMP280_OSR_X16);
        BMP280_SetMode(&bmp, BMP280_MODE_FORCED);
        
        HAL_Delay(50);  // 等待测量
        
        if(BMP280_ReadData(&bmp, &data) == 0)
        {
            printf("  Temperature: %.2f C\n", data.temperature);
        }
    }
    
    /* 测试气压过采样率 */
    BMP280_Oversampling press_osr[] = {
        BMP280_OSR_SKIP, BMP280_OSR_X1, BMP280_OSR_X2, 
        BMP280_OSR_X4, BMP280_OSR_X8, BMP280_OSR_X16
    };
    
    const char* press_osr_names[] = {
        "SKIP", "X1", "X2", "X4", "X8", "X16"
    };
    
    for(int i = 0; i < 6; i++)
    {
        printf("\nPressure OSR: %s\n", press_osr_names[i]);
        BMP280_SetOversampling(&bmp, BMP280_OSR_X2, press_osr[i]);
        BMP280_SetMode(&bmp, BMP280_MODE_FORCED);
        
        HAL_Delay(50);  // 等待测量
        
        if(BMP280_ReadData(&bmp, &data) == 0)
        {
            printf("  Pressure: %.2f hPa\n", data.pressure);
        }
    }
    
    printf("\nOversampling test complete.\n");
}

/**
 * @brief 测试滤波器
 */
void Test_Filter(void)
{
    printf("\n=== Testing Filter Settings ===\n");
    
    BMP280_Handle bmp;
    BMP280_Data data;
    
    /* 初始化 */
    BMP280_Init(&bmp, &hi2c1, BMP280_I2C_ADDR_WRITE);
    BMP280_SetOversampling(&bmp, BMP280_OSR_X2, BMP280_OSR_X16);
    BMP280_SetMode(&bmp, BMP280_MODE_NORMAL);
    
    /* 测试不同滤波器设置 */
    BMP280_Filter filters[] = {
        BMP280_FILTER_OFF, BMP280_FILTER_2, 
        BMP280_FILTER_4, BMP280_FILTER_8, BMP280_FILTER_16
    };
    
    const char* filter_names[] = {
        "OFF", "2", "4", "8", "16"
    };
    
    for(int i = 0; i < 5; i++)
    {
        printf("\nFilter: %s\n", filter_names[i]);
        BMP280_SetFilter(&bmp, filters[i]);
        
        /* 等待滤波器稳定 */
        HAL_Delay(1000);
        
        /* 读取10个样本 */
        float pressures[10];
        for(int j = 0; j < 10; j++)
        {
            if(BMP280_ReadData(&bmp, &data) == 0)
            {
                pressures[j] = data.pressure;
                printf("  Sample %d: %.2f hPa\n", j+1, pressures[j]);
            }
            HAL_Delay(100);
        }
        
        /* 计算标准差 */
        float sum = 0, mean = 0, stddev = 0;
        for(int j = 0; j < 10; j++) sum += pressures[j];
        mean = sum / 10;
        
        for(int j = 0; j < 10; j++)
        {
            stddev += (pressures[j] - mean) * (pressures[j] - mean);
        }
        stddev = sqrtf(stddev / 10);
        
        printf("  Mean: %.2f hPa, StdDev: %.4f hPa\n", mean, stddev);
    }
    
    printf("\nFilter test complete.\n");
}

/**
 * @brief 测试精度和稳定性
 */
void Test_Precision_Stability(void)
{
    printf("\n=== Testing Precision and Stability ===\n");
    
    BMP280_Handle bmp;
    BMP280_Data data;
    
    /* 初始化 */
    BMP280_Init(&bmp, &hi2c1, BMP280_I2C_ADDR_WRITE);
    
    /* 设置最高精度 */
    BMP280_SetOversampling(&bmp, BMP280_OSR_X16, BMP280_OSR_X16);
    BMP280_SetFilter(&bmp, BMP280_FILTER_16);
    BMP280_SetMode(&bmp, BMP280_MODE_NORMAL);
    
    printf("Collecting 100 samples (1 sample/second)...\n");
    
    float temperatures[100];
    float pressures[100];
    
    for(int i = 0; i < 100; i++)
    {
        if(BMP280_ReadData(&bmp, &data) == 0)
        {
            temperatures[i] = data.temperature;
            pressures[i] = data.pressure;
            
            if(i % 10 == 0)
            {
                printf("  Sample %d: %.2f C, %.2f hPa\n", 
                       i+1, data.temperature, data.pressure);
            }
        }
        
        HAL_Delay(1000);
    }
    
    /* 计算统计数据 */
    float temp_sum = 0, press_sum = 0;
    float temp_min = 100, temp_max = -100;
    float press_min = 2000, press_max = 0;
    
    for(int i = 0; i < 100; i++)
    {
        temp_sum += temperatures[i];
        press_sum += pressures[i];
        
        if(temperatures[i] < temp_min) temp_min = temperatures[i];
        if(temperatures[i] > temp_max) temp_max = temperatures[i];
        if(pressures[i] < press_min) press_min = pressures[i];
        if(pressures[i] > press_max) press_max = pressures[i];
    }
    
    float temp_mean = temp_sum / 100;
    float press_mean = press_sum / 100;
    
    float temp_stddev = 0, press_stddev = 0;
    for(int i = 0; i < 100; i++)
    {
        temp_stddev += (temperatures[i] - temp_mean) * (temperatures[i] - temp_mean);
        press_stddev += (pressures[i] - press_mean) * (pressures[i] - press_mean);
    }
    temp_stddev = sqrtf(temp_stddev / 100);
    press_stddev = sqrtf(press_stddev / 100);
    
    printf("\n=== Results ===\n");
    printf("Temperature:\n");
    printf("  Min: %.2f C, Max: %.2f C, Range: %.2f C\n", 
           temp_min, temp_max, temp_max - temp_min);
    printf("  Mean: %.3f C, StdDev: %.3f C\n", temp_mean, temp_stddev);
    printf("  Resolution: ~%.3f C\n", temp_stddev);
    
    printf("\nPressure:\n");
    printf("  Min: %.2f hPa, Max: %.2f hPa, Range: %.2f hPa\n", 
           press_min, press_max, press_max - press_min);
    printf("  Mean: %.3f hPa, StdDev: %.3f hPa\n", press_mean, press_stddev);
    printf("  Resolution: ~%.3f hPa\n", press_stddev);
    printf("  Altitude resolution: ~%.2f m\n", 
           44330.0f * (1.0f - powf((press_mean - press_stddev) / press_mean, 0.190295f)));
    
    printf("\nPrecision test complete.\n");
}

六、故障排除

6.1 常见问题解决

问题 可能原因 解决方案
I2C通信失败 1. 地址错误 2. 上拉电阻未接 3. 总线冲突 1. 扫描I2C地址 2. 添加4.7k上拉电阻 3. 检查设备连接
数据不正确 1. 校准参数未读取 2. 补偿算法错误 3. 电源噪声 1. 检查校准读取 2. 验证补偿计算 3. 添加去耦电容
测量漂移 1. 自热效应 2. 环境变化 3. 传感器老化 1. 降低测量频率 2. 添加温度补偿 3. 重新校准
响应慢 1. 过采样率过高 2. 滤波器过强 3. 待机时间过长 1. 降低过采样率 2. 调整滤波器 3. 减少待机时间

6.2 调试函数

c 复制代码
/**
 * @brief BMP280调试函数
 */
void BMP280_Debug_Print(BMP280_Handle *bmp)
{
    uint8_t reg_val;
    
    printf("\n=== BMP280 Debug Info ===\n");
    
    /* 读取所有主要寄存器 */
    BMP280_ReadBytes(bmp, BMP280_REG_ID, &reg_val, 1);
    printf("ID Register: 0x%02X\n", reg_val);
    
    BMP280_ReadBytes(bmp, BMP280_REG_RESET, &reg_val, 1);
    printf("Reset Register: 0x%02X\n", reg_val);
    
    BMP280_ReadBytes(bmp, BMP280_REG_STATUS, &reg_val, 1);
    printf("Status Register: 0x%02X\n", reg_val);
    printf("  Measuring: %s\n", (reg_val & 0x08) ? "Yes" : "No");
    printf("  im_update: %s\n", (reg_val & 0x01) ? "Yes" : "No");
    
    BMP280_ReadBytes(bmp, BMP280_REG_CTRL_MEAS, &reg_val, 1);
    printf("Ctrl_meas Register: 0x%02X\n", reg_val);
    printf("  osrs_t: %d\n", (reg_val >> 5) & 0x07);
    printf("  osrs_p: %d\n", (reg_val >> 2) & 0x07);
    printf("  mode: %d\n", reg_val & 0x03);
    
    BMP280_ReadBytes(bmp, BMP280_REG_CONFIG, &reg_val, 1);
    printf("Config Register: 0x%02X\n", reg_val);
    printf("  t_sb: %d\n", (reg_val >> 5) & 0x07);
    printf("  filter: %d\n", (reg_val >> 2) & 0x07);
    
    printf("=========================\n");
}
相关推荐
优信电子3 小时前
基于STM32F103C8T6单片机驱动ACS712模块进行电流检测
stm32·单片机·嵌入式硬件·嵌入式·电流检测·acs712·电流采集
崇山峻岭之间4 小时前
单片机外部中断实验
单片机·嵌入式硬件
chipsense5 小时前
工业UPS电流传感器选型实战指南:AS1V系列如何应对工业配电特殊挑战
单片机·嵌入式硬件·ups·电流传感器
振浩微433射频芯片5 小时前
告别“喊破嗓”:深度解析433MHz射频在宠物训练器中的核心应用与选型
单片机·嵌入式硬件·物联网·学习·宠物
╰⋛⋋⊱⋋翅膀⋌⊰⋌⋚╯5 小时前
ESP32-NVS保存
单片机
Hall_IC6 小时前
意法半导体STM32F103RCT6分销商
stm32·单片机·嵌入式硬件
世微 如初7 小时前
基于AP5160的大功率LED恒流驱动设计:原理分析与外围计算
驱动开发·单片机·芯片
华清远见IT开放实验室7 小时前
硬核根基,智能载体:华清远见嵌入式“硬件+仿真+课程+师资”产教融合与实践教学方案
linux·人工智能·stm32·物联网·嵌入式·虚拟仿真
老李的森林8 小时前
嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据--之2
stm32·单片机·嵌入式硬件·串口·dma·idle中断