Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
BME280.cpp
00001 #include "mbed.h" 00002 #include "BME280.h" 00003 00004 /* internal registers */ 00005 #define REG_HUM_LSB 0xFE 00006 #define REG_HUM_MSB 0xFD 00007 #define REG_TEMP_XLSB 0xFC 00008 #define REG_TEMP_LSB 0xFB 00009 #define REG_TEMP_MSB 0xFA 00010 #define REG_PRESS_XLSB 0xF9 00011 #define REG_PRESS_LSB 0xF8 00012 #define REG_PRESS_MSB 0xF7 00013 #define REG_CONFIG 0xF5 00014 #define REG_CTRL_MEAS 0xF4 00015 #define REG_STATUS 0xF3 00016 #define REG_CTRL_HUM 0xF2 00017 #define REG_RESET 0xE0 00018 #define REG_ID 0xD0 00019 00020 #define REG_CALIB00 0x88 00021 #define REG_CALIB25 0xA1 00022 #define REG_CALIB26 0xE1 00023 #define REG_CALIB41 0xF0 00024 00025 /** Trimming parameters */ 00026 /* temperature */ 00027 #define REG_T1_LSB 0x88 00028 #define REG_T1_MSB 0x89 00029 #define REG_T2_LSB 0x8A 00030 #define REG_T2_MSB 0x8B 00031 #define REG_T3_LSB 0x8C 00032 #define REG_T3_MSB 0x8D 00033 /* pressure */ 00034 #define REG_P1_LSB 0x8E 00035 #define REG_P1_MSB 0x8F 00036 #define REG_P2_LSB 0x90 00037 #define REG_P2_MSB 0x91 00038 #define REG_P3_LSB 0x92 00039 #define REG_P3_MSB 0x93 00040 #define REG_P4_LSB 0x94 00041 #define REG_P4_MSB 0x95 00042 #define REG_P5_LSB 0x96 00043 #define REG_P5_MSB 0x97 00044 #define REG_P6_LSB 0x98 00045 #define REG_P6_MSB 0x99 00046 #define REG_P7_LSB 0x9A 00047 #define REG_P7_MSB 0x9B 00048 #define REG_P8_LSB 0x9C 00049 #define REG_P8_MSB 0x9D 00050 #define REG_P9_LSB 0x9E 00051 #define REG_P9_MSB 0x9F 00052 /* humidity */ 00053 #define REG_H1 0xA1 00054 #define REG_H2_LSB 0xE1 00055 #define REG_H2_MSB 0xE2 00056 #define REG_H3 0xE3 00057 #define REG_H4 0xE4 00058 #define REG_H5 0xE5 00059 #define REG_H6 0xE7 00060 00061 /* 00062 * Register description 00063 * 0xD0 "id" 00064 * chip identification number chip_id[7:0], which is 0x60 00065 * 00066 * 0xE0 "reset" 00067 * Software reset register, writing 0xB6 causes complete power-on-reset. 00068 * 00069 * 0xF2 "ctrl_hum" 00070 * Specifies the humidity data acquision options. 00071 * Note: Changes to this register only become effective after a write 00072 * operaion to "ctrl_meas". 00073 * bit[2:0] osrs_h[2:0] Controls oversampling of humidity data. 00074 * 000: Skipped (output set to 0x8000) 00075 * 001: oversampling x1 00076 * 010: oversampling x2 00077 * 011: oversampling x4 00078 * 100: oversampling x8 00079 * 101, others, oversampling x16 00080 * 00081 * 0xF3 "status" 00082 * bit[3] measuring[0] Automatically set to '1' during conversion 00083 * and back to '0' when done 00084 * bit[0] im_update[0] Automatically set to '1' during NVM data copy 00085 * and back to '0' when done 00086 * 00087 * 0xF4 "ctrl_meas" 00088 * Specifies the pressure and temperature data acquision options. 00089 * Note: This register needs to be written after canging "ctrl_hum" to take effect. 00090 * bit[7:5] osrs_t[2:0] Controls oversampling of temperature data 00091 * bit value is similar to osrs_h (except 000 output set to 0x80000) 00092 * bit[4:2] osrs_p[2:0] Controls oversampling of pressure data 00093 * bit value is similar to osrs_h (except 000 output set to 0x80000) 00094 * bit[1:0] mode[1:0] Controls the sensor mode. 00095 * 00: Sleep mode 00096 * 01: Forced mode 00097 * 10: Forced mode 00098 * 11: Normal mode 00099 * 00100 * 0xF5 "config" 00101 * Specifies the rate, filter and interface options. 00102 * Writes to "config" in normal mode may be ignored. 00103 * In sleep mode writes are not ignored. 00104 * bit[7:5] t_sb[2:0] Controls inactive duration t_standby in normal mode. 00105 * 000: 0.5 [ms] 00106 * 001: 62.5 [ms] 00107 * 010: 125 [ms] 00108 * 011: 250 [ms] 00109 * 100: 500 [ms] 00110 * 101: 1000 [ms] 00111 * 110: 10 [ms] 00112 * 111: 20 [ms] 00113 * bit[4:2] filter[2:0] Controls the time constant of the IIR filter. 00114 * 000: Filter off 00115 * 001: 2 00116 * 010: 4 00117 * 011: 8 00118 * 100, others: 16 00119 * 00120 * 0xF7 .. 0xF9 "press" (_msb, _lsb, _xlsb) 00121 * 0xF7 bit[7:0] press_msb[7:0] MSB part up[19:12] 00122 * 0xF8 bit[7:0] press_lsb[7:0] LSB part up[11:4] 00123 * 0xF9 bit[7:4] press_xlsb[3:0] XLSB part up[3:0] 00124 * 00125 * 0xFA .. 0xFC "temp" (_msb, _lsb, _xlsb) 00126 * 0xFA bit[7:0] temp_msb[7:0] MSB part ut[19:12] 00127 * 0xFB bit[7:0] temp_lsb[7:0] LSB part ut[11:4] 00128 * 0xFC bit[7:4] temp_xlsp[3:0] XLSB part ut[3:0] 00129 * 00130 * 0xFD .. 0xFE "hum" (_msb, _lsb) 00131 * 0xFD bit[7:0] hum_msb[7:0] MSB part uh[15:8] 00132 * 0xFE bit[7:0] hum_lsb[7:0] LSB part uh[7:0] 00133 */ 00134 /* 00135 * Compensation parameter storage, naming and data type 00136 * Register addr, Register content, Data type 00137 * 0x88/0x89, dig_T1[7:0]/[15:8], unsigned short 00138 * 0x8A/0x8B, dig_T2[7:0]/[15:8], signed short 00139 * 0x8C/0x8D, dig_T3[7:0]/[15:8], signed short 00140 * 0x8E/0x8F, dig_P1[7:0]/[15:8], unsigned short 00141 * 0x90/0x91, dig_P2[7:0]/[15:8], signed short 00142 * 0x92/0x93, dig_P3[7:0]/[15:8], signed short 00143 * 0x94/0x95, dig_P4[7:0]/[15:8], signed short 00144 * 0x96/0x97, dig_P5[7:0]/[15:8], signed short 00145 * 0x98/0x99, dig_P6[7:0]/[15:8], signed short 00146 * 0x9A/0x9B, dig_P7[7:0]/[15:8], signed short 00147 * 0x9C/0x9D, dig_P8[7:0]/[15:8], signed short 00148 * 0x9E/0x9F, dig_P9[7:0]/[15:8], signed short 00149 * 0xA1, dig_H1[7:0], unsigned char 00150 * 0xE1/0xE2, dig_H2[7:0]/[15:8], signed short 00151 * 0xE3, dig_H3[7:0], unsigned char 00152 * 0xE4/0xE5[3:0], dig_H4[11:4]/[3:0] signed short 00153 * 0xE5[7:4]/0xE6, dig_H5[3:0]/[11:4] signed short 00154 * 0xE7, dig_H6[7:0], signed char 00155 */ 00156 00157 void BME280::init(void) 00158 { 00159 uint8_t data[18] ; 00160 00161 data[0] = REG_CTRL_HUM ; 00162 data[1] = 0x03 ; /* Humidity oversampling x4 */ 00163 writeRegs(data, 2) ; 00164 00165 data[0] = REG_CTRL_MEAS ; 00166 data[1] = (0x3 << 5) /* temp oversample x4 */ 00167 | (0x3 << 2) /* pres oversample x4 */ 00168 | (0x00) /* Sleep Mode */ 00169 ; 00170 writeRegs(data, 2) ; 00171 00172 data[0] = REG_CONFIG ; 00173 data[1] = (0x4 << 5) /* standby 500ms */ 00174 | (0x0 << 2) /* filter off */ 00175 | (0x0) /* spi 4wire mode */ 00176 ; 00177 writeRegs(data, 2) ; 00178 00179 /* read dig_T regs */ 00180 readRegs(REG_T1_LSB, data, 6) ; 00181 dig_T1 = (data[1] << 8) | data[0] ; 00182 dig_T2 = (data[3] << 8) | data[2] ; 00183 dig_T3 = (data[5] << 8) | data[4] ; 00184 // printf("dig_T1:0x%04X, dig_T2:0x%04X, dig_T3:0x%04X\n",dig_T1, dig_T2, dig_T3) ; 00185 00186 /* read dig_P regs */ 00187 readRegs(REG_P1_LSB, data, 18) ; 00188 dig_P1 = (data[ 1] << 8) | data[ 0] ; 00189 dig_P2 = (data[ 3] << 8) | data[ 2] ; 00190 dig_P3 = (data[ 5] << 8) | data[ 4] ; 00191 dig_P4 = (data[ 7] << 8) | data[ 6] ; 00192 dig_P5 = (data[ 9] << 8) | data[ 8] ; 00193 dig_P6 = (data[11] << 8) | data[10] ; 00194 dig_P7 = (data[13] << 8) | data[12] ; 00195 dig_P8 = (data[15] << 8) | data[14] ; 00196 dig_P9 = (data[17] << 8) | data[16] ; 00197 // printf("dig_P1:0x%04X, dig_P2:0x%04X, dig_P3:0x%04X\n",dig_P1, dig_P2, dig_P3) ; 00198 // printf("dig_P4:0x%04X, dig_P5:0x%04X, dig_P6:0x%04X\n",dig_P4, dig_P5, dig_P6) ; 00199 // printf("dig_P7:0x%04X, dig_P8:0x%04X, dig_P9:0x%04X\n",dig_P7, dig_P8, dig_P9) ; 00200 00201 /* read dig_H regs */ 00202 readRegs(REG_H1, data, 1) ; 00203 dig_H1 = data[0] ; 00204 readRegs(REG_H2_LSB, data, 2) ; 00205 dig_H2 = (data[1] << 8) | data[0] ; 00206 readRegs(REG_H3, data, 1) ; 00207 dig_H3 = data[0] ; 00208 readRegs(REG_H4, data, 3) ; 00209 dig_H4 = (data[0] << 4) | (data[1] & 0x0F) ; 00210 dig_H5 = (data[2] << 4) | (data[1] >> 4) ; 00211 readRegs(REG_H6, data, 1) ; 00212 dig_H6 = data[0] ; 00213 // printf("dig_H1:0x%04X, dig_H2:0x%04X, dig_H3:0x%04X\n",dig_H1, dig_H2, dig_H3) ; 00214 // printf("dig_H4:0x%04X, dig_H5:0x%04X, dig_H6:0x%04X\n",dig_H4, dig_H5, dig_H6) ; 00215 00216 trigger() ; /* dummy measure */ 00217 } 00218 00219 BME280::BME280(PinName sda, PinName scl, int addr) 00220 { 00221 m_i2c = new I2C(sda, scl) ; 00222 m_addr = (addr << 1) ; 00223 m_spi = 0 ; 00224 m_cs = 0 ; 00225 init() ; 00226 } 00227 00228 BME280::BME280(PinName sck, PinName miso, PinName mosi, PinName cs) 00229 { 00230 m_cs = new DigitalOut(cs, 1) ; 00231 m_spi = new SPI(mosi, miso, sck) ; 00232 m_spi->format(8, 3) ; 00233 m_i2c = 0 ; 00234 m_addr = 0 ; 00235 init() ; 00236 } 00237 00238 BME280::~BME280() 00239 { 00240 if (m_spi) { 00241 delete m_spi ; 00242 delete m_cs ; 00243 } 00244 if (m_i2c) { 00245 delete m_i2c ; 00246 m_addr = 0 ; 00247 } 00248 } 00249 00250 void BME280::i2c_readRegs(int addr, uint8_t * data, int len) { 00251 char t[1] = {addr} ; 00252 m_i2c->write(m_addr, t, 1, true) ; 00253 m_i2c->read(m_addr, (char*)data, len) ; 00254 } 00255 00256 void BME280::i2c_writeRegs(uint8_t * data, int len) { 00257 m_i2c->write(m_addr, (char *)data, len) ; 00258 } 00259 00260 void BME280::spi_readRegs(int addr, uint8_t * data, int len) { 00261 *m_cs = 0 ; 00262 m_spi->write(addr | 0x80) ; 00263 for (int i = 0 ; i < len ; i++ ) { 00264 data[i] = m_spi->write((addr+i)|0x80) ; 00265 } 00266 m_spi->write(0x00) ; // to terminate read mode 00267 *m_cs = 1 ; 00268 } 00269 00270 void BME280::spi_writeRegs(uint8_t * data, int len) { 00271 *m_cs = 0 ; 00272 for (int i = 0 ; i < len-1 ; i++ ) { 00273 m_spi->write((data[0]+i)^0x80) ; /* register address */ 00274 m_spi->write(data[i+1]) ; /* data to write */ 00275 00276 } 00277 *m_cs = 1 ; 00278 } 00279 00280 void BME280::readRegs(int addr, uint8_t *data, int len) 00281 { 00282 if (m_spi) { 00283 spi_readRegs(addr, data, len) ; 00284 } else if (m_i2c) { 00285 i2c_readRegs(addr, data, len) ; 00286 } 00287 } 00288 00289 void BME280::writeRegs(uint8_t *data, int len) 00290 { 00291 if (m_spi) { 00292 spi_writeRegs(data, len) ; 00293 } else if (m_i2c) { 00294 i2c_writeRegs(data, len) ; 00295 } 00296 } 00297 00298 void BME280::reset(void) 00299 { 00300 uint8_t data[2] ; 00301 data[0] = REG_RESET ; 00302 data[1] = 0xB6 ; 00303 writeRegs(data, 2) ; 00304 } 00305 00306 void BME280::trigger(void) 00307 { 00308 uint8_t data[2] ; 00309 readRegs(REG_CTRL_MEAS, &data[1], 1) ; 00310 00311 data[0] = REG_CTRL_MEAS ; 00312 data[1] = (data[1] & 0xFC) /* keep oversampling */ 00313 | (0x2) /* Forced Mode */ 00314 ; 00315 writeRegs(data, 2) ; 00316 } 00317 00318 uint8_t BME280::busy(void) 00319 { 00320 uint8_t data[1] ; 00321 readRegs(REG_STATUS, data, 1) ; 00322 return( data[0] & 0x9 ) ; 00323 } 00324 00325 uint8_t BME280::getID(void) 00326 { 00327 uint8_t data[1] ; 00328 readRegs(REG_ID, data, 1) ; 00329 return(data[0]) ; 00330 } 00331 00332 float BME280::getTemperature(void) 00333 { 00334 float tempf ; 00335 uint8_t data[3] ; 00336 BME280_S32_t var1, var2, T ; 00337 BME280_S32_t adc_T ; 00338 00339 readRegs(REG_TEMP_MSB, data, 3) ; 00340 adc_T = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); 00341 00342 var1 = ((((adc_T>>3) - ((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11; 00343 var2 = (((((adc_T>>4) - ((BME280_S32_t)dig_T1)) * ((adc_T>>4) - ((BME280_S32_t)dig_T1))) >> 12) * 00344 ((BME280_S32_t)dig_T3)) >> 14; 00345 t_fine = var1 + var2; 00346 T = (t_fine * 5 + 128) >> 8; 00347 00348 tempf = (float)T; 00349 return (tempf/100.0f); 00350 } 00351 00352 float BME280::getPressure(void) 00353 { 00354 BME280_S32_t adc_P ; 00355 BME280_S64_t var1, var2, p ; 00356 float pressf; 00357 uint8_t data[3]; 00358 00359 readRegs(REG_PRESS_MSB, data, 3) ; 00360 adc_P = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); 00361 00362 var1 = ((BME280_S64_t)t_fine) - 128000; 00363 var2 = var1 * var1 * (BME280_S64_t)dig_P6; 00364 var2 = var2 + ((var1*(BME280_S64_t)dig_P5)<<17); 00365 var2 = var2 + (((BME280_S64_t)dig_P4)<<35); 00366 var1 = ((var1 * var1 * (BME280_S64_t)dig_P3)>>8) + ((var1 * (BME280_S64_t)dig_P2)<<12); 00367 var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)dig_P1)>>33; 00368 if (var1 == 0) { 00369 return 0; // avoid exception caused by division by zero 00370 } 00371 p = 1048576-adc_P; 00372 p = (((p<<31)-var2)*3125)/var1; 00373 var1 = (((BME280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25; 00374 var2 = (((BME280_S64_t)dig_P8) * p) >> 19; 00375 p = ((p + var1 + var2) >> 8) + (((BME280_S64_t)dig_P7)<<4); 00376 00377 pressf = (float)(p >> 8) ; 00378 return (pressf/100.0f); 00379 } 00380 00381 float BME280::getHumidity(void) 00382 { 00383 BME280_S32_t adc_H; 00384 BME280_S32_t v_x1_u32r ; 00385 float humf; 00386 uint8_t data[2]; 00387 00388 readRegs(REG_HUM_MSB, data, 2) ; 00389 adc_H = (data[0] << 8) | data[1]; 00390 00391 v_x1_u32r = (t_fine - ((BME280_S32_t)76800)); 00392 v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)dig_H4) << 20) - (((BME280_S32_t)dig_H5) * v_x1_u32r)) + 00393 ((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)dig_H6)) >> 10) * (((v_x1_u32r * 00394 ((BME280_S32_t)dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) * 00395 ((BME280_S32_t)dig_H2) + 8192) >> 14)); 00396 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)dig_H1)) >> 4)); 00397 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); 00398 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); 00399 humf = (float)(v_x1_u32r >> 12) ; 00400 00401 return (humf/1024.0f); 00402 }
Generated on Sat Jul 30 2022 14:00:05 by
1.7.2