2 ****************************************************************************
3 * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
9 * Usage: Sensor Driver support file for BME280 sensor
11 ****************************************************************************
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
24 * Neither the name of the copyright holder nor the names of the
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
33 * OR CONTRIBUTORS BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
35 * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
36 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
41 * ANY WAY OUT OF THE USE OF THIS
42 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
44 * The information provided is believed to be accurate and reliable.
45 * The copyright holder assumes no responsibility
46 * for the consequences of use
47 * of such information nor for any infringement of patents or
48 * other rights of third parties which may result from its use.
49 * No license is granted by implication or otherwise under any patent or
50 * patent rights of the copyright holder.
51 **************************************************************************/
52 /*---------------------------------------------------------------------------*/
54 /*---------------------------------------------------------------------------*/
58 /*Enable the macro BME280_API to use this support file */
59 /*----------------------------------------------------------------------------*
60 * The following functions are used for reading and writing of
61 * sensor data using I2C or SPI communication
62 *----------------------------------------------------------------------------*/
64 /* \Brief: The function is used as I2C bus read
65 * \Return : Status of the I2C read
66 * \param dev_addr : The device address of the sensor
67 * \param reg_addr : Address of the first register, will data is going to be read
68 * \param reg_data : This data read from the sensor, which is hold in an array
69 * \param cnt : The no of byte of data to be read
71 s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
72 /* \Brief: The function is used as I2C bus write
73 * \Return : Status of the I2C write
74 * \param dev_addr : The device address of the sensor
75 * \param reg_addr : Address of the first register, will data is going to be written
76 * \param reg_data : It is a value hold in the array,
77 * will be used for write the value into the register
78 * \param cnt : The no of byte of data to be write
80 s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
81 /* \Brief: The function is used as SPI bus write
82 * \Return : Status of the SPI write
83 * \param dev_addr : The device address of the sensor
84 * \param reg_addr : Address of the first register, will data is going to be written
85 * \param reg_data : It is a value hold in the array,
86 * will be used for write the value into the register
87 * \param cnt : The no of byte of data to be write
89 s8 BME280_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
90 /* \Brief: The function is used as SPI bus read
91 * \Return : Status of the SPI read
92 * \param dev_addr : The device address of the sensor
93 * \param reg_addr : Address of the first register, will data is going to be read
94 * \param reg_data : This data read from the sensor, which is hold in an array
95 * \param cnt : The no of byte of data to be read */
96 s8 BME280_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
98 * \Brief: SPI/I2C init routine
100 s8 I2C_routine(void);
101 s8 SPI_routine(void);
103 /********************End of I2C/SPI function declarations***********************/
104 /* Brief : The delay routine
105 * \param : delay in ms
107 void BME280_delay_msek(u32 msek);
108 /* This function is an example for reading sensor data
110 * \return: communication result
112 s32 bme280_data_readout_template(void);
113 /*----------------------------------------------------------------------------*
114 * struct bme280_t parameters can be accessed by using bme280
115 * bme280_t having the following parameters
116 * Bus write function pointer: BME280_WR_FUNC_PTR
117 * Bus read function pointer: BME280_RD_FUNC_PTR
118 * Delay function pointer: delay_msec
119 * I2C address: dev_addr
120 * Chip id of the sensor: chip_id
121 *---------------------------------------------------------------------------*/
122 struct bme280_t bme280;
123 /* This function is an example for reading sensor data
125 * \return: communication result
127 s32 bme280_data_readout_template(void)
129 /* The variable used to assign the standby time*/
130 u8 v_stand_by_time_u8 = BME280_INIT_VALUE;
131 /* The variable used to read uncompensated temperature*/
132 s32 v_data_uncomp_temp_s32 = BME280_INIT_VALUE;
133 /* The variable used to read uncompensated pressure*/
134 s32 v_data_uncomp_pres_s32 = BME280_INIT_VALUE;
135 /* The variable used to read uncompensated pressure*/
136 s32 v_data_uncomp_hum_s32 = BME280_INIT_VALUE;
137 /* The variable used to read compensated temperature*/
138 s32 v_comp_temp_s32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
139 /* The variable used to read compensated pressure*/
140 u32 v_comp_press_u32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
141 /* The variable used to read compensated humidity*/
142 u32 v_comp_humidity_u32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
144 /* result of communication results*/
145 s32 com_rslt = ERROR;
149 /*********************** START INITIALIZATION ************************/
150 /* Based on the user need configure I2C or SPI interface.
151 * It is example code to explain how to use the bme280 API*/
156 /*--------------------------------------------------------------------------*
157 * This function used to assign the value/reference of
158 * the following parameters
163 *-------------------------------------------------------------------------*/
164 com_rslt = bme280_init(&bme280);
166 /* For initialization it is required to set the mode of
167 * the sensor as "NORMAL"
168 * data acquisition/read/write is possible in this mode
169 * by using the below API able to set the power mode as NORMAL*/
170 /* Set the power mode as NORMAL*/
171 com_rslt += bme280_set_power_mode(BME280_NORMAL_MODE);
172 /* For reading the pressure, humidity and temperature data it is required to
173 * set the OSS setting of humidity, pressure and temperature
174 * The "BME280_CTRLHUM_REG_OSRSH" register sets the humidity
175 * data acquisition options of the device.
176 * changes to this registers only become effective after a write operation to
177 * "BME280_CTRLMEAS_REG" register.
178 * In the code automated reading and writing of "BME280_CTRLHUM_REG_OSRSH"
179 * register first set the "BME280_CTRLHUM_REG_OSRSH" and then read and write
180 * the "BME280_CTRLMEAS_REG" register in the function*/
181 com_rslt += bme280_set_oversamp_humidity(BME280_OVERSAMP_1X);
183 /* set the pressure oversampling*/
184 com_rslt += bme280_set_oversamp_pressure(BME280_OVERSAMP_2X);
185 /* set the temperature oversampling*/
186 com_rslt += bme280_set_oversamp_temperature(BME280_OVERSAMP_4X);
187 /*--------------------------------------------------------------------------*/
188 /*------------------------------------------------------------------------*
189 ************************* START GET and SET FUNCTIONS DATA ****************
190 *---------------------------------------------------------------------------*/
191 /* This API used to Write the standby time of the sensor input
192 * value have to be given
193 * Normal mode comprises an automated perpetual cycling between an (active)
194 * Measurement period and an (inactive) standby period.
195 * The standby time is determined by the contents of the register t_sb.
196 * Standby time can be set using BME280_STANDBYTIME_125_MS.
197 * Usage Hint : bme280_set_standbydur(BME280_STANDBYTIME_125_MS)*/
199 com_rslt += bme280_set_standby_durn(BME280_STANDBY_TIME_1_MS);
201 /* This API used to read back the written value of standby time*/
202 com_rslt += bme280_get_standby_durn(&v_stand_by_time_u8);
203 /*-----------------------------------------------------------------*
204 ************************* END GET and SET FUNCTIONS ****************
205 *------------------------------------------------------------------*/
207 /************************* END INITIALIZATION *************************/
209 /*------------------------------------------------------------------*
210 ************ START READ UNCOMPENSATED PRESSURE, TEMPERATURE
211 AND HUMIDITY DATA ********
212 *---------------------------------------------------------------------*/
213 /* API is used to read the uncompensated temperature*/
214 com_rslt += bme280_read_uncomp_temperature(&v_data_uncomp_temp_s32);
216 /* API is used to read the uncompensated pressure*/
217 com_rslt += bme280_read_uncomp_pressure(&v_data_uncomp_pres_s32);
219 /* API is used to read the uncompensated humidity*/
220 com_rslt += bme280_read_uncomp_humidity(&v_data_uncomp_hum_s32);
222 /* API is used to read the uncompensated temperature,pressure
224 com_rslt += bme280_read_uncomp_pressure_temperature_humidity(
225 &v_data_uncomp_temp_s32, &v_data_uncomp_pres_s32, &v_data_uncomp_hum_s32);
226 /*--------------------------------------------------------------------*
227 ************ END READ UNCOMPENSATED PRESSURE AND TEMPERATURE********
228 *-------------------------------------------------------------------------*/
230 /*------------------------------------------------------------------*
231 ************ START READ COMPENSATED PRESSURE, TEMPERATURE
232 AND HUMIDITY DATA ********
233 *---------------------------------------------------------------------*/
234 /* API is used to compute the compensated temperature*/
235 v_comp_temp_s32[0] = bme280_compensate_temperature_int32(
236 v_data_uncomp_temp_s32);
238 /* API is used to compute the compensated pressure*/
239 v_comp_press_u32[0] = bme280_compensate_pressure_int32(
240 v_data_uncomp_pres_s32);
242 /* API is used to compute the compensated humidity*/
243 v_comp_humidity_u32[0] = bme280_compensate_humidity_int32(
244 v_data_uncomp_hum_s32);
246 /* API is used to read the compensated temperature, humidity and pressure*/
247 com_rslt += bme280_read_pressure_temperature_humidity(
248 &v_comp_press_u32[1], &v_comp_temp_s32[1], &v_comp_humidity_u32[1]);
249 /*--------------------------------------------------------------------*
250 ************ END READ COMPENSATED PRESSURE, TEMPERATURE AND HUMIDITY ********
251 *-------------------------------------------------------------------------*/
253 /*-----------------------------------------------------------------------*
254 ************************* START DE-INITIALIZATION ***********************
255 *-------------------------------------------------------------------------*/
256 /* For de-initialization it is required to set the mode of
257 * the sensor as "SLEEP"
258 * the device reaches the lowest power consumption only
259 * In SLEEP mode no measurements are performed
260 * All registers are accessible
261 * by using the below API able to set the power mode as SLEEP*/
262 /* Set the power mode as SLEEP*/
263 com_rslt += bme280_set_power_mode(BME280_SLEEP_MODE);
264 /*---------------------------------------------------------------------*
265 ************************* END DE-INITIALIZATION **********************
266 *---------------------------------------------------------------------*/
271 #define SPI_READ 0x80
272 #define SPI_WRITE 0x7F
273 #define BME280_DATA_INDEX 1
274 #define BME280_ADDRESS_INDEX 2
275 /*--------------------------------------------------------------------------*
276 * The following function is used to map the I2C bus read, write, delay and
277 * device address with global structure bme280
278 *-------------------------------------------------------------------------*/
279 s8 I2C_routine(void) {
280 /*--------------------------------------------------------------------------*
281 * By using bme280 the following structure parameter can be accessed
282 * Bus write function pointer: BME280_WR_FUNC_PTR
283 * Bus read function pointer: BME280_RD_FUNC_PTR
284 * Delay function pointer: delay_msec
285 * I2C address: dev_addr
286 *--------------------------------------------------------------------------*/
287 bme280.bus_write = BME280_I2C_bus_write;
288 bme280.bus_read = BME280_I2C_bus_read;
289 bme280.dev_addr = BME280_I2C_ADDRESS2;
290 bme280.delay_msec = BME280_delay_msek;
292 return BME280_INIT_VALUE;
295 /*---------------------------------------------------------------------------*
296 * The following function is used to map the SPI bus read, write and delay
297 * with global structure bme280
298 *--------------------------------------------------------------------------*/
299 s8 SPI_routine(void) {
300 /*--------------------------------------------------------------------------*
301 * By using bme280 the following structure parameter can be accessed
302 * Bus write function pointer: BME280_WR_FUNC_PTR
303 * Bus read function pointer: BME280_RD_FUNC_PTR
304 * Delay function pointer: delay_msec
305 *--------------------------------------------------------------------------*/
307 bme280.bus_write = BME280_SPI_bus_write;
308 bme280.bus_read = BME280_SPI_bus_read;
309 bme280.delay_msec = BME280_delay_msek;
311 return BME280_INIT_VALUE;
314 /************** I2C/SPI buffer length ******/
315 #define I2C_BUFFER_LEN 8
316 #define SPI_BUFFER_LEN 5
318 /*-------------------------------------------------------------------*
319 * This is a sample code for read and write the data by using I2C/SPI
320 * Use either I2C or SPI based on your need
321 * The device address defined in the bme280.h file
322 *-----------------------------------------------------------------------*/
323 /* \Brief: The function is used as I2C bus write
324 * \Return : Status of the I2C write
325 * \param dev_addr : The device address of the sensor
326 * \param reg_addr : Address of the first register, will data is going to be written
327 * \param reg_data : It is a value hold in the array,
328 * will be used for write the value into the register
329 * \param cnt : The no of byte of data to be write
331 s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
333 s32 iError = BME280_INIT_VALUE;
334 u8 array[I2C_BUFFER_LEN];
335 u8 stringpos = BME280_INIT_VALUE;
336 array[BME280_INIT_VALUE] = reg_addr;
337 for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
338 array[stringpos + BME280_DATA_INDEX] = *(reg_data + stringpos);
341 * Please take the below function as your reference for
342 * write the data using I2C communication
343 * "IERROR = I2C_WRITE_STRING(DEV_ADDR, array, cnt+1)"
344 * add your I2C write function here
345 * iError is an return value of I2C read function
346 * Please select your valid return value
347 * In the driver SUCCESS defined as 0
348 * and FAILURE defined as -1
350 * This is a full duplex operation,
351 * The first read data is discarded, for that extra write operation
352 * have to be initiated. For that cnt+1 operation done in the I2C write string function
353 * For more information please refer data sheet SPI communication:
358 /* \Brief: The function is used as I2C bus read
359 * \Return : Status of the I2C read
360 * \param dev_addr : The device address of the sensor
361 * \param reg_addr : Address of the first register, will data is going to be read
362 * \param reg_data : This data read from the sensor, which is hold in an array
363 * \param cnt : The no of data byte of to be read
365 s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
367 s32 iError = BME280_INIT_VALUE;
368 u8 array[I2C_BUFFER_LEN] = {BME280_INIT_VALUE};
369 u8 stringpos = BME280_INIT_VALUE;
370 array[BME280_INIT_VALUE] = reg_addr;
371 /* Please take the below function as your reference
372 * for read the data using I2C communication
373 * add your I2C rad function here.
374 * "IERROR = I2C_WRITE_READ_STRING(DEV_ADDR, ARRAY, ARRAY, 1, CNT)"
375 * iError is an return value of SPI write function
376 * Please select your valid return value
377 * In the driver SUCCESS defined as 0
378 * and FAILURE defined as -1
380 for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
381 *(reg_data + stringpos) = array[stringpos];
386 /* \Brief: The function is used as SPI bus read
387 * \Return : Status of the SPI read
388 * \param dev_addr : The device address of the sensor
389 * \param reg_addr : Address of the first register, will data is going to be read
390 * \param reg_data : This data read from the sensor, which is hold in an array
391 * \param cnt : The no of byte of data to be read
393 s8 BME280_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
395 s32 iError=BME280_INIT_VALUE;
396 u8 array[SPI_BUFFER_LEN]={0,};
398 /* For the SPI mode only 7 bits of register addresses are used.
399 The MSB of register address is declared the bit what functionality it is
400 read/write (read as 1/write as BME280_INIT_VALUE)*/
401 array[BME280_INIT_VALUE] = reg_addr|SPI_READ;/*read routine is initiated register address is mask with 0x80*/
403 * Please take the below function as your reference for
404 * read the data using SPI communication
405 * " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"
406 * add your SPI read function here
407 * iError is an return value of SPI read function
408 * Please select your valid return value
409 * In the driver SUCCESS defined as 0
410 * and FAILURE defined as -1
412 * This is a full duplex operation,
413 * The first read data is discarded, for that extra write operation
414 * have to be initiated. For that cnt+1 operation done in the SPI read
415 * and write string function
416 * For more information please refer data sheet SPI communication:
418 for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
419 *(reg_data + stringpos) = array[stringpos+BME280_DATA_INDEX];
424 /* \Brief: The function is used as SPI bus write
425 * \Return : Status of the SPI write
426 * \param dev_addr : The device address of the sensor
427 * \param reg_addr : Address of the first register, where data is to be written
428 * \param reg_data : It is a value hold in the array,
429 * will be used for write the value into the register
430 * \param cnt : The no of byte of data to be write
432 s8 BME280_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
434 s32 iError = BME280_INIT_VALUE;
435 u8 array[SPI_BUFFER_LEN * BME280_ADDRESS_INDEX];
436 u8 stringpos = BME280_INIT_VALUE;
437 u8 index = BME280_INIT_VALUE;
438 for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
439 /* the operation of (reg_addr++)&0x7F done as per the
440 SPI communication protocol specified in the data sheet*/
441 index = stringpos * BME280_ADDRESS_INDEX;
442 array[index] = (reg_addr++) & SPI_WRITE;
443 array[index + BME280_DATA_INDEX] = *(reg_data + stringpos);
445 /* Please take the below function as your reference
446 * for write the data using SPI communication
447 * add your SPI write function here.
448 * "IERROR = SPI_WRITE_STRING(ARRAY, CNT*2)"
449 * iError is an return value of SPI write function
450 * Please select your valid return value
451 * In the driver SUCCESS defined as 0
452 * and FAILURE defined as -1
457 /* Brief : The delay routine
458 * \param : delay in ms
460 void BME280_delay_msek(u32 msek)
462 /*Here you can write your own delay routine*/