博世BOSCH公司出了两款大气压检测模块,BME280和BMP280.
BMP280有温度检测、大气压检测
BME280有温度检测、大气压检测、湿度检测
本文主要选用的传感器是BME280,该传感器有两种通信方式,IIC(3.4MHz)和SPI(10MHz)。而我们采用的是IIC通信。
电压范围: 1.71 V to 3.6 V
温度范围:-40~+85℃
湿度范围:0~100%RH
大气压范围:300~1100hPa
程序流程图:
根据数据手册我们可以知道,设备的前六位是固定的,而最后一位由SDO决定。
若SDO 接 GND 则设备地址为 0x76
若SDO 接 VDDIO 则设备地址为 0x77
我们通过原理图可以看出SDO接GND,故设备地址为 0x76
从上面的表我们可以得出
设备 ID 地址 为 0xD0,而返回的数值为 0x60
配置 地址为 0xF5
读取大气压地址为0xF7
#define BME280_ADDRESS 0x76
#define BME280_CHIP_ID 0xD0 //发送芯片ID
#define BME280_DEFAULT_CHIP_ID 0x60 //返回芯片ID
#define BME280_Ctrl_Hum 0xF2
#define BME280_Ctrl_Meas 0xF4
#define BME280_Config 0xF5
#define BME280_Ctrl_Meas_MODE (BME280_Temperature_OSR<<5)|(BME280_Pressure_OSR<<2)|BME280_Normal_Mode
#define BME280_Config_MODE (BME280_TStandBy_1000Ms<<5)|(BME280_Filter_off<<2)|BME280_Spi3W_en
#define BME280_Pressure_OSR BME280_OversamplingX8
#define BME280_Temperature_OSR BME280_OversamplingX16
#define BME280_Humidity_OSR BME280_OversamplingX16
#define BME280_OversamplingX1 0x01
#define BME280_OversamplingX2 0x02
#define BME280_OversamplingX4 0x03
#define BME280_OversamplingX8 0x04
#define BME280_OversamplingX16 0x05
#define BME280_Sleep_Mode 0x00
#define BME280_Forced_Mode 0x01
#define BME280_Normal_Mode 0x03
#define BME280_TStandBy_1000Ms 0x05
#define BME280_Filter_off 0x00
#define BME280_Spi3W_en 0x00
void BME280_Init(void)//BME280初始化
{
//IIC初始化
gpio_init(GPIOB,GPIO_Pin_6,GPO_P,1);//PB6推挽输出——SDA
gpio_init(GPIOB,GPIO_Pin_7,GPO_P,1);//PB7推挽输出——SCL
delay_ms(20);
//检测芯片ID
bme280ID = IIC_Read_Reg(BME280_ADDRESS,BME280_CHIP_ID);
while(bme280ID != BME280_DEFAULT_CHIP_ID);
IIC_Write_Reg(BME280_ADDRESS,BME280_Ctrl_Hum,BME280_Humidity_OSR);
IIC_Write_Reg(BME280_ADDRESS,BME280_Ctrl_Meas,BME280_Ctrl_Meas_MODE);
IIC_Write_Reg(BME280_ADDRESS,BME280_Config,BME280_Config_MODE);
//校准数据
trimming_values();
}
读取 Trimming data:
uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int8_t dig_H1;
int16_t dig_H2;
int8_t dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t dig_H6;
void trimming_values(void)
{
u8 data[32];
IIC_Read_Buff(BME280_ADDRESS,0x88,24,&data[0]);
IIC_Read_Buff(BME280_ADDRESS,0xA1,1,&data[24]);
IIC_Read_Buff(BME280_ADDRESS,0xE1,7,&data[25]);
dig_T1 = (data[1] << 8) | data[0];
dig_T2 = (data[3] << 8) | data[2];
dig_T3 = (data[5] << 8) | data[4];
dig_P1 = (data[7] << 8) | data[6];
dig_P2 = (data[9] << 8) | data[8];
dig_P3 = (data[11] << 8) | data[10];
dig_P4 = (data[13] << 8) | data[12];
dig_P5 = (data[15] << 8) | data[14];
dig_P6 = (data[17] << 8) | data[16];
dig_P7 = (data[19] << 8) | data[18];
dig_P8 = (data[21] << 8) | data[20];
dig_P9 = (data[23] << 8) | data[22];
dig_H1 = data[24];
dig_H2 = (data[26] << 8) | data[25];
dig_H3 = data[27];
dig_H4 = (data[28] << 4) | (data[29] & 0x0F);
dig_H5 = (data[30] << 4) | ((data[29] >> 4) );
dig_H6 = data[31];
}
大气压读取地址:0xF7-0xF9
温度读取地址:0xFA-0xFC
湿度读取地址:0xFD-0xFE
//读取数值
void BME280_GetData(float *pressure,float *temperature,float *humility)
{
u8 data[8];
u32 press_t,temp_t,hum_t;
//校正
signed long int temp_cal;
unsigned long int press_cal,hum_cal;
IIC_Read_Buff(BME280_ADDRESS,0xF7,8,&data[0]);
press_t = (data[0]<<12)|(data[1]<<4)|(data[2]>>4);
temp_t = (data[3]<<12)|(data[4]<<4)|(data[5]>>4);
hum_t = (data[6]<<8)|data[7];
temp_cal = (double)calibration_T(temp_t) / 100.0;
press_cal = (double)calibration_P(press_t) / 25600.0;
hum_cal = (double)calibration_H(hum_t) / 1024.0;
*temperature = temp_cal;
*pressure = press_cal;
*humility = hum_cal;
}
数值校正函数:
//返回温度值,单位为度degree,输出值若为“5123”等价于51.23度
signed long int calibration_T(signed long int adc_T)
{
signed long int var1, var2, T;
var1 = ((((adc_T >> 3) - ((signed long int)dig_T1<<1))) * ((signed long int)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T>>4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
//返回大气压值,单位为Pa
//输出值若为“24674867” 等于 24674867/256 = 96386.2Pa = 963862hPa
unsigned long int calibration_P(signed long int adc_P)
{
int64_t var1, var2,P;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)dig_P6;
var2 = var2 + ((var1*(int64_t)dig_P5)<<17);
var2 = var2 + (((int64_t)dig_P4) <<35);
var1 = ((var1 * var1 * (int64_t)dig_P3) >> 8) + ((var1 * (int64_t)dig_P2) << 12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)dig_P1)>>33;
if (var1 == 0) return 0;
P = 1048576-adc_P;
P = (((P<<31)-var2)*3125)/var1;
var1 = (((int64_t)dig_P9) * (P>>13) * (P>>13))>>25;
var2 = (((int64_t)dig_P8) * P) >> 19;
P = ((P + var1 + var2) >> 8) + (((int64_t)dig_P7)<<4);
return (unsigned long int)P;
}
//输出值为"47445",代表 47445/1021 = 46.333%RH
unsigned long int calibration_H(signed long int adc_H)
{
int64_t v_x1_u32r;
v_x1_u32r=(t_fine-((int64_t)76800));
v_x1_u32r=(((((adc_H<<14)-(((int64_t)dig_H4)<<20)-(((int64_t)dig_H5)*v_x1_u32r))+((int64_t)16384))>>15)*(((((((v_x1_u32r*(
(int64_t)dig_H6))>>10)*(((v_x1_u32r*((int64_t)dig_H3))>>11)+((int64_t)32768)))>>10)+((int64_t)2097152))*((int64_t)
dig_H2)+8192)>>14));
v_x1_u32r=(v_x1_u32r-(((((v_x1_u32r>>15)*(v_x1_u32r>>15))>>7)*((int64_t)dig_H1))>>4));
v_x1_u32r=(v_x1_u32r<0?0:v_x1_u32r);
v_x1_u32r=(v_x1_u32r>419430400?419430400:v_x1_u32r);
return (uint32_t)(v_x1_u32r>>12);
}
最终结果: