气压计 BMP280 使用记录
来源:嵌入式Linux系统开发 发布时间:2023-03-26 分享至微信

博主最近在调试 bmp280 气压传感器,先看效果视频:

1、前言

BOSCH 出的 BMP280 气压传感器,可以用于测量气压、海拔高度等。无人机一般都会使用气压计,给飞控定高,还可以做天气监控,因为温度和风速的变化都会影响测量结果。

目前已经出了 BMP380、BMP390 ,精度更高。

2、传感器特性

  1. 具有数字 I2C、SPI 串口标准输出。(I2C up to 3.4 MHz)(SPI 3 and 4 wire, up to 10 MHz)
  2. 封装 8-pin LGA,2.0 × 2.5 × 0.95mm,小尺寸适用于很多设备
  3. 功耗 2.7µA @ 1 Hz sampling rate
  4. 工作温度 -40 … +85 °C
  5. 测压范围 300 … 1100 hPa

典型应用

  1. 增强 GPS 导航(例如,首次修复改进时间、航位推算、坡度检测)
  2. 室内导航(楼层检测、电梯检测)
  3. 户外导航、休闲和体育应用
  4. 天气预报
  5. 医疗保健应用(如肺活量测定)
  6. 垂直速度指示(例如上升/下降速度)

目标设备

  1. 手机、平板电脑、GPS 设备等手持设备
  2. 导航系统
  3. 便携式医疗保健设备
  4. 家庭气象站
  5. 飞行玩具
  6. 手表

BMP180、BMP280 对比

3、参考资料

bosch 官网有数据手册

https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/
https://blog.csdn.net/bdjsm_hh/article/details/107623788

4、引脚说明

一共 8 个 PIN 脚

Pin description

4-wire SPI

3-wire SPI

C1, C2 is 100 nF.

I2C connection

5、工作模式

  1. sleep mode
  2. normal mode
  3. forced mode

在睡眠模式下,不进行任何测量。正常模式包括自动在活动测量周期和非活动待机周期之间的永久循环。在强制模式下,执行单次测量,测量完成后传感器返回睡眠模式。

6、I2C 读写地址

BMP280 从机地址是 111011x ,高 6 bit 是固定的,最后一位 x 和一个 PIN 的状态有关系。如果 SDO 是高,从机地址是 1110111 (0x77)。如果 SDO 是低,从机地址是 1110110 (0x76)。

这个方案可以使得一路 I2C bus 挂两个 bmp280,同时使用。

I2C write

I2C read

另外,该器件支持 SPI mode ‘00’ (CPOL = CPHA = ‘0’) and mode ‘11’ (CPOL= CPHA = ‘1’). SPI 支持 4-wire and 3-wire。详情参看数据手册。

7、寄存器

#defineBMP280_ADDRESS0x76//从设备地址
#defineBMP280_RESET_VALUE0xB6//复位寄存器写入值

#defineBMP280_CHIPID_REG0xD0/*ChipIDRegister*/
#defineBMP280_RESET_REG0xE0/*SoftresetRegister*/
#defineBMP280_STATUS_REG0xF3/*StatusRegister*/
#defineBMP280_CTRLMEAS_REG0xF4/*CtrlMeasureRegister*/
#defineBMP280_CONFIG_REG0xF5/*ConfigurationRegister*/
#defineBMP280_PRESSURE_MSB_REG0xF7/*PressureMSBRegister*/
#defineBMP280_PRESSURE_LSB_REG0xF8/*PressureLSBRegister*/
#defineBMP280_PRESSURE_XLSB_REG0xF9/*PressureXLSBRegister*/
#defineBMP280_TEMPERATURE_MSB_REG0xFA/*TemperatureMSBReg*/
#defineBMP280_TEMPERATURE_LSB_REG0xFB/*TemperatureLSBReg*/
#defineBMP280_TEMPERATURE_XLSB_REG0xFC/*TemperatureXLSBReg*/
//状态寄存器转换标志
#defineBMP280_MEASURING0x01
#defineBMP280_IM_UPDATE0x08
  1. 第一个 chip_id 寄存器。
  2. 第二个复位寄存器,向 0xE0 写 0xB6 复位。
  3. 状态寄存器,两个状态:一个是 MEASURING,一个是 UPDATE。
  4. 4 和 5 寄存器用来设置它的模式。
  5. 最后 6 个是数据寄存器,XLSB 是小数位的意思,后面用来浮点转化用。

8、代码

博主用的是轮询去读数据,大家也可以配置成中断方式。

初始化部分,主要是读补偿参数、设置工作模式、设置过采样参数等:

BMP280bmp280_inst;
BMP280*bmp280=bmp280_inst;//这个全局结构体变量用来保存存在芯片内ROM补偿参数
voidBmp_Init(void)
{
u8Lsb,Msb;

/********************接下来读出矫正参数*********************/
//温度传感器的矫正值
Lsb=BMP280_Read_Byte(BMP280_DIG_T1_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_T1_MSB_REG);
bmp280->T1=(((u16)Msb)<<8)+Lsb;//高位加低位
Lsb=BMP280_Read_Byte(BMP280_DIG_T2_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_T2_MSB_REG);
bmp280->T2=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_T3_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_T3_MSB_REG);
bmp280->T3=(((u16)Msb)<<8)+Lsb;

//大气压传感器的矫正值
Lsb=BMP280_Read_Byte(BMP280_DIG_P1_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P1_MSB_REG);
bmp280->P1=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P2_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P2_MSB_REG);
bmp280->P2=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P3_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P3_MSB_REG);
bmp280->P3=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P4_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P4_MSB_REG);
bmp280->P4=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P5_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P5_MSB_REG);
bmp280->P5=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P6_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P6_MSB_REG);
bmp280->P6=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P7_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P7_MSB_REG);
bmp280->P7=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P8_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P8_MSB_REG);
bmp280->P8=(((u16)Msb)<<8)+Lsb;
Lsb=BMP280_Read_Byte(BMP280_DIG_P9_LSB_REG);
Msb=BMP280_Read_Byte(BMP280_DIG_P9_MSB_REG);
bmp280->P9=(((u16)Msb)<<8)+Lsb;
/******************************************************/
BMP280_Write_Byte(BMP280_RESET_REG,BMP280_RESET_VALUE);//往复位寄存器写入给定值

BMP_OVERSAMPLE_MODEBMP_OVERSAMPLE_MODEStructure;
BMP_OVERSAMPLE_MODEStructure.P_Osample=BMP280_P_MODE_3;
BMP_OVERSAMPLE_MODEStructure.T_Osample=BMP280_T_MODE_1;
BMP_OVERSAMPLE_MODEStructure.WORKMODE=BMP280_NORMAL_MODE;
BMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODEStructure);

BMP_CONFIGBMP_CONFIGStructure;
BMP_CONFIGStructure.T_SB=BMP280_T_SB1;
BMP_CONFIGStructure.FILTER_COEFFICIENT=BMP280_FILTER_MODE_4;
BMP_CONFIGStructure.SPI_EN=DISABLE;

BMP280_Set_Standby_FILTER(BMP_CONFIGStructure);
}

bmp280.h

#include"myiic.h"
#include"sys.h"
//#include<stdint.h>

#defineBMP280_ADDRESS0xEC
//#defineBMP280_ADDRESS(0x76<<1)
#defineBMP280_RESET_VALUE0xB6

#defineBMP280_CHIPID_REG0xD0/*ChipIDRegister*/
#defineBMP280_RESET_REG0xE0/*SoftresetRegister*/
#defineBMP280_STATUS_REG0xF3/*StatusRegister*/
#defineBMP280_CTRLMEAS_REG0xF4/*CtrlMeasureRegister*/
#defineBMP280_CONFIG_REG0xF5/*ConfigurationRegister*/
#defineBMP280_PRESSURE_MSB_REG0xF7/*PressureMSBRegister*/
#defineBMP280_PRESSURE_LSB_REG0xF8/*PressureLSBRegister*/
#defineBMP280_PRESSURE_XLSB_REG0xF9/*PressureXLSBRegister*/
#defineBMP280_TEMPERATURE_MSB_REG0xFA/*TemperatureMSBReg*/
#defineBMP280_TEMPERATURE_LSB_REG0xFB/*TemperatureLSBReg*/
#defineBMP280_TEMPERATURE_XLSB_REG0xFC/*TemperatureXLSBReg*/

#defineBMP280_MEASURING0x01
#defineBMP280_IM_UPDATE0x08

/*calibrationparameters*/
#defineBMP280_DIG_T1_LSB_REG0x88
#defineBMP280_DIG_T1_MSB_REG0x89
#defineBMP280_DIG_T2_LSB_REG0x8A
#defineBMP280_DIG_T2_MSB_REG0x8B
#defineBMP280_DIG_T3_LSB_REG0x8C
#defineBMP280_DIG_T3_MSB_REG0x8D
#defineBMP280_DIG_P1_LSB_REG0x8E
#defineBMP280_DIG_P1_MSB_REG0x8F
#defineBMP280_DIG_P2_LSB_REG0x90
#defineBMP280_DIG_P2_MSB_REG0x91
#defineBMP280_DIG_P3_LSB_REG0x92
#defineBMP280_DIG_P3_MSB_REG0x93
#defineBMP280_DIG_P4_LSB_REG0x94
#defineBMP280_DIG_P4_MSB_REG0x95
#defineBMP280_DIG_P5_LSB_REG0x96
#defineBMP280_DIG_P5_MSB_REG0x97
#defineBMP280_DIG_P6_LSB_REG0x98
#defineBMP280_DIG_P6_MSB_REG0x99
#defineBMP280_DIG_P7_LSB_REG0x9A
#defineBMP280_DIG_P7_MSB_REG0x9B
#defineBMP280_DIG_P8_LSB_REG0x9C
#defineBMP280_DIG_P8_MSB_REG0x9D
#defineBMP280_DIG_P9_LSB_REG0x9E
#defineBMP280_DIG_P9_MSB_REG0x9F

typedefenum{
BMP280_SLEEP_MODE=0x0,
BMP280_FORCED_MODE=0x1,//???0x2
BMP280_NORMAL_MODE=0x3
}BMP280_WORK_MODE;


typedefenum
{
BMP280_P_MODE_SKIP=0x0,/*skipped*/
BMP280_P_MODE_1,/*x1*/
BMP280_P_MODE_2,/*x2*/
BMP280_P_MODE_3,/*x4*/
BMP280_P_MODE_4,/*x8*/
BMP280_P_MODE_5/*x16*/
}BMP280_P_OVERSAMPLING;


typedefenum{
BMP280_T_MODE_SKIP=0x0,/*skipped*/
BMP280_T_MODE_1,/*x1*/
BMP280_T_MODE_2,/*x2*/
BMP280_T_MODE_3,/*x4*/
BMP280_T_MODE_4,/*x8*/
BMP280_T_MODE_5/*x16*/
}BMP280_T_OVERSAMPLING;

//IIR
typedefenum{
BMP280_FILTER_OFF=0x0,/*filteroff*/
BMP280_FILTER_MODE_1,/*0.223*ODR*//*x2*/
BMP280_FILTER_MODE_2,/*0.092*ODR*//*x4*/
BMP280_FILTER_MODE_3,/*0.042*ODR*//*x8*/
BMP280_FILTER_MODE_4/*0.021*ODR*//*x16*/
}BMP280_FILTER_COEFFICIENT;


typedefenum{
BMP280_T_SB1=0x0,/*0.5ms*/
BMP280_T_SB2,/*62.5ms*/
BMP280_T_SB3,/*125ms*/
BMP280_T_SB4,/*250ms*/
BMP280_T_SB5,/*500ms*/
BMP280_T_SB6,/*1000ms*/
BMP280_T_SB7,/*2000ms*/
BMP280_T_SB8,/*4000ms*/
}BMP280_T_SB;


typedefstruct
{

/*T1~P9*/
uint16_tT1;
int16_tT2;
int16_tT3;
uint16_tP1;
int16_tP2;
int16_tP3;
int16_tP4;
int16_tP5;
int16_tP6;
int16_tP7;
int16_tP8;
int16_tP9;
}BMP280;

typedeflongsignedintBMP280_S32_t;
typedeflongunsignedintBMP280_U32_t;
typedeflonglongsignedintBMP280_S64_t;

#definedig_T1bmp280->T1
#definedig_T2bmp280->T2
#definedig_T3bmp280->T3
#definedig_P1bmp280->P1
#definedig_P2bmp280->P2
#definedig_P3bmp280->P3
#definedig_P4bmp280->P4
#definedig_P5bmp280->P5
#definedig_P6bmp280->P6
#definedig_P7bmp280->P7
#definedig_P8bmp280->P8
#definedig_P9bmp280->P9
/************************************************CUT****************************************/

typedefstruct
{

BMP280_P_OVERSAMPLINGP_Osample;
BMP280_T_OVERSAMPLINGT_Osample;
BMP280_WORK_MODEWORKMODE;
}BMP_OVERSAMPLE_MODE;

typedefstruct
{

BMP280_T_SBT_SB;
BMP280_FILTER_COEFFICIENTFILTER_COEFFICIENT;
FunctionalStateSPI_EN;
}BMP_CONFIG;

externBMP280*bmp280;

u8BMP280_Check(void);
voidBMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODE*Oversample_Mode);
voidBMP280_Set_Standby_FILTER(BMP_CONFIG*BMP_Config);
voidBmp_Init(void);
u8BMP280_GetStatus(u8status_flag);
//longBMP280_Get_Pressure(void);
doubleBMP280_Get_Pressure(void);
doublebmp280_compensate_T_double(BMP280_S32_tadc_T);
doublebmp280_compensate_P_double(BMP280_S32_tadc_P);

主函数

voidtask2_task(void*pvParameters)
{
doubleBMP_Pressure;
Bmp_Init();

while(1)
{
while(BMP280_GetStatus(BMP280_MEASURING)!=RESET);
while(BMP280_GetStatus(BMP280_IM_UPDATE)!=RESET);
BMP_Pressure=BMP280_Get_Pressure();
printf("Pressure%fPa\r\n",BMP_Pressure);
}
}

doubleBMP280_Get_Pressure(void)
{
uint8_tXLsb,Lsb,Msb;
longsignedBit32;
doublepressure;
XLsb=I2C_ReadOneByte(BMP280_ADDRESS,BMP280_PRESSURE_XLSB_REG);
Lsb=I2C_ReadOneByte(BMP280_ADDRESS,BMP280_PRESSURE_LSB_REG);
Msb=I2C_ReadOneByte(BMP280_ADDRESS,BMP280_PRESSURE_MSB_REG);
Bit32=((long)(Msb<<12))|((long)(Lsb<<4))|(XLsb>>4);
pressure=bmp280_compensate_P_double(Bit32);
returnpressure;
}

doublebmp280_compensate_P_double(BMP280_S32_tadc_P)
{
doublevar1,var2,p;
var1=((double)t_fine/2.0)-64000.0;
var2=var1*var1*((double)dig_P6)/32768.0;
var2=var2+var1*((double)dig_P5)*2.0;
var2=(var2/4.0)+(((double)dig_P4)*65536.0);
var1=(((double)dig_P3)*var1*var1/524288.0+((double)dig_P2)*var1)/524288.0;
var1=(1.0+var1/32768.0)*((double)dig_P1);
if(var1==0.0)
{
return0;//avoidexceptioncausedbydivisionbyzero
}
p=1048576.0-(double)adc_P;
p=(p-(var2/4096.0))*6250.0/var1;
var1=((double)dig_P9)*p*p/2147483648.0;
var2=p*((double)dig_P8)/32768.0;
p=p+(var1+var2+((double)dig_P7))/16.0;
returnp;
}


[ 新闻来源:嵌入式Linux系统开发,更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj]
存入云盘 收藏
举报
全部评论

暂无评论哦,快来评论一下吧!

查看更多
相关文章
热门搜索