Skip to content

Instantly share code, notes, and snippets.

@yplam
Created April 8, 2026 11:27
Show Gist options
  • Select an option

  • Save yplam/c43b9c35d9e847acdc54f267fdf10008 to your computer and use it in GitHub Desktop.

Select an option

Save yplam/c43b9c35d9e847acdc54f267fdf10008 to your computer and use it in GitHub Desktop.
BME280 - Software Debugging Reference

BME280 - Software Debugging Reference

1. Communication Quick-Start

  • Device Type: Digital humidity, pressure, and temperature sensor.
  • Interfaces:
    • I2C: Up to 3.4 MHz. Slave addresses: 0x76 (SDO pin to GND) or 0x77 (SDO pin to VDDIO).
    • SPI: 3-wire and 4-wire support, up to 10 MHz. Supports SPI modes '00' (CPOL=0, CPHA=0) and '11' (CPOL=1, CPHA=1).
  • SPI Address Format: The 7-bit register address is shifted. Bit 7 is the Read/Write bit (0 for Write, 1 for Read). Example: To write to 0xF4, use SPI address 0x74. To read 0xF4, use 0xF4.
  • I2C Transaction:
    • Write: [Slave Addr + W] -> [Reg Addr] -> [Data].
    • Read: [Slave Addr + W] -> [Reg Addr] -> [Repeated Start] -> [Slave Addr + R] -> [Data].
  • Power-on Timing:
    • $t_{startup}$: Max 2 ms after VDD > 1.58V and VDDIO > 0.65V.
    • After power-up, the device enters Sleep Mode.
  • Data Consistency: Always use burst reads (starting from 0xF7) to ensure data consistency via internal shadowing.

2. Complete Register Map

Address Name Size Reset Value R/W Brief Description
0x88 - 0x89 dig_T1 16-bit Individual R Temperature calibration parameter (Unsigned)
0x8A - 0x8B dig_T2 16-bit Individual R Temperature calibration parameter (Signed)
0x8C - 0x8D dig_T3 16-bit Individual R Temperature calibration parameter (Signed)
0x8E - 0x8F dig_P1 16-bit Individual R Pressure calibration parameter (Unsigned)
0x90 - 0x91 dig_P2 16-bit Individual R Pressure calibration parameter (Signed)
0x92 - 0x93 dig_P3 16-bit Individual R Pressure calibration parameter (Signed)
0x94 - 0x95 dig_P4 16-bit Individual R Pressure calibration parameter (Signed)
0x96 - 0x97 dig_P5 16-bit Individual R Pressure calibration parameter (Signed)
0x98 - 0x99 dig_P6 16-bit Individual R Pressure calibration parameter (Signed)
0x9A - 0x9B dig_P7 16-bit Individual R Pressure calibration parameter (Signed)
0x9C - 0x9D dig_P8 16-bit Individual R Pressure calibration parameter (Signed)
0x9E - 0x9F dig_P9 16-bit Individual R Pressure calibration parameter (Signed)
0xA1 dig_H1 8-bit Individual R Humidity calibration parameter (Unsigned)
0xD0 id 8-bit 0x60 R Chip ID (Fixed at 0x60)
0xE0 reset 8-bit 0x00 W Soft reset register (Write 0xB6 to trigger)
0xE1 - 0xE2 dig_H2 16-bit Individual R Humidity calibration parameter (Signed)
0xE3 dig_H3 8-bit Individual R Humidity calibration parameter (Unsigned)
0xE4 - 0xE5[3:0] dig_H4 12-bit Individual R Humidity calibration parameter (Signed)
0xE5[7:4] - 0xE6 dig_H5 12-bit Individual R Humidity calibration parameter (Signed)
0xE7 dig_H6 8-bit Individual R Humidity calibration parameter (Signed)
0xF2 ctrl_hum 8-bit 0x00 R/W Humidity oversampling settings
0xF3 status 8-bit 0x00 R Device status (measuring and update flags)
0xF4 ctrl_meas 8-bit 0x00 R/W Pressure/Temp oversampling and sensor mode
0xF5 config 8-bit 0x00 R/W Rate, filter, and SPI interface options
0xF7 press_msb 8-bit 0x80 R Raw pressure MSB [19:12]
0xF8 press_lsb 8-bit 0x00 R Raw pressure LSB [11:4]
0xF9 press_xlsb 8-bit 0x00 R Raw pressure XLSB [3:0] (Bits 7:4)
0xFA temp_msb 8-bit 0x80 R Raw temperature MSB [19:12]
0xFB temp_lsb 8-bit 0x00 R Raw temperature LSB [11:4]
0xFC temp_xlsb 8-bit 0x00 R Raw temperature XLSB [3:0] (Bits 7:4)
0xFD hum_msb 8-bit 0x80 R Raw humidity MSB [15:8]
0xFE hum_lsb 8-bit 0x00 R Raw humidity LSB [7:0]

3. Bit-Field Details

Register 0xF2: ctrl_hum

Bits Field Name Reset R/W Description
7:3 Reserved 0 R Reserved
2:0 osrs_h[2:0] 000 R/W Humidity oversampling: 000: Skipped; 001: x1; 010: x2; 011: x4; 100: x8; 101 or others: x16

Register 0xF3: status

Bits Field Name Reset R/W Description
7:4 Reserved 0 R Reserved
3 measuring 0 R 1 when conversion is running, 0 when results transferred to data registers
2:1 Reserved 0 R Reserved
0 im_update 0 R 1 when NVM data is being copied to image registers

Register 0xF4: ctrl_meas

Bits Field Name Reset R/W Description
7:5 osrs_t[2:0] 000 R/W Temperature oversampling: 000: Skipped; 001: x1; 010: x2; 011: x4; 100: x8; 101 or others: x16
4:2 osrs_p[2:0] 000 R/W Pressure oversampling: 000: Skipped; 001: x1; 010: x2; 011: x4; 100: x8; 101 or others: x16
1:0 mode[1:0] 00 R/W Sensor mode: 00: Sleep; 01 or 10: Forced; 11: Normal

Register 0xF5: config

Bits Field Name Reset R/W Description
7:5 t_sb[2:0] 000 R/W Standby time (Normal mode): 000: 0.5ms; 001: 62.5ms; 010: 125ms; 011: 250ms; 100: 500ms; 101: 1000ms; 110: 10ms; 111: 20ms
4:2 filter[2:0] 000 R/W IIR filter coefficient: 000: Off; 001: 2; 010: 4; 011: 8; 100 or others: 16
1 Reserved 0 R Reserved
0 spi3w_en 0 R/W 1: Enables 3-wire SPI interface

Data Registers (0xF7 - 0xFE)

  • Pressure (0xF7-0xF9): 20-bit unsigned. press_msb << 12 | press_lsb << 4 | press_xlsb >> 4.
  • Temperature (0xFA-0xFC): 20-bit unsigned. temp_msb << 12 | temp_lsb << 4 | temp_xlsb >> 4.
  • Humidity (0xFD-0xFE): 16-bit unsigned. hum_msb << 8 | hum_lsb.

4. Operating Procedures & Data Conversion

Initialization Sequence

  1. Soft Reset: Write 0xB6 to 0xE0. Wait 2ms.
  2. Read Calibration: Read registers 0x88-0xA1 and 0xE1-0xE7 to store trimming parameters.
  3. Configure Humidity: Write ctrl_hum (0xF2). Note: This write only takes effect after a subsequent write to ctrl_meas.
  4. Configure Mode/Oversampling: Write ctrl_meas (0xF4).
  5. Configure Filter/Standby: Write config (0xF5).

Measurement (Forced Mode)

  1. Write mode = 01 to ctrl_meas (0xF4).
  2. Poll status (0xF3) bit 3 (measuring) until it returns to 0.
  3. Burst read 0xF7 through 0xFE.

Data Conversion (32-bit Integer)

The variable t_fine is calculated during temperature compensation and required for pressure and humidity.

Temperature (°C):

// Returns temperature in DegC, resolution is 0.01 DegC. Output "5123" = 51.23°C.
BME280_S32_t var1, var2, T;
var1 = ((((adc_T >> 3) - ((BME280_S32_t)dig_T1 << 1))) * ((BME280_S32_t)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((BME280_S32_t)dig_T1)) * ((adc_T >> 4) - ((BME280_S32_t)dig_T1))) >> 12) * ((BME280_S32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;

Pressure (Pa): (Uses 64-bit integer for high accuracy)

// Returns pressure in Pa as Q24.8 format (24 integer bits and 8 fractional bits).
// Output "24674867" = 24674867/256 = 96386.2 Pa
BME280_S64_t var1, var2, p;
var1 = ((BME280_S64_t)t_fine) - 128000;
var2 = var1 * var1 * (BME280_S64_t)dig_P6;
var2 = var2 + ((var1 * (BME280_S64_t)dig_P5) << 17);
var2 = var2 + (((BME280_S64_t)dig_P4) << 35);
var1 = ((var1 * var1 * (BME280_S64_t)dig_P3) >> 8) + ((var1 * (BME280_S64_t)dig_P2) << 12);
var1 = (((((BME280_S64_t)1) << 47) + var1)) * ((BME280_S64_t)dig_P1) >> 33;
if (var1 == 0) return 0; // Avoid div by zero
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((BME280_S64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((BME280_S64_t)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + ((BME280_S64_t)dig_P7 << 4);
return (BME280_U32_t)p;

Humidity (%RH):

// Returns humidity in %RH as Q22.10 format. Output "47445" = 46.333 %RH
BME280_S32_t v_x1_u32r;
v_x1_u32r = (t_fine - ((BME280_S32_t)76800));
v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)dig_H4) << 20) - (((BME280_S32_t)dig_H5) * v_x1_u32r)) + ((BME280_S32_t)16384)) >> 15) * (((((v_x1_u32r * ((BME280_S32_t)dig_H6)) >> 10) * ((v_x1_u32r * ((BME280_S32_t)dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) * ((BME280_S32_t)dig_H2) + 8192) >> 14);
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_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 (BME280_U32_t)(v_x1_u32r >> 12);

5. Debugging Checklist

  • Register Update Order: Changes to ctrl_hum (0xF2) only apply after a write to ctrl_meas (0xF4).
  • SPI Mode Lock: If CSB is not high during power-on, the device may lock into SPI mode and ignore I2C.
  • Shadowing Trap: If you read registers individually (not burst), the MSB and LSB might come from different measurement cycles. Always burst read 0xF7 to 0xFE.
  • IIR Filter Reset: Writing to the filter bits in config (0xF5) resets the IIR filter memory.
  • Status Flags:
    • measuring == 1: Conversion is in progress.
    • im_update == 1: NVM copy in progress. Do not write to configuration registers during this time.
  • Invalid Data: Raw values of 0x80000 (Pressure/Temp) or 0x8000 (Humidity) indicate the measurement was skipped or is not yet ready.
  • Bus Recovery: If the I2C bus hangs, toggle the VDD line or perform a soft reset by writing 0xB6 to 0xE0 (if the bus is still responsive).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment