博主最近在調(diào)試 bmp280 氣壓傳感器。
1、前言
BOSCH 出的 BMP280 氣壓傳感器,可以用于測(cè)量氣壓、海拔高度等。 無(wú)人機(jī)一般都會(huì)使用氣壓計(jì),給飛控定高,還可以做天氣監(jiān)控,因?yàn)闇囟群惋L(fēng)速的變化都會(huì)影響測(cè)量結(jié)果。
目前已經(jīng)出了 BMP380、BMP390 ,精度更高。
2、傳感器特性
- 具有數(shù)字 I2C、SPI 串口標(biāo)準(zhǔn)輸出。 (I2C up to 3.4 MHz) (SPI 3 and 4 wire, up to 10 MHz)
- 封裝 8-pin LGA,2.0 × 2.5 × 0.95mm,小尺寸適用于很多設(shè)備
- 功耗 2.7μA @ 1 Hz 采樣率
- 工作溫度 -40 … +85 °C
- 測(cè)壓范圍 300 … 1100 hPa
典型應(yīng)用
- 增強(qiáng) GPS 導(dǎo)航(例如,首次修復(fù)改進(jìn)時(shí)間、航位推算、坡度檢測(cè))
- 室內(nèi)導(dǎo)航(樓層檢測(cè)、電梯檢測(cè))
- 戶(hù)外導(dǎo)航、休閑和體育應(yīng)用
- 天氣預(yù)報(bào)
- 醫(yī)療保健應(yīng)用(如肺活量測(cè)定)
- 垂直速度指示(例如上升/下降速度)
目標(biāo)設(shè)備
BMP180、BMP280 對(duì)比
3、參考資料
bosch 官網(wǎng)有數(shù)據(jù)手冊(cè)
4、引腳說(shuō)明
一共 8 個(gè) PIN 腳
引腳說(shuō)明
4 線 SPI
3 線 SPI
C1, C2 為 100 nF。
I2C 連接
5、工作模式
- 睡眠模式
- 正常模式
- 強(qiáng)制模式
在睡眠模式下,不進(jìn)行任何測(cè)量。 正常模式包括自動(dòng)在活動(dòng)測(cè)量周期和非活動(dòng)待機(jī)周期之間的永久循環(huán)。 在強(qiáng)制模式下,執(zhí)行單次測(cè)量,測(cè)量完成后傳感器返回睡眠模式。
6、I2C 讀寫(xiě)地址
BMP280 從機(jī)地址是 111011x ,高 6 bit 是固定的,最后一位 x 和一個(gè) PIN 的狀態(tài)有關(guān)系。 如果 SDO 是高,從機(jī)地址是 1110111 (0x77)。 如果 SDO 是低,從機(jī)地址是 1110110 (0x76)。
這個(gè)方案可以使得一路 I2C bus 掛兩個(gè) bmp280,同時(shí)使用。
I2C 寫(xiě)入
I2C 讀取
另外,該器件支持 SPI mode ‘00’ (CPOL = CPHA = ‘0’) and mode ‘11’ (CPOL= CPHA = ‘1’). SPI 支持 4-wire and 3-wire。 詳情參看數(shù)據(jù)手冊(cè)。
7、寄存器
#define BMP280_ADDRESS 0x76 //從設(shè)備地址
#define BMP280_RESET_VALUE 0xB6 //復(fù)位寄存器寫(xiě)入值
#define BMP280_CHIPID_REG 0xD0 /*Chip ID Register */
#define BMP280_RESET_REG 0xE0 /*Softreset Register */
#define BMP280_STATUS_REG 0xF3 /*Status Register */
#define BMP280_CTRLMEAS_REG 0xF4 /*Ctrl Measure Register */
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
//狀態(tài)寄存器轉(zhuǎn)換標(biāo)志
#define BMP280_MEASURING 0x01
#define BMP280_IM_UPDATE 0x08
- 第一個(gè) chip_id 寄存器。
- 第二個(gè)復(fù)位寄存器,向 0xE0 寫(xiě) 0xB6 復(fù)位。
- 狀態(tài)寄存器,兩個(gè)狀態(tài):一個(gè)是 MEASURING,一個(gè)是 UPDATE。
- 4 和 5 寄存器用來(lái)設(shè)置它的模式。
- 最后 6 個(gè)是數(shù)據(jù)寄存器,XLSB 是小數(shù)位的意思,后面用來(lái)浮點(diǎn)轉(zhuǎn)化用。
8、代碼
博主用的是輪詢(xún)?nèi)プx數(shù)據(jù),大家也可以配置成中斷方式。
初始化部分,主要是讀補(bǔ)償參數(shù)、設(shè)置工作模式、設(shè)置過(guò)采樣參數(shù)等:
BMP280 bmp280_inst;
BMP280* bmp280 = &bmp280_inst; //這個(gè)全局結(jié)構(gòu)體變量用來(lái)保存存在芯片內(nèi)ROM補(bǔ)償參數(shù)
void Bmp_Init(void)
{
u8 Lsb,Msb;
/********************接下來(lái)讀出矯正參數(shù)*********************/
//溫度傳感器的矯正值
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); //往復(fù)位寄存器寫(xiě)入給定值
BMP_OVERSAMPLE_MODE BMP_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_CONFIG BMP_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
#define BMP280_ADDRESS 0xEC
//#define BMP280_ADDRESS (0x76 << 1)
#define BMP280_RESET_VALUE 0xB6
#define BMP280_CHIPID_REG 0xD0 /*Chip ID Register */
#define BMP280_RESET_REG 0xE0 /*Softreset Register */
#define BMP280_STATUS_REG 0xF3 /*Status Register */
#define BMP280_CTRLMEAS_REG 0xF4 /*Ctrl Measure Register */
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
#define BMP280_MEASURING 0x01
#define BMP280_IM_UPDATE 0x08
/*calibration parameters */
#define BMP280_DIG_T1_LSB_REG 0x88
#define BMP280_DIG_T1_MSB_REG 0x89
#define BMP280_DIG_T2_LSB_REG 0x8A
#define BMP280_DIG_T2_MSB_REG 0x8B
#define BMP280_DIG_T3_LSB_REG 0x8C
#define BMP280_DIG_T3_MSB_REG 0x8D
#define BMP280_DIG_P1_LSB_REG 0x8E
#define BMP280_DIG_P1_MSB_REG 0x8F
#define BMP280_DIG_P2_LSB_REG 0x90
#define BMP280_DIG_P2_MSB_REG 0x91
#define BMP280_DIG_P3_LSB_REG 0x92
#define BMP280_DIG_P3_MSB_REG 0x93
#define BMP280_DIG_P4_LSB_REG 0x94
#define BMP280_DIG_P4_MSB_REG 0x95
#define BMP280_DIG_P5_LSB_REG 0x96
#define BMP280_DIG_P5_MSB_REG 0x97
#define BMP280_DIG_P6_LSB_REG 0x98
#define BMP280_DIG_P6_MSB_REG 0x99
#define BMP280_DIG_P7_LSB_REG 0x9A
#define BMP280_DIG_P7_MSB_REG 0x9B
#define BMP280_DIG_P8_LSB_REG 0x9C
#define BMP280_DIG_P8_MSB_REG 0x9D
#define BMP280_DIG_P9_LSB_REG 0x9E
#define BMP280_DIG_P9_MSB_REG 0x9F
typedef enum {
BMP280_SLEEP_MODE = 0x0,
BMP280_FORCED_MODE = 0x1, //???0x2
BMP280_NORMAL_MODE = 0x3
} BMP280_WORK_MODE;
typedef enum
{
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;
typedef enum {
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
typedef enum {
BMP280_FILTER_OFF = 0x0, /*filter off*/
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;
typedef enum {
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;
typedef struct
{
/* T1~P9 */
uint16_t T1;
int16_t T2;
int16_t T3;
uint16_t P1;
int16_t P2;
int16_t P3;
int16_t P4;
int16_t P5;
int16_t P6;
int16_t P7;
int16_t P8;
int16_t P9;
} BMP280;
typedef long signed int BMP280_S32_t;
typedef long unsigned int BMP280_U32_t;
typedef long long signed int BMP280_S64_t;
#define dig_T1 bmp280->T1
#define dig_T2 bmp280->T2
#define dig_T3 bmp280->T3
#define dig_P1 bmp280->P1
#define dig_P2 bmp280->P2
#define dig_P3 bmp280->P3
#define dig_P4 bmp280->P4
#define dig_P5 bmp280->P5
#define dig_P6 bmp280->P6
#define dig_P7 bmp280->P7
#define dig_P8 bmp280->P8
#define dig_P9 bmp280->P9
/************************************************CUT****************************************/
typedef struct
{
BMP280_P_OVERSAMPLING P_Osample;
BMP280_T_OVERSAMPLING T_Osample;
BMP280_WORK_MODE WORKMODE;
} BMP_OVERSAMPLE_MODE;
typedef struct
{
BMP280_T_SB T_SB;
BMP280_FILTER_COEFFICIENT FILTER_COEFFICIENT;
FunctionalState SPI_EN;
} BMP_CONFIG;
extern BMP280* bmp280;
u8 BMP280_Check(void);
void BMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODE * Oversample_Mode);
void BMP280_Set_Standby_FILTER(BMP_CONFIG * BMP_Config);
void Bmp_Init(void);
u8 BMP280_GetStatus(u8 status_flag);
//long BMP280_Get_Pressure(void);
double BMP280_Get_Pressure(void);
double bmp280_compensate_T_double(BMP280_S32_t adc_T);
double bmp280_compensate_P_double(BMP280_S32_t adc_P);
主函數(shù)
void task2_task(void *pvParameters)
{
double BMP_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 %f Pa \\r\\n",BMP_Pressure);
}
}
double BMP280_Get_Pressure(void)
{
uint8_t XLsb,Lsb, Msb;
long signed Bit32;
double pressure;
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);
return pressure;
}
double bmp280_compensate_P_double(BMP280_S32_t adc_P)
{
double var1, 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)
{
return 0; // avoid exception caused by division by zero
}
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;
return p;
}
-
傳感器
+關(guān)注
關(guān)注
2551文章
51099瀏覽量
753606 -
串口
+關(guān)注
關(guān)注
14文章
1554瀏覽量
76523 -
BOSCH
+關(guān)注
關(guān)注
14文章
53瀏覽量
54304 -
氣壓傳感器
+關(guān)注
關(guān)注
4文章
136瀏覽量
21079 -
BMP280
+關(guān)注
關(guān)注
1文章
20瀏覽量
5731
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論