当前位置: 首页 > news >正文

STM32 之BMP280的应用--基于RTOS的环境

文章目录

  • 1 项目应用
  • 1.1 介绍一下bmp280
    • 1.2 性能尺寸
    • 1.2 工作原理
    • 1.3 典型应用
    • 1.4 与 BMP388 的对比
    • 1.4 总结
  • 2 电路介绍
    • 2.1 设计原理图
    • 2.2 接线说明
  • 3 应用开发
    • 3.1 软I2C 配置
    • 3.2 BMP280 初始化
    • 3.3 温度和压强读取, 数据校准

1 项目应用

项目中需要采集大气压力,通过采集大气压力,初步估算现在的高度。

1.1 介绍一下bmp280

BMP280 是 Bosch Sensortec 推出的一款高精度、低功耗的数字式气压传感器。它是前代产品 BMP180 的升级版,在尺寸、精度和噪音性能上都有显著改进。它通过测量大气压来间接计算海拔高度,同时也能提供温度读数。由于其优异的性能和低廉的价格,BMP280 在创客项目、消费电子和工业应用中变得极其流行。

1.2 性能尺寸

主要特点和优势
高精度:

气压精度: 典型值为 ±1 hPa(相当于海平面高度变化约 ±8.5米)。

相对精度: 更佳,非常适合测量相对高度变化。

温度精度: 典型值为 ±1.0°C。

低功耗:

在标准模式下的功耗仅为 2.7 μA,这使得它非常适合电池供电的便携设备,如智能手机、GPS追踪器或户外传感器。

高分辨率与低噪音:

气压和温度读数具有很高的分辨率,可以通过配置滤波器来优化性能,适应不同的应用场景(如天气监测或无人机飞行)。

小尺寸:

采用极其紧凑的 LGA 封装,尺寸仅为 2.0 × 2.5 × 0.95 mm³。这使其可以轻松集成到空间受限的移动设备中。

强大的接口支持:

支持标准的 I²C 和 SPI 通信协议,可以灵活地与各种微控制器(如 Arduino, ESP32, Raspberry Pi Pico)连接。

高响应速率:

相比于 BMP180,BMP280 的数据输出速率更快,更适合需要快速响应的应用。

1.2 工作原理

BMP280 的核心是一个微机电系统(MEMS) 压阻式压力传感器和一个温度传感器。

传感器内部的硅膜会随着外界气压的变化而产生微小的形变。

这种形变会导致嵌入在硅膜上的压敏电阻的电阻值发生变化。

内置的 ASIC(专用集成电路)将这些模拟信号转换为高分辨率的数字信号,并通过 I²C 或 SPI 接口输出。

温度传感器用于对气压测量进行温度补偿,以确保读数在不同温度环境下的准确性。

1.3 典型应用

凭借其测量气压和温度的能力,BMP280 被广泛应用于:

海拔高度测量:通过气压值换算得到高度(注意:高度精度受天气变化影响)。

天气预报:监测气压变化趋势,可以用于预测短期的天气变化(例如,气压持续下降通常预示着坏天气的到来)。

室内室外导航:作为 GPS 的补充,在GPS信号弱时(如隧道、城市峡谷)或无法提供高度信息时提供辅助导航。

健康与运动监测:用于可穿戴设备,记录爬楼梯、登山等活动的海拔增益。

无人机和飞行控制器:提供关键的高度保持(定高)数据。

物联网(IoT)节点:作为环境数据记录仪,收集气压和温度信息。

1.4 与 BMP388 的对比

在这里插入图片描述

简单总结:BMP388 是 BMP280 的高性能升级版,主要在精度、稳定性和功耗上进行了优化。对于大多数业余项目和一般性应用,BMP280 已经完全足够且性价比极高。而对于有严格性能要求的专业应用,则应选择 BMP388。

1.4 总结

BMP280 是一款功能强大、经济实惠且易于使用的环境传感器,是嵌入式项目和物联网应用的瑞士军刀。它在精度、功耗和成本之间取得了完美的平衡,这也是其经久不衰的原因。如果您正在寻找一款入门级的气压/高度计,BMP280 是一个非常可靠的选择。

2 电路介绍

2.1 设计原理图

在这里插入图片描述

在这里插入图片描述

2.2 接线说明

这里通讯采用I2C的通讯

VCC 接 3.3V
GND 接 GND
SCL 接 PB8
SDA 接 PB9

3 应用开发

3.1 软I2C 配置

这里采用软I2C,主要的原因:在测试过程总。软的I2C会相对比较稳定。

// 向指定设备写入数据
uint8_t Soft_I2C_Write(uint8_t devAddr, uint8_t regAddr, uint8_t *pData, uint16_t len)
{uint16_t i;Soft_I2C_Start();                           // 起始信号Soft_I2C_Send_Byte(devAddr & 0xFE);         // 发送设备地址+写模式if(Soft_I2C_Wait_Ack())                     // 等待应答{Soft_I2C_Stop();return 1;}Soft_I2C_Send_Byte(regAddr);                // 发送寄存器地址if(Soft_I2C_Wait_Ack()){Soft_I2C_Stop();return 1;}for(i = 0; i < len; i++){Soft_I2C_Send_Byte(pData[i]);           // 发送数据if(Soft_I2C_Wait_Ack()){Soft_I2C_Stop();return 1;}}Soft_I2C_Stop();                            // 停止信号return 0;
}// 从指定设备读取数据
uint8_t Soft_I2C_Read(uint8_t devAddr, uint8_t regAddr, uint8_t *pData, uint16_t len)
{Soft_I2C_Start();                           // 起始信号Soft_I2C_Send_Byte(devAddr & 0xFE);         // 发送设备地址+写模式if(Soft_I2C_Wait_Ack()){Soft_I2C_Stop();return 1;}Soft_I2C_Send_Byte(regAddr);                // 发送寄存器地址if(Soft_I2C_Wait_Ack()){Soft_I2C_Stop();return 1;}Soft_I2C_Start();                           // 重复起始信号Soft_I2C_Send_Byte(devAddr | 0x01);         // 发送设备地址+读模式if(Soft_I2C_Wait_Ack()){Soft_I2C_Stop();return 1;}// 读取数据for(uint16_t i = 0; i < len; i++){if(i == len - 1)pData[i] = Soft_I2C_Read_Byte(1);   // 最后一个字节发送NACKelsepData[i] = Soft_I2C_Read_Byte(0);   // 发送ACK继续读取}Soft_I2C_Stop();                            // 停止信号return 0;
}I2C_Status I2C1_ReadByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data)
{u8 res;dev_addr<<=1;res=Soft_I2C_Read(dev_addr,reg_addr,data,1);if(res==0)return I2C_OK;elsereturn I2C_TIMEOUT;}
I2C_Status I2C1_ReadBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len)
{u8 res;dev_addr<<=1;res=Soft_I2C_Read(dev_addr,reg_addr,data,len);if(res==0)return I2C_OK;elsereturn I2C_TIMEOUT;}I2C_Status I2C1_WriteByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data)
{u8 res;dev_addr<<=1;res=Soft_I2C_Write(dev_addr,reg_addr,&data,1);if(res==0)return I2C_OK;elsereturn I2C_TIMEOUT;
}

3.2 BMP280 初始化

配置 BMP280 的核心在于理解和操作其内部的控制寄存器。整个过程可以分为以下几个步骤:初始化 -> 配置工作模式 -> 配置滤波与输出数据速率 -> 读取数据。

步骤一:初始化和通信检查
初始化 I²C/SPI 通信。

读取 WHO_AM_I 寄存器(地址 0xD0)。BMP280 固定返回 0x58。这是一个确认传感器连接正确的良好方式。

步骤二:配置测量模式 (CTRL_MEAS)
这是最核心的配置,决定了传感器如何工作。

选择过采样率 (osrs_t 和 osrs_p):

更高的过采样率意味着传感器会采集更多样本进行平均,从而提高精度,但也会增加功耗和测量时间。

设置为 0 (跳过) 可以节省功耗,如果你不需要该数据。

常用设置:对于高度测量,通常压力采样率设置得比温度更高,例如 osrs_p = 0x05 (x16), osrs_t = 0x02 (x2)。

选择工作模式 (mode):

休眠模式 (Sleep): 00 - 低功耗模式,不进行任何测量。

强制模式 (Forced): 01 或 10 - 执行一次测量,将结果存入数据寄存器,然后自动返回休眠模式。适用于低功耗应用的按需测量。

正常模式 (Normal): 11 - 持续循环测量。测量间隔 = 测量时间 + standby time (t_sb)。

步骤三:配置滤波和待机时间 (CONFIG)
这个寄存器主要优化在 Normal mode 下的数据输出。

IIR 滤波器 (filter):

用于平滑输出数据,抑制高频噪音(例如无人机旋翼引起的快速气压变化)。

滤波器系数越高,输出越平滑,但对气压变化的响应也会变慢。

对于气象监测,推荐使用较高的滤波(如 4 或 8)。对于高度快速变化的无人机,推荐使用较低的滤波(如 2 或关闭)。

待机时间 (t_sb):

仅在 Normal mode 下有效。

它定义了两次测量之间的间隔时间。与 osrs_p 和 osrs_t 共同决定输出数据速率 (ODR)。

ODR = 1 / (测量时间 + standby_time)

// 初始化BMP280
uint8_t BMP280_Init(BMP280_Device *dev, uint8_t i2c_addr)
{dev->addr = i2c_addr;	u8 sta;// 检查设备IDif ((sta=BMP280_ReadID(dev) )!= 0x58) {rt_kprintf("BMP280 not found!\n");rt_kprintf("is id %d\r\n",sta);return 0;}// 复位设备if (BMP280_Reset(dev) != I2C_OK) {rt_kprintf("BMP280 reset failed!\n");return 0;}rt_thread_mdelay(10);// 读取校准数据if (BMP280_ReadCalibrationData(dev) != I2C_OK) {rt_kprintf("Read calibration data failed!\n");return 0;}// 配置传感器if (BMP280_Config(dev, BMP280_MODE_NORMAL, BMP280_OSRS_2X, BMP280_OSRS_16X,BMP280_FILTER_16, BMP280_STANDBY_250) != I2C_OK) {rt_kprintf("BMP280 config failed!\n");return 0;}return 1;
}

3.3 温度和压强读取, 数据校准

在 Forced mode 下,写入模式后需要等待测量完成。可以通过读取 STATUS 寄存器(地址 0xF3)的 measuring bit (bit3) 来判断,为 1 表示正在转换,为 0 表示完成。更简单的方法是延时等待(数据手册提供了最大转换时间表,例如 16x 压力采样 + 2x 温度采样约需 7.6ms)。

读取数据:

一次性读取从 PRESS_MSB (0xF7) 到 TEMP_LSB (0xFA) 的共 6 个字节的数据寄存器。

补偿计算:

原始的压力和温度数据(通常是 20-bit)需要根据芯片内部存储的校准参数(共 24 个,从地址 0x88 到 0xA1)进行复杂的补偿计算,才能得到精确的值。这个过程通常由一个专门的函数(如 bmp280_compensate_T_int32(), bmp280_compensate_P_int64())来完成。强烈建议使用官方或 Adafruit 的驱动库,它们已经实现了这些复杂的计算。

// 读取传感器数据
uint8_t BMP280_ReadData(BMP280_Device *dev)
{uint8_t data[6];int32_t adc_p, adc_t;// 读取原始数据if (I2C1_ReadBytes(dev->addr, BMP280_REG_PRESS_MSB, data, 6) != I2C_OK) {return I2C_ERROR;}// 组合压力数据adc_p = (int32_t)(((uint32_t)data[0] << 12) | ((uint32_t)data[1] << 4) | ((uint32_t)data[2] >> 4));// 组合温度数据adc_t = (int32_t)(((uint32_t)data[3] << 12) | ((uint32_t)data[4] << 4) | ((uint32_t)data[5] >> 4));// 计算实际值BMP280_CalculateData(dev, adc_t, adc_p);return I2C_OK;
}// 计算实际温度气压值
void BMP280_CalculateData(BMP280_Device *dev, int32_t adc_t, int32_t adc_p)
{int32_t var1, var2, t_fine;int64_t var1_p, var2_p, p;BMP280_CalibData *calib = &dev->calib;// 计算温度(官方算法)var1 = ((((adc_t >> 3) - ((int32_t)calib->dig_T1 << 1))) * ((int32_t)calib->dig_T2)) >> 11;var2 = (((((adc_t >> 4) - ((int32_t)calib->dig_T1)) * ((adc_t >> 4) - ((int32_t)calib->dig_T1))) >> 12) * ((int32_t)calib->dig_T3)) >> 14;t_fine = var1 + var2;// 温度转换为摄氏度dev->data.temperature = (t_fine * 5 + 128) >> 8;dev->data.temperature /= 100.0f;// 计算压力(官方算法)var1_p = ((int64_t)t_fine) - 128000;var2_p = var1_p * var1_p * (int64_t)calib->dig_P6;var2_p = var2_p + ((var1_p * (int64_t)calib->dig_P5) << 17);var2_p = var2_p + (((int64_t)calib->dig_P4) << 35);var1_p = ((var1_p * var1_p * (int64_t)calib->dig_P3) >> 8) + ((var1_p * (int64_t)calib->dig_P2) << 12);var1_p = (((((int64_t)1) << 47) + var1_p)) * ((int64_t)calib->dig_P1) >> 33;if (var1_p == 0) {dev->data.pressure = 0;return;}p = 1048576 - adc_p;p = (((p << 31) - var2_p) * 3125) / var1_p;var1_p = (((int64_t)calib->dig_P9) * (p >> 13) * (p >> 13)) >> 25;var2_p = (((int64_t)calib->dig_P8) * p) >> 19;p = ((p + var1_p + var2_p) >> 8) + (((int64_t)calib->dig_P7) << 4);dev->data.pressure = (float)p / 256.0f;// 计算海拔(简化公式,海平面气压为101325Pa)dev->data.altitude = 44330.0f * (1.0f - powf(dev->data.pressure / 101325.0f, 0.1903f));
}
http://www.xdnf.cn/news/1402021.html

相关文章:

  • 【MLLM】多模态理解Ovis2.5模型架构和训练流程
  • Codeforces Round 1033 (Div. 2) and CodeNite 2025 vp补题
  • 【自然语言处理与大模型】如何进行大模型多模态微调
  • 互联网大厂Java面试:从基础到微服务的深度解析
  • folium地图不显示加载不出来空白问题解决
  • 将 Logits 得分转换为概率,如何计算
  • 学习嵌入式第四十一天
  • nestjs连接oracle
  • WIFI模块-USB-UART-SDIO
  • Manus AI 与多语言手写识别技术全解析
  • U-Boot移植过程中的关键目录文件解析
  • fastdds qos:LifespanQosPolicy
  • 【C++】类和对象(终章)
  • 第二十六天-待机唤醒实验
  • 信息系统架构
  • v-model ,在 vue3和 vue2中的区别
  • Linux(1)|入门的开始:Linux基本指令
  • 认识Redis
  • IDM手机端,速度能提高6倍!
  • CPU的MBR寄存器和MDR寄存器
  • 联合体和枚举——嵌入式学习笔记
  • Linux IO复用
  • 优选算法:二分查找
  • 数据库攻略:“CMU 15-445”Project0:C++ Primer(2024 Fall)
  • 《Java反射与动态代理:从原理到实践》
  • SpringBoot整合Actuator实现健康检查
  • MIT 6.5840 (Spring, 2024) 通关指南——Lab 1: MapReduce
  • GitHub 热榜项目 - 日榜(2025-08-30)
  • 基于Ubuntu本地GitLab 搭建 Git 服务器
  • 解构机器学习:如何从零开始设计一个学习系统?