bme280.c (4780B)
1 #include "bme280.h" 2 #include "i2c.h" 3 #include "tmr0.h" 4 5 #define MODE_WRITE 0 6 #define MODE_READ 1 7 8 #define BME280_DELAY 100 9 10 #define BME280_SAMPLE_SKIP 0x00 11 #define BME280_SAMPLE_X1 0x01 12 #define BME280_FILTER_OFF 0x00 13 #define BME280_STANDBY_0_5 0x00 14 #define BME280_MODE_NORMAL 0x03 15 #define BME280_RESET_POWERON 0xb6 16 17 #define BME280_ADDR 0xee 18 #define BME280_CHIPID 0x60 19 20 #define BME280_REG_DIG_T1 0x88 21 #define BME280_REG_DIG_T2 0x8a 22 #define BME280_REG_DIG_T3 0x8c 23 24 #define BME280_REG_DIG_H1 0xa1 25 #define BME280_REG_DIG_H2 0xe1 26 #define BME280_REG_DIG_H3 0xe3 27 #define BME280_REG_DIG_H4 0xe4 28 #define BME280_REG_DIG_H5 0xe5 29 #define BME280_REG_DIG_H6 0xe7 30 31 #define BME280_REG_CHIPID 0xd0 32 #define BME280_REG_SOFTRESET 0xe0 33 34 #define BME280_REG_CTLHUM 0xf2 35 #define BME280_REG_STATUS 0xf3 36 #define BME280_REG_CTL 0xf4 37 #define BME280_REG_CONFIG 0xf5 38 #define BME280_REG_PRESS_MSB 0xf7 39 40 struct bme280_calib { 41 uint16_t dig_t1; 42 int16_t dig_t2; 43 int16_t dig_t3; 44 /* Pressure fields are not used to preserve space. */ 45 uint8_t dig_h1; 46 int16_t dig_h2; 47 uint8_t dig_h3; 48 int16_t dig_h4; 49 int16_t dig_h5; 50 int8_t dig_h6; 51 }; 52 53 static void bme280_write(uint8_t, uint8_t); 54 static uint8_t bme280_read8(uint8_t); 55 static uint16_t bme280_read16(uint8_t); 56 static void bme280_update(void); 57 58 static struct bme280_calib cal; 59 static int32_t adc_t, adc_h, t_fine; 60 61 static void 62 bme280_write(uint8_t reg, uint8_t dat) 63 { 64 i2c_start(); 65 i2c_write(BME280_ADDR | MODE_WRITE); 66 i2c_write(reg); 67 i2c_write(dat); 68 i2c_stop(); 69 } 70 71 static uint8_t 72 bme280_read8(uint8_t reg) 73 { 74 uint8_t c; 75 76 i2c_start(); 77 i2c_write(BME280_ADDR | MODE_WRITE); 78 i2c_write(reg); 79 i2c_restart(); 80 i2c_write(BME280_ADDR | MODE_READ); 81 c = i2c_read(0); 82 i2c_stop(); 83 return (c); 84 } 85 86 static uint16_t 87 bme280_read16(uint8_t reg) 88 { 89 uint16_t c; 90 91 i2c_start(); 92 i2c_write(BME280_ADDR | MODE_WRITE); 93 i2c_write(reg); 94 i2c_restart(); 95 i2c_write(BME280_ADDR | MODE_READ); 96 c = i2c_read(1); 97 c |= i2c_read(0) << 8; 98 i2c_stop(); 99 return (c); 100 } 101 102 static void 103 bme280_update(void) 104 { 105 union { 106 uint8_t a[4]; 107 uint32_t v; 108 } r; 109 110 i2c_start(); 111 i2c_write(BME280_ADDR | MODE_WRITE); 112 i2c_write(BME280_REG_PRESS_MSB); 113 i2c_restart(); 114 i2c_write(BME280_ADDR | MODE_READ); 115 116 /* Ignore pressure */ 117 (void)i2c_read(1); 118 (void)i2c_read(1); 119 (void)i2c_read(1); 120 121 r.a[3] = 0x00; 122 r.a[2] = i2c_read(1); 123 r.a[1] = i2c_read(1); 124 r.a[0] = i2c_read(1); 125 adc_t = (r.v >> 4) & 0xfffff; 126 127 r.a[2] = 0x00; 128 r.a[1] = i2c_read(1); 129 r.a[0] = i2c_read(0); 130 adc_h = r.v & 0xffff; 131 132 i2c_stop(); 133 } 134 135 int 136 bme280_init(void) 137 { 138 if (bme280_read8(BME280_REG_CHIPID) != BME280_CHIPID) 139 return (-1); 140 bme280_write(BME280_REG_SOFTRESET, BME280_RESET_POWERON); 141 tmr0_delay_ms(BME280_DELAY); 142 while ((bme280_read8(BME280_REG_STATUS) & 0x01) == 0x01) 143 tmr0_delay_ms(BME280_DELAY); 144 145 cal.dig_t1 = bme280_read16(BME280_REG_DIG_T1); 146 cal.dig_t2 = bme280_read16(BME280_REG_DIG_T2); 147 cal.dig_t3 = bme280_read16(BME280_REG_DIG_T3); 148 149 cal.dig_h1 = bme280_read8(BME280_REG_DIG_H1); 150 cal.dig_h2 = bme280_read16(BME280_REG_DIG_H2); 151 cal.dig_h3 = bme280_read8(BME280_REG_DIG_H3); 152 cal.dig_h4 = ((uint16_t)bme280_read8(BME280_REG_DIG_H4) << 4) | 153 (bme280_read8(BME280_REG_DIG_H4 + 1) & 0x0f); 154 if (cal.dig_h4 & 0x0800) /* H4 < 0 */ 155 cal.dig_h4 |= 0xf000; 156 cal.dig_h5 = ((uint16_t)bme280_read8(BME280_REG_DIG_H5 + 1) << 4) | 157 (bme280_read8(BME280_REG_DIG_H5) >> 4); 158 if (cal.dig_h5 & 0x0800) /* H5 < 0 */ 159 cal.dig_h5 |= 0xf000; 160 cal.dig_h6 = bme280_read8(BME280_REG_DIG_H6); 161 162 bme280_write(BME280_REG_CTLHUM, BME280_SAMPLE_X1); 163 bme280_write(BME280_REG_CONFIG, ((BME280_STANDBY_0_5 << 5) | 164 (BME280_FILTER_OFF << 2)) & 0xfc); 165 bme280_write(BME280_REG_CTL, ((BME280_SAMPLE_X1 << 5) | 166 (BME280_SAMPLE_SKIP << 2)) | BME280_MODE_NORMAL); 167 168 tmr0_delay_ms(BME280_DELAY); 169 170 return (0); 171 } 172 173 /* Black magic taken (stolen) from BME280's datasheet. */ 174 int32_t 175 bme280_read_temp(void) 176 { 177 int32_t v1, v2; 178 179 bme280_update(); 180 v1 = ((((adc_t >> 3) - ((int32_t)cal.dig_t1 << 1))) * 181 ((int32_t)cal.dig_t2)) >> 11; 182 v2 = (((((adc_t >> 4) - ((int32_t)cal.dig_t1)) * 183 ((adc_t >> 4) - ((int32_t)cal.dig_t1))) >> 12) * 184 ((int32_t)cal.dig_t3)) >> 14; 185 186 t_fine = v1 + v2; 187 188 return ((t_fine * 5 + 128) / 256); 189 } 190 191 uint32_t 192 bme280_read_humid(void) 193 { 194 int32_t v = 0; 195 196 bme280_update(); 197 v = (t_fine - ((int32_t)76800)); 198 199 v = (((((adc_h << 14) - (((int32_t)cal.dig_h4) << 20) - 200 (((int32_t)cal.dig_h5) * v)) + ((int32_t)16384)) >> 15) * 201 (((((((v * ((int32_t)cal.dig_h6)) >> 10) * 202 (((v * ((int32_t)cal.dig_h3)) >> 11) + ((int32_t)32768))) >> 10) + 203 ((int32_t)2097152)) * ((int32_t)cal.dig_h2) + 8192) >> 14)); 204 205 v = (v - (((((v >> 15) * (v >> 15)) >> 7) * ((int32_t)cal.dig_h1)) >> 4)); 206 v = (v < 0 ? 0 : v); 207 v = (v > 419430400 ? 419430400 : v); 208 209 return ((uint32_t)(v >> 12)); 210 }