#define BME280_ADDR (0x76 << 1) /* HAL uses 8-bit address */
/* Calibration data (read once at startup) */
static int16_t dig_T2, dig_T3;
static uint16_t dig_H1_u, dig_H3_u;
static int16_t dig_H2, dig_H4, dig_H5;
static int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
uint8_t BME280_Init(I2C_HandleTypeDef *hi2c)
if (HAL_I2C_Mem_Read(hi2c, BME280_ADDR, reg, 1, &chip_id, 1, 100) != HAL_OK)
if (chip_id != 0x60) return 0; /* BME280 chip ID */
/* Read temperature calibration */
HAL_I2C_Mem_Read(hi2c, BME280_ADDR, 0x88, 1, cal, 26, 100);
dig_T1 = (cal[1] << 8) | cal[0];
dig_T2 = (cal[3] << 8) | cal[2];
dig_T3 = (cal[5] << 8) | cal[4];
/* Pressure calibration */
dig_P1 = (cal[7] << 8) | cal[6];
dig_P2 = (cal[9] << 8) | cal[8];
dig_P3 = (cal[11] << 8) | cal[10];
dig_P4 = (cal[13] << 8) | cal[12];
dig_P5 = (cal[15] << 8) | cal[14];
dig_P6 = (cal[17] << 8) | cal[16];
dig_P7 = (cal[19] << 8) | cal[18];
dig_P8 = (cal[21] << 8) | cal[20];
dig_P9 = (cal[23] << 8) | cal[22];
/* Humidity calibration (split across registers 0xA1 and 0xE1-0xE7) */
HAL_I2C_Mem_Read(hi2c, BME280_ADDR, 0xA1, 1, &hcal[0], 1, 100);
HAL_I2C_Mem_Read(hi2c, BME280_ADDR, 0xE1, 1, &hcal[1], 7, 100);
dig_H2 = (hcal[2] << 8) | hcal[1];
dig_H4 = (hcal[4] << 4) | (hcal[5] & 0x0F);
dig_H5 = (hcal[6] << 4) | ((hcal[5] >> 4) & 0x0F);
dig_H6 = (int8_t)hcal[7];
/* Configure: humidity oversampling x1 (must be set before ctrl_meas) */
HAL_I2C_Mem_Write(hi2c, BME280_ADDR, 0xF2, 1, &ctrl_hum, 1, 100);
/* Configure: temp x2, pressure x2, normal mode */
uint8_t ctrl_meas = 0x4B; /* osrs_t=010, osrs_p=010, mode=11 */
HAL_I2C_Mem_Write(hi2c, BME280_ADDR, 0xF4, 1, &ctrl_meas, 1, 100);
/* Config: standby 62.5 ms, filter coeff 4 */
HAL_I2C_Mem_Write(hi2c, BME280_ADDR, 0xF5, 1, &config, 1, 100);
uint8_t BME280_Read(I2C_HandleTypeDef *hi2c, float *temp, float *hum, float *press)
if (HAL_I2C_Mem_Read(hi2c, BME280_ADDR, 0xF7, 1, data, 8, 100) != HAL_OK)
/* Raw pressure (20-bit) */
int32_t adc_P = ((int32_t)data[0] << 12) | ((int32_t)data[1] << 4) | (data[2] >> 4);
/* Raw temperature (20-bit) */
int32_t adc_T = ((int32_t)data[3] << 12) | ((int32_t)data[4] << 4) | (data[5] >> 4);
/* Raw humidity (16-bit) */
int32_t adc_H = ((int32_t)data[6] << 8) | data[7];
/* Temperature compensation (from BME280 datasheet) */
int32_t var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
int32_t var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) *
((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) *
((int32_t)dig_T3)) >> 14;
*temp = (float)((t_fine * 5 + 128) >> 8) / 100.0f;
/* Pressure compensation */
int64_t var1_p = ((int64_t)t_fine) - 128000;
int64_t var2_p = var1_p * var1_p * (int64_t)dig_P6;
var2_p = var2_p + ((var1_p * (int64_t)dig_P5) << 17);
var2_p = var2_p + (((int64_t)dig_P4) << 35);
var1_p = ((var1_p * var1_p * (int64_t)dig_P3) >> 8) +
((var1_p * (int64_t)dig_P2) << 12);
var1_p = (((((int64_t)1) << 47) + var1_p)) * ((int64_t)dig_P1) >> 33;
if (var1_p == 0) { *press = 0; }
int64_t p = 1048576 - adc_P;
p = (((p << 31) - var2_p) * 3125) / var1_p;
var1_p = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
var2_p = (((int64_t)dig_P8) * p) >> 19;
p = ((p + var1_p + var2_p) >> 8) + (((int64_t)dig_P7) << 4);
*press = (float)((uint32_t)p) / 25600.0f;
/* Humidity compensation */
int32_t v_x1 = (t_fine - ((int32_t)76800));
v_x1 = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) -
(((int32_t)dig_H5) * v_x1)) + ((int32_t)16384)) >> 15) *
(((((((v_x1 * ((int32_t)dig_H6)) >> 10) *
(((v_x1 * ((int32_t)dig_H3_u)) >> 11) + ((int32_t)32768))) >> 10) +
((int32_t)2097152)) * ((int32_t)dig_H2) + 8192) >> 14));
v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((int32_t)dig_H1_u)) >> 4));
v_x1 = (v_x1 < 0) ? 0 : v_x1;
v_x1 = (v_x1 > 419430400) ? 419430400 : v_x1;
*hum = (float)(v_x1 >> 12) / 1024.0f;
Comments