Added a wait until the NVM copy was complete.

This commit is contained in:
Bosch Sensortec 2019-09-13 13:10:43 +02:00 committed by Kevin Goveas
parent 47596cdf7f
commit bdf4e573cb
7 changed files with 2800 additions and 2772 deletions

603
README.md
View File

@ -1,303 +1,300 @@
# BME280 sensor API # BME280 sensor API
## Introduction ## Introduction
This package contains the Bosch Sensortec's BME280 pressure sensor driver (sensor API) This package contains the Bosch Sensortec's BME280 pressure sensor driver (sensor API)
The sensor driver package includes bme280.c, bme280.h and bme280_defs.h files. The sensor driver package includes bme280.c, bme280.h and bme280_defs.h files.
## Version ## Version
File | Version | Date File | Version | Date
--------------|---------|------------ --------------|---------|------------
bme280.c | 3.3.6 | 08 Mar 2019 bme280.c | 3.3.7 | 26 Aug 2019
bme280.h | 3.3.6 | 08 Mar 2019 bme280.h | 3.3.7 | 26 Aug 2019
bme280_defs.h | 3.3.6 | 08 Mar 2019 bme280_defs.h | 3.3.7 | 26 Aug 2019
## Integration details ## Integration details
* Integrate bme280.h, bme280_defs.h and bme280.c file in to the project. * Integrate bme280.h, bme280_defs.h and bme280.c file in to the project.
* Include the bme280.h file in your code like below. * Include the bme280.h file in your code like below.
``` c ``` c
#include "bme280.h" #include "bme280.h"
``` ```
## File information ## File information
* bme280_defs.h : This header file has the constants, macros and datatype declarations. * bme280_defs.h : This header file has the constants, macros and datatype declarations.
* bme280.h : This header file contains the declarations of the sensor driver APIs. * bme280.h : This header file contains the declarations of the sensor driver APIs.
* bme280.c : This source file contains the definitions of the sensor driver APIs. * bme280.c : This source file contains the definitions of the sensor driver APIs.
## Supported sensor interfaces ## Supported sensor interfaces
* SPI 4-wire * SPI 4-wire
* I2C * I2C
SPI 3-wire is currently not supported in the API. SPI 3-wire is currently not supported in the API.
## Usage guide ## Usage guide
### Initializing the sensor ### Initializing the sensor
To initialize the sensor, user need to create a device structure. User can do this by To initialize the sensor, user need to create a device structure. User can do this by
creating an instance of the structure bme280_dev. After creating the device strcuture, user creating an instance of the structure bme280_dev. After creating the device strcuture, user
need to fill in the various parameters as shown below. need to fill in the various parameters as shown below.
#### Example for SPI 4-Wire #### Example for SPI 4-Wire
``` c ``` c
struct bme280_dev dev; struct bme280_dev dev;
int8_t rslt = BME280_OK; int8_t rslt = BME280_OK;
/* Sensor_0 interface over SPI with native chip select line */ /* Sensor_0 interface over SPI with native chip select line */
dev.dev_id = 0; dev.dev_id = 0;
dev.intf = BME280_SPI_INTF; dev.intf = BME280_SPI_INTF;
dev.read = user_spi_read; dev.read = user_spi_read;
dev.write = user_spi_write; dev.write = user_spi_write;
dev.delay_ms = user_delay_ms; dev.delay_ms = user_delay_ms;
rslt = bme280_init(&dev); rslt = bme280_init(&dev);
``` ```
#### Example for I2C #### Example for I2C
``` c ``` c
struct bme280_dev dev; struct bme280_dev dev;
int8_t rslt = BME280_OK; int8_t rslt = BME280_OK;
dev.dev_id = BME280_I2C_ADDR_PRIM; dev.dev_id = BME280_I2C_ADDR_PRIM;
dev.intf = BME280_I2C_INTF; dev.intf = BME280_I2C_INTF;
dev.read = user_i2c_read; dev.read = user_i2c_read;
dev.write = user_i2c_write; dev.write = user_i2c_write;
dev.delay_ms = user_delay_ms; dev.delay_ms = user_delay_ms;
rslt = bme280_init(&dev); rslt = bme280_init(&dev);
``` ```
Regarding compensation functions for temperature,pressure and humidity we have two implementations. Regarding compensation functions for temperature,pressure and humidity we have two implementations.
1) Double precision floating point version 1) Double precision floating point version
2) Integer version 2) Integer version
By default, integer version is used in the API. If the user needs the floating point version, the user has to uncomment BME280_FLOAT_ENABLE macro in bme280_defs.h file or add that to the compiler flags. By default, integer version is used in the API. If the user needs the floating point version, the user has to uncomment BME280_FLOAT_ENABLE macro in bme280_defs.h file or add that to the compiler flags.
In integer compensation functions, we also have below two implementations for pressure. In integer compensation functions, we also have below two implementations for pressure.
1) For 32 bit machine. 1) For 32 bit machine.
2) For 64 bit machine. 2) For 64 bit machine.
By default, 64 bit variant is used in the API. If the user wants 32 bit variant, the user can disable the By default, 64 bit variant is used in the API. If the user wants 32 bit variant, the user can disable the
macro BME280_64BIT_ENABLE in bme280_defs.h file. macro BME280_64BIT_ENABLE in bme280_defs.h file.
### Sensor data units ### Sensor data units
> The sensor data units depends on the following macros being enabled or not, > The sensor data units depends on the following macros being enabled or not,
> (in bme280_defs.h file or as compiler macros) > (in bme280_defs.h file or as compiler macros)
> * BME280_FLOAT_ENABLE > * BME280_FLOAT_ENABLE
> * BME280_64BIT_ENABLE > * BME280_64BIT_ENABLE
In case of the macro "BME280_FLOAT_ENABLE" enabled, In case of the macro "BME280_FLOAT_ENABLE" enabled,
The outputs are in double and the units are The outputs are in double and the units are
- °C for temperature - °C for temperature
- % relative humidity - % relative humidity
- Pascal for pressure - Pascal for pressure
In case if "BME280_FLOAT_ENABLE" is not enabled, then it is In case if "BME280_FLOAT_ENABLE" is not enabled, then it is
- int32_t for temperature with the units 100 * °C - int32_t for temperature with the units 100 * °C
- uint32_t for humidity with the units 1024 * % relative humidity - uint32_t for humidity with the units 1024 * % relative humidity
- uint32_t for pressure - uint32_t for pressure
If macro "BME280_64BIT_ENABLE" is enabled, which it is by default, the unit is 100 * Pascal If macro "BME280_64BIT_ENABLE" is enabled, which it is by default, the unit is 100 * Pascal
If this macro is disabled, Then the unit is in Pascal If this macro is disabled, Then the unit is in Pascal
### Stream sensor data ### Stream sensor data
#### Stream sensor data in forced mode #### Stream sensor data in forced mode
``` c ``` c
int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev)
{ {
int8_t rslt; int8_t rslt;
uint8_t settings_sel; uint8_t settings_sel;
struct bme280_data comp_data; struct bme280_data comp_data;
/* Recommended mode of operation: Indoor navigation */ /* Recommended mode of operation: Indoor navigation */
dev->settings.osr_h = BME280_OVERSAMPLING_1X; dev->settings.osr_h = BME280_OVERSAMPLING_1X;
dev->settings.osr_p = BME280_OVERSAMPLING_16X; dev->settings.osr_p = BME280_OVERSAMPLING_16X;
dev->settings.osr_t = BME280_OVERSAMPLING_2X; dev->settings.osr_t = BME280_OVERSAMPLING_2X;
dev->settings.filter = BME280_FILTER_COEFF_16; dev->settings.filter = BME280_FILTER_COEFF_16;
settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL; settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
rslt = bme280_set_sensor_settings(settings_sel, dev); rslt = bme280_set_sensor_settings(settings_sel, dev);
printf("Temperature, Pressure, Humidity\r\n"); printf("Temperature, Pressure, Humidity\r\n");
/* Continuously stream sensor data */ /* Continuously stream sensor data */
while (1) { while (1) {
rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev);
/* Wait for the measurement to complete and print data @25Hz */ /* Wait for the measurement to complete and print data @25Hz */
dev->delay_ms(40); dev->delay_ms(40);
rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
print_sensor_data(&comp_data); print_sensor_data(&comp_data);
} }
return rslt; return rslt;
} }
void print_sensor_data(struct bme280_data *comp_data) void print_sensor_data(struct bme280_data *comp_data)
{ {
#ifdef BME280_FLOAT_ENABLE #ifdef BME280_FLOAT_ENABLE
printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity);
#else #else
printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity);
#endif #endif
} }
``` ```
##### Stream sensor data in normal mode ##### Stream sensor data in normal mode
``` c ``` c
int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev) int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev)
{ {
int8_t rslt; int8_t rslt;
uint8_t settings_sel; uint8_t settings_sel;
struct bme280_data comp_data; struct bme280_data comp_data;
/* Recommended mode of operation: Indoor navigation */ /* Recommended mode of operation: Indoor navigation */
dev->settings.osr_h = BME280_OVERSAMPLING_1X; dev->settings.osr_h = BME280_OVERSAMPLING_1X;
dev->settings.osr_p = BME280_OVERSAMPLING_16X; dev->settings.osr_p = BME280_OVERSAMPLING_16X;
dev->settings.osr_t = BME280_OVERSAMPLING_2X; dev->settings.osr_t = BME280_OVERSAMPLING_2X;
dev->settings.filter = BME280_FILTER_COEFF_16; dev->settings.filter = BME280_FILTER_COEFF_16;
dev->settings.standby_time = BME280_STANDBY_TIME_62_5_MS; dev->settings.standby_time = BME280_STANDBY_TIME_62_5_MS;
settings_sel = BME280_OSR_PRESS_SEL; settings_sel = BME280_OSR_PRESS_SEL;
settings_sel |= BME280_OSR_TEMP_SEL; settings_sel |= BME280_OSR_TEMP_SEL;
settings_sel |= BME280_OSR_HUM_SEL; settings_sel |= BME280_OSR_HUM_SEL;
settings_sel |= BME280_STANDBY_SEL; settings_sel |= BME280_STANDBY_SEL;
settings_sel |= BME280_FILTER_SEL; settings_sel |= BME280_FILTER_SEL;
rslt = bme280_set_sensor_settings(settings_sel, dev); rslt = bme280_set_sensor_settings(settings_sel, dev);
rslt = bme280_set_sensor_mode(BME280_NORMAL_MODE, dev); rslt = bme280_set_sensor_mode(BME280_NORMAL_MODE, dev);
printf("Temperature, Pressure, Humidity\r\n"); printf("Temperature, Pressure, Humidity\r\n");
while (1) { while (1) {
/* Delay while the sensor completes a measurement */ /* Delay while the sensor completes a measurement */
dev->delay_ms(70); dev->delay_ms(70);
rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
print_sensor_data(&comp_data); print_sensor_data(&comp_data);
} }
return rslt; return rslt;
} }
void print_sensor_data(struct bme280_data *comp_data) void print_sensor_data(struct bme280_data *comp_data)
{ {
#ifdef BME280_FLOAT_ENABLE #ifdef BME280_FLOAT_ENABLE
printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity);
#else #else
printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity);
#endif #endif
} }
``` ```
### Templates for function pointers ### Templates for function pointers
``` c ``` c
void user_delay_ms(uint32_t period) void user_delay_ms(uint32_t period)
{ {
/* /*
* Return control or wait, * Return control or wait,
* for a period amount of milliseconds * for a period amount of milliseconds
*/ */
} }
int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{ {
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
/* /*
* The parameter dev_id can be used as a variable to select which Chip Select pin has * The parameter dev_id can be used as a variable to select which Chip Select pin has
* to be set low to activate the relevant device on the SPI bus * to be set low to activate the relevant device on the SPI bus
*/ */
/* /*
* Data on the bus should be like * Data on the bus should be like
* |----------------+---------------------+-------------| * |----------------+---------------------+-------------|
* | MOSI | MISO | Chip Select | * | MOSI | MISO | Chip Select |
* |----------------+---------------------|-------------| * |----------------+---------------------|-------------|
* | (don't care) | (don't care) | HIGH | * | (don't care) | (don't care) | HIGH |
* | (reg_addr) | (don't care) | LOW | * | (reg_addr) | (don't care) | LOW |
* | (don't care) | (reg_data[0]) | LOW | * | (don't care) | (reg_data[0]) | LOW |
* | (....) | (....) | LOW | * | (....) | (....) | LOW |
* | (don't care) | (reg_data[len - 1]) | LOW | * | (don't care) | (reg_data[len - 1]) | LOW |
* | (don't care) | (don't care) | HIGH | * | (don't care) | (don't care) | HIGH |
* |----------------+---------------------|-------------| * |----------------+---------------------|-------------|
*/ */
return rslt; return rslt;
} }
int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{ {
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
/* /*
* The parameter dev_id can be used as a variable to select which Chip Select pin has * The parameter dev_id can be used as a variable to select which Chip Select pin has
* to be set low to activate the relevant device on the SPI bus * to be set low to activate the relevant device on the SPI bus
*/ */
/* /*
* Data on the bus should be like * Data on the bus should be like
* |---------------------+--------------+-------------| * |---------------------+--------------+-------------|
* | MOSI | MISO | Chip Select | * | MOSI | MISO | Chip Select |
* |---------------------+--------------|-------------| * |---------------------+--------------|-------------|
* | (don't care) | (don't care) | HIGH | * | (don't care) | (don't care) | HIGH |
* | (reg_addr) | (don't care) | LOW | * | (reg_addr) | (don't care) | LOW |
* | (reg_data[0]) | (don't care) | LOW | * | (reg_data[0]) | (don't care) | LOW |
* | (....) | (....) | LOW | * | (....) | (....) | LOW |
* | (reg_data[len - 1]) | (don't care) | LOW | * | (reg_data[len - 1]) | (don't care) | LOW |
* | (don't care) | (don't care) | HIGH | * | (don't care) | (don't care) | HIGH |
* |---------------------+--------------|-------------| * |---------------------+--------------|-------------|
*/ */
return rslt; return rslt;
} }
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{ {
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
/* /*
* The parameter dev_id can be used as a variable to store the I2C address of the device * The parameter dev_id can be used as a variable to store the I2C address of the device
*/ */
/* /*
* Data on the bus should be like * Data on the bus should be like
* |------------+---------------------| * |------------+---------------------|
* | I2C action | Data | * | I2C action | Data |
* |------------+---------------------| * |------------+---------------------|
* | Start | - | * | Start | - |
* | Write | (reg_addr) | * | Write | (reg_addr) |
* | Stop | - | * | Stop | - |
* | Start | - | * | Start | - |
* | Read | (reg_data[0]) | * | Read | (reg_data[0]) |
* | Read | (....) | * | Read | (....) |
* | Read | (reg_data[len - 1]) | * | Read | (reg_data[len - 1]) |
* | Stop | - | * | Stop | - |
* |------------+---------------------| * |------------+---------------------|
*/ */
return rslt; return rslt;
} }
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{ {
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
/* /*
* The parameter dev_id can be used as a variable to store the I2C address of the device * The parameter dev_id can be used as a variable to store the I2C address of the device
*/ */
/* /*
* Data on the bus should be like * Data on the bus should be like
* |------------+----------------------| * |------------+---------------------|
* | I2C action | Data | * | I2C action | Data |
* |------------+----------------------| * |------------+---------------------|
* | Start | - | * | Start | - |
* | Write | (reg_addr) | * | Write | (reg_addr) |
* | Write | (reg_data[0]) | * | Write | (reg_data[0]) |
* | Write | (reg_addr + 1) | * | Write | (....) |
* | Write | (reg_data[1]) | * | Write | (reg_data[len - 1]) |
* | Write | (....) | * | Stop | - |
* | Write | (reg_addr + len - 1) | * |------------+---------------------|
* | Write | (reg_data[len - 1]) | */
* | Stop | - |
* |------------+----------------------| return rslt;
*/ }
return rslt; ```
}
## Copyright (C) 2016 - 2017 Bosch Sensortec GmbH
```
## Copyright (C) 2016 - 2017 Bosch Sensortec GmbH

2890
bme280.c

File diff suppressed because it is too large Load Diff

488
bme280.h
View File

@ -1,244 +1,244 @@
/** /**
* Copyright (C) 2018 - 2019 Bosch Sensortec GmbH * Copyright (C) 2018 - 2019 Bosch Sensortec GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* Neither the name of the copyright holder nor the names of the * Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY * OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS * ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
* *
* The information provided is believed to be accurate and reliable. * The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility * The copyright holder assumes no responsibility
* for the consequences of use * for the consequences of use
* of such information nor for any infringement of patents or * of such information nor for any infringement of patents or
* other rights of third parties which may result from its use. * other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or * No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder. * patent rights of the copyright holder.
* *
* @file bme280.h * @file bme280.h
* @date 08 Mar 2019 * @date 26 Aug 2019
* @version 3.3.6 * @version 3.3.7
* @brief * @brief
* *
*/ */
/*! @file bme280.h /*! @file bme280.h
* @brief Sensor driver for BME280 sensor * @brief Sensor driver for BME280 sensor
*/ */
/*! /*!
* @defgroup BME280 SENSOR API * @defgroup BME280 SENSOR API
*/ */
#ifndef BME280_H_ #ifndef BME280_H_
#define BME280_H_ #define BME280_H_
/*! CPP guard */ /*! CPP guard */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Header includes */ /* Header includes */
#include "bme280_defs.h" #include "bme280_defs.h"
/*! /*!
* @brief This API is the entry point. * @brief This API is the entry point.
* It reads the chip-id and calibration data from the sensor. * It reads the chip-id and calibration data from the sensor.
* *
* @param[in,out] dev : Structure instance of bme280_dev * @param[in,out] dev : Structure instance of bme280_dev
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_init(struct bme280_dev *dev); int8_t bme280_init(struct bme280_dev *dev);
/*! /*!
* @brief This API writes the given data to the register address * @brief This API writes the given data to the register address
* of the sensor. * of the sensor.
* *
* @param[in] reg_addr : Register address from where the data to be written. * @param[in] reg_addr : Register address from where the data to be written.
* @param[in] reg_data : Pointer to data buffer which is to be written * @param[in] reg_data : Pointer to data buffer which is to be written
* in the sensor. * in the sensor.
* @param[in] len : No of bytes of data to write.. * @param[in] len : No of bytes of data to write..
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bme280_dev *dev); int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bme280_dev *dev);
/*! /*!
* @brief This API reads the data from the given register address of the sensor. * @brief This API reads the data from the given register address of the sensor.
* *
* @param[in] reg_addr : Register address from where the data to be read * @param[in] reg_addr : Register address from where the data to be read
* @param[out] reg_data : Pointer to data buffer to store the read data. * @param[out] reg_data : Pointer to data buffer to store the read data.
* @param[in] len : No of bytes of data to be read. * @param[in] len : No of bytes of data to be read.
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct bme280_dev *dev); int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct bme280_dev *dev);
/*! /*!
* @brief This API sets the oversampling, filter and standby duration * @brief This API sets the oversampling, filter and standby duration
* (normal mode) settings in the sensor. * (normal mode) settings in the sensor.
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* @param[in] desired_settings : Variable used to select the settings which * @param[in] desired_settings : Variable used to select the settings which
* are to be set in the sensor. * are to be set in the sensor.
* *
* @note : Below are the macros to be used by the user for selecting the * @note : Below are the macros to be used by the user for selecting the
* desired settings. User can do OR operation of these macros for configuring * desired settings. User can do OR operation of these macros for configuring
* multiple settings. * multiple settings.
* *
* Macros | Functionality * Macros | Functionality
* -----------------------|---------------------------------------------- * -----------------------|----------------------------------------------
* BME280_OSR_PRESS_SEL | To set pressure oversampling. * BME280_OSR_PRESS_SEL | To set pressure oversampling.
* BME280_OSR_TEMP_SEL | To set temperature oversampling. * BME280_OSR_TEMP_SEL | To set temperature oversampling.
* BME280_OSR_HUM_SEL | To set humidity oversampling. * BME280_OSR_HUM_SEL | To set humidity oversampling.
* BME280_FILTER_SEL | To set filter setting. * BME280_FILTER_SEL | To set filter setting.
* BME280_STANDBY_SEL | To set standby duration setting. * BME280_STANDBY_SEL | To set standby duration setting.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
*/ */
int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev); int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev);
/*! /*!
* @brief This API gets the oversampling, filter and standby duration * @brief This API gets the oversampling, filter and standby duration
* (normal mode) settings from the sensor. * (normal mode) settings from the sensor.
* *
* @param[in,out] dev : Structure instance of bme280_dev. * @param[in,out] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
*/ */
int8_t bme280_get_sensor_settings(struct bme280_dev *dev); int8_t bme280_get_sensor_settings(struct bme280_dev *dev);
/*! /*!
* @brief This API sets the power mode of the sensor. * @brief This API sets the power mode of the sensor.
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* @param[in] sensor_mode : Variable which contains the power mode to be set. * @param[in] sensor_mode : Variable which contains the power mode to be set.
* *
* sensor_mode | Macros * sensor_mode | Macros
* ---------------------|------------------- * ---------------------|-------------------
* 0 | BME280_SLEEP_MODE * 0 | BME280_SLEEP_MODE
* 1 | BME280_FORCED_MODE * 1 | BME280_FORCED_MODE
* 3 | BME280_NORMAL_MODE * 3 | BME280_NORMAL_MODE
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev); int8_t bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev);
/*! /*!
* @brief This API gets the power mode of the sensor. * @brief This API gets the power mode of the sensor.
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* @param[out] sensor_mode : Pointer variable to store the power mode. * @param[out] sensor_mode : Pointer variable to store the power mode.
* *
* sensor_mode | Macros * sensor_mode | Macros
* ---------------------|------------------- * ---------------------|-------------------
* 0 | BME280_SLEEP_MODE * 0 | BME280_SLEEP_MODE
* 1 | BME280_FORCED_MODE * 1 | BME280_FORCED_MODE
* 3 | BME280_NORMAL_MODE * 3 | BME280_NORMAL_MODE
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev); int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev);
/*! /*!
* @brief This API performs the soft reset of the sensor. * @brief This API performs the soft reset of the sensor.
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
*/ */
int8_t bme280_soft_reset(const struct bme280_dev *dev); int8_t bme280_soft_reset(const struct bme280_dev *dev);
/*! /*!
* @brief This API reads the pressure, temperature and humidity data from the * @brief This API reads the pressure, temperature and humidity data from the
* sensor, compensates the data and store it in the bme280_data structure * sensor, compensates the data and store it in the bme280_data structure
* instance passed by the user. * instance passed by the user.
* *
* @param[in] sensor_comp : Variable which selects which data to be read from * @param[in] sensor_comp : Variable which selects which data to be read from
* the sensor. * the sensor.
* *
* sensor_comp | Macros * sensor_comp | Macros
* ------------|------------------- * ------------|-------------------
* 1 | BME280_PRESS * 1 | BME280_PRESS
* 2 | BME280_TEMP * 2 | BME280_TEMP
* 4 | BME280_HUM * 4 | BME280_HUM
* 7 | BME280_ALL * 7 | BME280_ALL
* *
* @param[out] comp_data : Structure instance of bme280_data. * @param[out] comp_data : Structure instance of bme280_data.
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev); int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev);
/*! /*!
* @brief This API is used to parse the pressure, temperature and * @brief This API is used to parse the pressure, temperature and
* humidity data and store it in the bme280_uncomp_data structure instance. * humidity data and store it in the bme280_uncomp_data structure instance.
* *
* @param[in] reg_data : Contains register data which needs to be parsed * @param[in] reg_data : Contains register data which needs to be parsed
* @param[out] uncomp_data : Contains the uncompensated pressure, temperature * @param[out] uncomp_data : Contains the uncompensated pressure, temperature
* and humidity data. * and humidity data.
*/ */
void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data); void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data);
/*! /*!
* @brief This API is used to compensate the pressure and/or * @brief This API is used to compensate the pressure and/or
* temperature and/or humidity data according to the component selected by the * temperature and/or humidity data according to the component selected by the
* user. * user.
* *
* @param[in] sensor_comp : Used to select pressure and/or temperature and/or * @param[in] sensor_comp : Used to select pressure and/or temperature and/or
* humidity. * humidity.
* @param[in] uncomp_data : Contains the uncompensated pressure, temperature and * @param[in] uncomp_data : Contains the uncompensated pressure, temperature and
* humidity data. * humidity data.
* @param[out] comp_data : Contains the compensated pressure and/or temperature * @param[out] comp_data : Contains the compensated pressure and/or temperature
* and/or humidity data. * and/or humidity data.
* @param[in] calib_data : Pointer to the calibration data structure. * @param[in] calib_data : Pointer to the calibration data structure.
* *
* @return Result of API execution status. * @return Result of API execution status.
* @retval zero -> Success / -ve value -> Error * @retval zero -> Success / -ve value -> Error
*/ */
int8_t bme280_compensate_data(uint8_t sensor_comp, int8_t bme280_compensate_data(uint8_t sensor_comp,
const struct bme280_uncomp_data *uncomp_data, const struct bme280_uncomp_data *uncomp_data,
struct bme280_data *comp_data, struct bme280_data *comp_data,
struct bme280_calib_data *calib_data); struct bme280_calib_data *calib_data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* End of CPP guard */ #endif /* End of CPP guard */
#endif /* BME280_H_ */ #endif /* BME280_H_ */
/** @}*/ /** @}*/

View File

@ -1,390 +1,395 @@
/** /**
* Copyright (C) 2018 - 2019 Bosch Sensortec GmbH * Copyright (C) 2018 - 2019 Bosch Sensortec GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* Neither the name of the copyright holder nor the names of the * Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY * OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS * ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
* *
* The information provided is believed to be accurate and reliable. * The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility * The copyright holder assumes no responsibility
* for the consequences of use * for the consequences of use
* of such information nor for any infringement of patents or * of such information nor for any infringement of patents or
* other rights of third parties which may result from its use. * other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or * No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder. * patent rights of the copyright holder.
* *
* @file bme280_defs.h * @file bme280_defs.h
* @date 08 Mar 2019 * @date 26 Aug 2019
* @version 3.3.6 * @version 3.3.7
* @brief * @brief
* *
*/ */
/*! @file bme280_defs.h /*! @file bme280_defs.h
* @brief Sensor driver for BME280 sensor * @brief Sensor driver for BME280 sensor
*/ */
/*! /*!
* @defgroup BME280 SENSOR API * @defgroup BME280 SENSOR API
* @brief * @brief
*/ */
#ifndef BME280_DEFS_H_ #ifndef BME280_DEFS_H_
#define BME280_DEFS_H_ #define BME280_DEFS_H_
/********************************************************/ /********************************************************/
/* header includes */ /* header includes */
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#else #else
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#endif #endif
/********************************************************/ /********************************************************/
/*! @name Common macros */ /*! @name Common macros */
/********************************************************/ /********************************************************/
#if !defined(UINT8_C) && !defined(INT8_C) #if !defined(UINT8_C) && !defined(INT8_C)
#define INT8_C(x) S8_C(x) #define INT8_C(x) S8_C(x)
#define UINT8_C(x) U8_C(x) #define UINT8_C(x) U8_C(x)
#endif #endif
#if !defined(UINT16_C) && !defined(INT16_C) #if !defined(UINT16_C) && !defined(INT16_C)
#define INT16_C(x) S16_C(x) #define INT16_C(x) S16_C(x)
#define UINT16_C(x) U16_C(x) #define UINT16_C(x) U16_C(x)
#endif #endif
#if !defined(INT32_C) && !defined(UINT32_C) #if !defined(INT32_C) && !defined(UINT32_C)
#define INT32_C(x) S32_C(x) #define INT32_C(x) S32_C(x)
#define UINT32_C(x) U32_C(x) #define UINT32_C(x) U32_C(x)
#endif #endif
#if !defined(INT64_C) && !defined(UINT64_C) #if !defined(INT64_C) && !defined(UINT64_C)
#define INT64_C(x) S64_C(x) #define INT64_C(x) S64_C(x)
#define UINT64_C(x) U64_C(x) #define UINT64_C(x) U64_C(x)
#endif #endif
/**@}*/ /**@}*/
/**\name C standard macros */ /**\name C standard macros */
#ifndef NULL #ifndef NULL
#ifdef __cplusplus #ifdef __cplusplus
#define NULL 0 #define NULL 0
#else #else
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#endif #endif
/********************************************************/ /********************************************************/
#ifndef BME280_FLOAT_ENABLE #ifndef BME280_FLOAT_ENABLE
/* #define BME280_FLOAT_ENABLE */ /* #define BME280_FLOAT_ENABLE */
#endif #endif
#ifndef BME280_FLOAT_ENABLE #ifndef BME280_FLOAT_ENABLE
#ifndef BME280_64BIT_ENABLE #ifndef BME280_64BIT_ENABLE
#define BME280_64BIT_ENABLE #define BME280_64BIT_ENABLE
#endif #endif
#endif #endif
#ifndef TRUE #ifndef TRUE
#define TRUE UINT8_C(1) #define TRUE UINT8_C(1)
#endif #endif
#ifndef FALSE #ifndef FALSE
#define FALSE UINT8_C(0) #define FALSE UINT8_C(0)
#endif #endif
/**\name I2C addresses */ /**\name I2C addresses */
#define BME280_I2C_ADDR_PRIM UINT8_C(0x76) #define BME280_I2C_ADDR_PRIM UINT8_C(0x76)
#define BME280_I2C_ADDR_SEC UINT8_C(0x77) #define BME280_I2C_ADDR_SEC UINT8_C(0x77)
/**\name BME280 chip identifier */ /**\name BME280 chip identifier */
#define BME280_CHIP_ID UINT8_C(0x60) #define BME280_CHIP_ID UINT8_C(0x60)
/**\name Register Address */ /**\name Register Address */
#define BME280_CHIP_ID_ADDR UINT8_C(0xD0) #define BME280_CHIP_ID_ADDR UINT8_C(0xD0)
#define BME280_RESET_ADDR UINT8_C(0xE0) #define BME280_RESET_ADDR UINT8_C(0xE0)
#define BME280_TEMP_PRESS_CALIB_DATA_ADDR UINT8_C(0x88) #define BME280_TEMP_PRESS_CALIB_DATA_ADDR UINT8_C(0x88)
#define BME280_HUMIDITY_CALIB_DATA_ADDR UINT8_C(0xE1) #define BME280_HUMIDITY_CALIB_DATA_ADDR UINT8_C(0xE1)
#define BME280_PWR_CTRL_ADDR UINT8_C(0xF4) #define BME280_PWR_CTRL_ADDR UINT8_C(0xF4)
#define BME280_CTRL_HUM_ADDR UINT8_C(0xF2) #define BME280_CTRL_HUM_ADDR UINT8_C(0xF2)
#define BME280_CTRL_MEAS_ADDR UINT8_C(0xF4) #define BME280_CTRL_MEAS_ADDR UINT8_C(0xF4)
#define BME280_CONFIG_ADDR UINT8_C(0xF5) #define BME280_CONFIG_ADDR UINT8_C(0xF5)
#define BME280_DATA_ADDR UINT8_C(0xF7) #define BME280_DATA_ADDR UINT8_C(0xF7)
/**\name API success code */ /**\name API success code */
#define BME280_OK INT8_C(0) #define BME280_OK INT8_C(0)
/**\name API error codes */ /**\name API error codes */
#define BME280_E_NULL_PTR INT8_C(-1) #define BME280_E_NULL_PTR INT8_C(-1)
#define BME280_E_DEV_NOT_FOUND INT8_C(-2) #define BME280_E_DEV_NOT_FOUND INT8_C(-2)
#define BME280_E_INVALID_LEN INT8_C(-3) #define BME280_E_INVALID_LEN INT8_C(-3)
#define BME280_E_COMM_FAIL INT8_C(-4) #define BME280_E_COMM_FAIL INT8_C(-4)
#define BME280_E_SLEEP_MODE_FAIL INT8_C(-5) #define BME280_E_SLEEP_MODE_FAIL INT8_C(-5)
#define BME280_E_NVM_COPY_FAILED INT8_C(-6)
/**\name API warning codes */
#define BME280_W_INVALID_OSR_MACRO INT8_C(1) /**\name API warning codes */
#define BME280_W_INVALID_OSR_MACRO INT8_C(1)
/**\name Macros related to size */
#define BME280_TEMP_PRESS_CALIB_DATA_LEN UINT8_C(26) /**\name Macros related to size */
#define BME280_HUMIDITY_CALIB_DATA_LEN UINT8_C(7) #define BME280_TEMP_PRESS_CALIB_DATA_LEN UINT8_C(26)
#define BME280_P_T_H_DATA_LEN UINT8_C(8) #define BME280_HUMIDITY_CALIB_DATA_LEN UINT8_C(7)
#define BME280_P_T_H_DATA_LEN UINT8_C(8)
/**\name Sensor power modes */
#define BME280_SLEEP_MODE UINT8_C(0x00) /**\name Sensor power modes */
#define BME280_FORCED_MODE UINT8_C(0x01) #define BME280_SLEEP_MODE UINT8_C(0x00)
#define BME280_NORMAL_MODE UINT8_C(0x03) #define BME280_FORCED_MODE UINT8_C(0x01)
#define BME280_NORMAL_MODE UINT8_C(0x03)
/**\name Macro to combine two 8 bit data's to form a 16 bit data */
#define BME280_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) /**\name Macro to combine two 8 bit data's to form a 16 bit data */
#define BME280_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb)
#define BME280_SET_BITS(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \ #define BME280_SET_BITS(reg_data, bitname, data) \
((data << bitname##_POS) & bitname##_MSK)) ((reg_data & ~(bitname##_MSK)) | \
#define BME280_SET_BITS_POS_0(reg_data, bitname, data) \ ((data << bitname##_POS) & bitname##_MSK))
((reg_data & ~(bitname##_MSK)) | \ #define BME280_SET_BITS_POS_0(reg_data, bitname, data) \
(data & bitname##_MSK)) ((reg_data & ~(bitname##_MSK)) | \
(data & bitname##_MSK))
#define BME280_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \
(bitname##_POS)) #define BME280_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \
#define BME280_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) (bitname##_POS))
#define BME280_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
/**\name Macros for bit masking */
#define BME280_SENSOR_MODE_MSK UINT8_C(0x03) /**\name Macros for bit masking */
#define BME280_SENSOR_MODE_POS UINT8_C(0x00) #define BME280_SENSOR_MODE_MSK UINT8_C(0x03)
#define BME280_SENSOR_MODE_POS UINT8_C(0x00)
#define BME280_CTRL_HUM_MSK UINT8_C(0x07)
#define BME280_CTRL_HUM_POS UINT8_C(0x00) #define BME280_CTRL_HUM_MSK UINT8_C(0x07)
#define BME280_CTRL_HUM_POS UINT8_C(0x00)
#define BME280_CTRL_PRESS_MSK UINT8_C(0x1C)
#define BME280_CTRL_PRESS_POS UINT8_C(0x02) #define BME280_CTRL_PRESS_MSK UINT8_C(0x1C)
#define BME280_CTRL_PRESS_POS UINT8_C(0x02)
#define BME280_CTRL_TEMP_MSK UINT8_C(0xE0)
#define BME280_CTRL_TEMP_POS UINT8_C(0x05) #define BME280_CTRL_TEMP_MSK UINT8_C(0xE0)
#define BME280_CTRL_TEMP_POS UINT8_C(0x05)
#define BME280_FILTER_MSK UINT8_C(0x1C)
#define BME280_FILTER_POS UINT8_C(0x02) #define BME280_FILTER_MSK UINT8_C(0x1C)
#define BME280_FILTER_POS UINT8_C(0x02)
#define BME280_STANDBY_MSK UINT8_C(0xE0)
#define BME280_STANDBY_POS UINT8_C(0x05) #define BME280_STANDBY_MSK UINT8_C(0xE0)
#define BME280_STANDBY_POS UINT8_C(0x05)
/**\name Sensor component selection macros
* These values are internal for API implementation. Don't relate this to /**\name Sensor component selection macros
* data sheet. * These values are internal for API implementation. Don't relate this to
*/ * data sheet.
#define BME280_PRESS UINT8_C(1) */
#define BME280_TEMP UINT8_C(1 << 1) #define BME280_PRESS UINT8_C(1)
#define BME280_HUM UINT8_C(1 << 2) #define BME280_TEMP UINT8_C(1 << 1)
#define BME280_ALL UINT8_C(0x07) #define BME280_HUM UINT8_C(1 << 2)
#define BME280_ALL UINT8_C(0x07)
/**\name Settings selection macros */
#define BME280_OSR_PRESS_SEL UINT8_C(1) /**\name Settings selection macros */
#define BME280_OSR_TEMP_SEL UINT8_C(1 << 1) #define BME280_OSR_PRESS_SEL UINT8_C(1)
#define BME280_OSR_HUM_SEL UINT8_C(1 << 2) #define BME280_OSR_TEMP_SEL UINT8_C(1 << 1)
#define BME280_FILTER_SEL UINT8_C(1 << 3) #define BME280_OSR_HUM_SEL UINT8_C(1 << 2)
#define BME280_STANDBY_SEL UINT8_C(1 << 4) #define BME280_FILTER_SEL UINT8_C(1 << 3)
#define BME280_ALL_SETTINGS_SEL UINT8_C(0x1F) #define BME280_STANDBY_SEL UINT8_C(1 << 4)
#define BME280_ALL_SETTINGS_SEL UINT8_C(0x1F)
/**\name Oversampling macros */
#define BME280_NO_OVERSAMPLING UINT8_C(0x00) /**\name Oversampling macros */
#define BME280_OVERSAMPLING_1X UINT8_C(0x01) #define BME280_NO_OVERSAMPLING UINT8_C(0x00)
#define BME280_OVERSAMPLING_2X UINT8_C(0x02) #define BME280_OVERSAMPLING_1X UINT8_C(0x01)
#define BME280_OVERSAMPLING_4X UINT8_C(0x03) #define BME280_OVERSAMPLING_2X UINT8_C(0x02)
#define BME280_OVERSAMPLING_8X UINT8_C(0x04) #define BME280_OVERSAMPLING_4X UINT8_C(0x03)
#define BME280_OVERSAMPLING_16X UINT8_C(0x05) #define BME280_OVERSAMPLING_8X UINT8_C(0x04)
#define BME280_OVERSAMPLING_16X UINT8_C(0x05)
/**\name Standby duration selection macros */
#define BME280_STANDBY_TIME_0_5_MS (0x00) /**\name Standby duration selection macros */
#define BME280_STANDBY_TIME_62_5_MS (0x01) #define BME280_STANDBY_TIME_0_5_MS (0x00)
#define BME280_STANDBY_TIME_125_MS (0x02) #define BME280_STANDBY_TIME_62_5_MS (0x01)
#define BME280_STANDBY_TIME_250_MS (0x03) #define BME280_STANDBY_TIME_125_MS (0x02)
#define BME280_STANDBY_TIME_500_MS (0x04) #define BME280_STANDBY_TIME_250_MS (0x03)
#define BME280_STANDBY_TIME_1000_MS (0x05) #define BME280_STANDBY_TIME_500_MS (0x04)
#define BME280_STANDBY_TIME_10_MS (0x06) #define BME280_STANDBY_TIME_1000_MS (0x05)
#define BME280_STANDBY_TIME_20_MS (0x07) #define BME280_STANDBY_TIME_10_MS (0x06)
#define BME280_STANDBY_TIME_20_MS (0x07)
/**\name Filter coefficient selection macros */
#define BME280_FILTER_COEFF_OFF (0x00) /**\name Filter coefficient selection macros */
#define BME280_FILTER_COEFF_2 (0x01) #define BME280_FILTER_COEFF_OFF (0x00)
#define BME280_FILTER_COEFF_4 (0x02) #define BME280_FILTER_COEFF_2 (0x01)
#define BME280_FILTER_COEFF_8 (0x03) #define BME280_FILTER_COEFF_4 (0x02)
#define BME280_FILTER_COEFF_16 (0x04) #define BME280_FILTER_COEFF_8 (0x03)
#define BME280_FILTER_COEFF_16 (0x04)
/*!
* @brief Interface selection Enums #define BME280_STATUS_REG_ADDR (0xF3)
*/ #define BME280_SOFT_RESET_COMMAND (0xB6)
enum bme280_intf { #define BME280_STATUS_IM_UPDATE (0x01)
/*! SPI interface */
BME280_SPI_INTF, /*!
* @brief Interface selection Enums
/*! I2C interface */ */
BME280_I2C_INTF enum bme280_intf {
}; /*! SPI interface */
BME280_SPI_INTF,
/*!
* @brief Type definitions /*! I2C interface */
*/ BME280_I2C_INTF
typedef int8_t (*bme280_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len); };
typedef void (*bme280_delay_fptr_t)(uint32_t period);
/*!
/*! * @brief Type definitions
* @brief Calibration data */
*/ typedef int8_t (*bme280_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
struct bme280_calib_data typedef void (*bme280_delay_fptr_t)(uint32_t period);
{
/** /*!
* @ Trim Variables * @brief Calibration data
*/ */
struct bme280_calib_data
/**@{*/ {
uint16_t dig_T1; /**
int16_t dig_T2; * @ Trim Variables
int16_t dig_T3; */
uint16_t dig_P1;
int16_t dig_P2; /**@{*/
int16_t dig_P3; uint16_t dig_T1;
int16_t dig_P4; int16_t dig_T2;
int16_t dig_P5; int16_t dig_T3;
int16_t dig_P6; uint16_t dig_P1;
int16_t dig_P7; int16_t dig_P2;
int16_t dig_P8; int16_t dig_P3;
int16_t dig_P9; int16_t dig_P4;
uint8_t dig_H1; int16_t dig_P5;
int16_t dig_H2; int16_t dig_P6;
uint8_t dig_H3; int16_t dig_P7;
int16_t dig_H4; int16_t dig_P8;
int16_t dig_H5; int16_t dig_P9;
int8_t dig_H6; uint8_t dig_H1;
int32_t t_fine; int16_t dig_H2;
uint8_t dig_H3;
/**@}*/ int16_t dig_H4;
}; int16_t dig_H5;
int8_t dig_H6;
/*! int32_t t_fine;
* @brief bme280 sensor structure which comprises of temperature, pressure and
* humidity data /**@}*/
*/ };
#ifdef BME280_FLOAT_ENABLE
struct bme280_data /*!
{ * @brief bme280 sensor structure which comprises of temperature, pressure and
/*! Compensated pressure */ * humidity data
double pressure; */
#ifdef BME280_FLOAT_ENABLE
/*! Compensated temperature */ struct bme280_data
double temperature; {
/*! Compensated pressure */
/*! Compensated humidity */ double pressure;
double humidity;
}; /*! Compensated temperature */
#else double temperature;
struct bme280_data
{ /*! Compensated humidity */
/*! Compensated pressure */ double humidity;
uint32_t pressure; };
#else
/*! Compensated temperature */ struct bme280_data
int32_t temperature; {
/*! Compensated pressure */
/*! Compensated humidity */ uint32_t pressure;
uint32_t humidity;
}; /*! Compensated temperature */
#endif /* BME280_USE_FLOATING_POINT */ int32_t temperature;
/*! /*! Compensated humidity */
* @brief bme280 sensor structure which comprises of uncompensated temperature, uint32_t humidity;
* pressure and humidity data };
*/ #endif /* BME280_USE_FLOATING_POINT */
struct bme280_uncomp_data
{ /*!
/*! un-compensated pressure */ * @brief bme280 sensor structure which comprises of uncompensated temperature,
uint32_t pressure; * pressure and humidity data
*/
/*! un-compensated temperature */ struct bme280_uncomp_data
uint32_t temperature; {
/*! un-compensated pressure */
/*! un-compensated humidity */ uint32_t pressure;
uint32_t humidity;
}; /*! un-compensated temperature */
uint32_t temperature;
/*!
* @brief bme280 sensor settings structure which comprises of mode, /*! un-compensated humidity */
* oversampling and filter settings. uint32_t humidity;
*/ };
struct bme280_settings
{ /*!
/*! pressure oversampling */ * @brief bme280 sensor settings structure which comprises of mode,
uint8_t osr_p; * oversampling and filter settings.
*/
/*! temperature oversampling */ struct bme280_settings
uint8_t osr_t; {
/*! pressure oversampling */
/*! humidity oversampling */ uint8_t osr_p;
uint8_t osr_h;
/*! temperature oversampling */
/*! filter coefficient */ uint8_t osr_t;
uint8_t filter;
/*! humidity oversampling */
/*! standby time */ uint8_t osr_h;
uint8_t standby_time;
}; /*! filter coefficient */
uint8_t filter;
/*!
* @brief bme280 device structure /*! standby time */
*/ uint8_t standby_time;
struct bme280_dev };
{
/*! Chip Id */ /*!
uint8_t chip_id; * @brief bme280 device structure
*/
/*! Device Id */ struct bme280_dev
uint8_t dev_id; {
/*! Chip Id */
/*! SPI/I2C interface */ uint8_t chip_id;
enum bme280_intf intf;
/*! Device Id */
/*! Read function pointer */ uint8_t dev_id;
bme280_com_fptr_t read;
/*! SPI/I2C interface */
/*! Write function pointer */ enum bme280_intf intf;
bme280_com_fptr_t write;
/*! Read function pointer */
/*! Delay function pointer */ bme280_com_fptr_t read;
bme280_delay_fptr_t delay_ms;
/*! Write function pointer */
/*! Trim data */ bme280_com_fptr_t write;
struct bme280_calib_data calib_data;
/*! Delay function pointer */
/*! Sensor settings */ bme280_delay_fptr_t delay_ms;
struct bme280_settings settings;
}; /*! Trim data */
struct bme280_calib_data calib_data;
#endif /* BME280_DEFS_H_ */
/** @}*/ /*! Sensor settings */
/** @}*/ struct bme280_settings settings;
};
#endif /* BME280_DEFS_H_ */
/** @}*/
/** @}*/

View File

@ -1,161 +1,171 @@
/* /*
Linux userspace test code, simple and mose code directy from the doco. * Linux userspace test code, simple and mose code directy from the doco.
compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280 * compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280
tested: Raspberry Pi. * tested: Raspberry Pi.
Use like: ./bme280 /dev/i2c-0 * Use like: ./bme280 /dev/i2c-0
*/ */
#include "bme280.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <linux/i2c-dev.h> #ifdef __KERNEL__
#include <sys/ioctl.h> #include <linux/i2c-dev.h>
#include <sys/types.h> #include <sys/ioctl.h>
#include <fcntl.h> #endif
#include "bme280.h" #include <sys/types.h>
#include <fcntl.h>
int fd;
int fd;
int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{ int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
if (write(fd, &reg_addr, sizeof(reg_addr)) < sizeof(reg_addr)) void user_delay_ms(uint32_t period);
return BME280_E_COMM_FAIL; int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
if (read(fd, data, len) < len) void print_sensor_data(struct bme280_data *comp_data);
return BME280_E_COMM_FAIL; int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev);
return BME280_OK;
} int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
void user_delay_ms(uint32_t period) write(fd, &reg_addr, 1);
{ read(fd, data, len);
usleep(period * 1000);
} return 0;
}
int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{ void user_delay_ms(uint32_t period)
int8_t *buf; {
buf = malloc(len + 1); usleep(period * 1000);
buf[0] = reg_addr; }
memcpy(buf + 1, data, len);
if (write(fd, buf, len + 1) < len) int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
return BME280_E_COMM_FAIL; {
free(buf); int8_t *buf;
return BME280_OK;
} buf = malloc(len + 1);
buf[0] = reg_addr;
void print_sensor_data(struct bme280_data *comp_data) memcpy(buf + 1, data, len);
{ if (write(fd, buf, len + 1) < len)
float temp, press, hum; return BME280_E_COMM_FAIL;
#ifdef BME280_FLOAT_ENABLE free(buf);
temp = comp_data->temperature; return BME280_OK;
press = 0.01 * comp_data->pressure; }
hum = comp_data->humidity;
#else void print_sensor_data(struct bme280_data *comp_data)
#ifdef BME280_64BIT_ENABLE {
temp = 0.01f * comp_data->temperature; float temp, press, hum;
press = 0.0001f * comp_data->pressure; #ifdef BME280_FLOAT_ENABLE
hum = 1.0f / 1024.0f * comp_data->humidity; temp = comp_data->temperature;
#else press = 0.01 * comp_data->pressure;
temp = 0.01f * comp_data->temperature; hum = comp_data->humidity;
press = 0.01f * comp_data->pressure; #else
hum = 1.0f / 1024.0f * comp_data->humidity; #ifdef BME280_64BIT_ENABLE
#endif temp = 0.01f * comp_data->temperature;
#endif press = 0.0001f * comp_data->pressure;
printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum); hum = 1.0f / 1024.0f * comp_data->humidity;
} #else
temp = 0.01f * comp_data->temperature;
int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) press = 0.01f * comp_data->pressure;
{ hum = 1.0f / 1024.0f * comp_data->humidity;
int8_t rslt; #endif
uint8_t settings_sel; #endif
struct bme280_data comp_data; printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum);
}
/* Recommended mode of operation: Indoor navigation */
dev->settings.osr_h = BME280_OVERSAMPLING_1X; int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev)
dev->settings.osr_p = BME280_OVERSAMPLING_16X; {
dev->settings.osr_t = BME280_OVERSAMPLING_2X; int8_t rslt;
dev->settings.filter = BME280_FILTER_COEFF_16; uint8_t settings_sel;
struct bme280_data comp_data;
settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
/* Recommended mode of operation: Indoor navigation */
rslt = bme280_set_sensor_settings(settings_sel, dev); dev->settings.osr_h = BME280_OVERSAMPLING_1X;
if (rslt != BME280_OK) dev->settings.osr_p = BME280_OVERSAMPLING_16X;
{ dev->settings.osr_t = BME280_OVERSAMPLING_2X;
fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt); dev->settings.filter = BME280_FILTER_COEFF_16;
return rslt;
} settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
printf("Temperature, Pressure, Humidity\n"); rslt = bme280_set_sensor_settings(settings_sel, dev);
/* Continuously stream sensor data */ if (rslt != BME280_OK)
while (1) {
{ fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt);
rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); return rslt;
if (rslt != BME280_OK) }
{
fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt); printf("Temperature, Pressure, Humidity\n");
break; /* Continuously stream sensor data */
} while (1)
/* Wait for the measurement to complete and print data @25Hz */ {
dev->delay_ms(40); rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev);
rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); if (rslt != BME280_OK)
if (rslt != BME280_OK) {
{ fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt);
fprintf(stderr, "Failed to get sensor data (code %+d).", rslt); break;
break; }
} /* Wait for the measurement to complete and print data @25Hz */
print_sensor_data(&comp_data); dev->delay_ms(40);
} rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
return rslt; if (rslt != BME280_OK)
} {
fprintf(stderr, "Failed to get sensor data (code %+d).", rslt);
int main(int argc, char* argv[]) break;
{ }
struct bme280_dev dev; print_sensor_data(&comp_data);
int8_t rslt = BME280_OK; }
if (argc < 2) return rslt;
{ }
fprintf(stderr, "Missing argument for i2c bus.\n");
exit(1); int main(int argc, char* argv[])
} {
struct bme280_dev dev;
// make sure to select BME280_I2C_ADDR_PRIM int8_t rslt = BME280_OK;
// or BME280_I2C_ADDR_SEC as needed
dev.dev_id = if (argc < 2)
#if 1 {
BME280_I2C_ADDR_PRIM fprintf(stderr, "Missing argument for i2c bus.\n");
#else exit(1);
BME280_I2C_ADDR_SEC }
#endif
; // make sure to select BME280_I2C_ADDR_PRIM
// or BME280_I2C_ADDR_SEC as needed
dev.intf = BME280_I2C_INTF; dev.dev_id =
dev.read = user_i2c_read; #if 1
dev.write = user_i2c_write; BME280_I2C_ADDR_PRIM
dev.delay_ms = user_delay_ms; #else
BME280_I2C_ADDR_SEC
if ((fd = open(argv[1], O_RDWR)) < 0) #endif
{ ;
fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]);
exit(1); dev.intf = BME280_I2C_INTF;
} dev.read = user_i2c_read;
if (ioctl(fd, I2C_SLAVE, dev.dev_id) < 0) dev.write = user_i2c_write;
{ dev.delay_ms = user_delay_ms;
fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
exit(1); if ((fd = open(argv[1], O_RDWR)) < 0)
} {
fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]);
rslt = bme280_init(&dev); exit(1);
if (rslt != BME280_OK) }
{ #ifdef __KERNEL__
fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt); if (ioctl(fd, I2C_SLAVE, dev.dev_id) < 0)
exit(1); {
} fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
rslt = stream_sensor_data_forced_mode(&dev); exit(1);
if (rslt != BME280_OK) }
{ #endif
fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt);
exit(1); rslt = bme280_init(&dev);
} if (rslt != BME280_OK)
return 0; {
} fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt);
exit(1);
}
rslt = stream_sensor_data_forced_mode(&dev);
if (rslt != BME280_OK)
{
fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt);
exit(1);
}
return 0;
}

View File

@ -1,155 +1,155 @@
/**\mainpage /**\mainpage
* Copyright (C) 2018 - 2019 Bosch Sensortec GmbH * Copyright (C) 2018 - 2019 Bosch Sensortec GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* Neither the name of the copyright holder nor the names of the * Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY * OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS * ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
* *
* The information provided is believed to be accurate and reliable. * The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility * The copyright holder assumes no responsibility
* for the consequences of use * for the consequences of use
* of such information nor for any infringement of patents or * of such information nor for any infringement of patents or
* other rights of third parties which may result from its use. * other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or * No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder. * patent rights of the copyright holder.
* *
* File bme280_selftest.c * File bme280_selftest.c
* Date 08 Mar 2019 * Date 26 Aug 2019
* Version 3.3.6 * Version 3.3.7
* *
*/ */
#include "bme280_selftest.h" #include "bme280_selftest.h"
#define BME280_CRC_DATA_ADDR UINT8_C(0xE8) #define BME280_CRC_DATA_ADDR UINT8_C(0xE8)
#define BME280_CRC_DATA_LEN UINT8_C(1) #define BME280_CRC_DATA_LEN UINT8_C(1)
#define BME280_CRC_CALIB1_ADDR UINT8_C(0x88) #define BME280_CRC_CALIB1_ADDR UINT8_C(0x88)
#define BME280_CRC_CALIB1_LEN UINT8_C(26) #define BME280_CRC_CALIB1_LEN UINT8_C(26)
#define BME280_CRC_CALIB2_ADDR UINT8_C(0xE1) #define BME280_CRC_CALIB2_ADDR UINT8_C(0xE1)
#define BME280_CRC_CALIB2_LEN UINT8_C(7) #define BME280_CRC_CALIB2_LEN UINT8_C(7)
/*! /*!
* @brief This API calculates the CRC * @brief This API calculates the CRC
* *
* @param[in] mem_values : reg_data parameter to calculate CRC * @param[in] mem_values : reg_data parameter to calculate CRC
* @param[in] mem_length : Parameter to calculate CRC * @param[in] mem_length : Parameter to calculate CRC
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
static uint8_t crc_calculate(uint8_t *mem_values, uint8_t mem_length); static uint8_t crc_calculate(uint8_t *mem_values, uint8_t mem_length);
/*! /*!
* @brief This API reads the stored CRC and then compare with calculated CRC * @brief This API reads the stored CRC and then compare with calculated CRC
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> self test success / +ve value -> warning(self test fail) * @retval zero -> self test success / +ve value -> warning(self test fail)
*/ */
int8_t bme280_crc_selftest(const struct bme280_dev *dev) int8_t bme280_crc_selftest(const struct bme280_dev *dev)
{ {
int8_t rslt; int8_t rslt;
uint8_t reg_addr; uint8_t reg_addr;
uint8_t reg_data[64]; uint8_t reg_data[64];
uint8_t stored_crc = 0; uint8_t stored_crc = 0;
uint8_t calculated_crc = 0; uint8_t calculated_crc = 0;
/* Read stored crc value from register */ /* Read stored crc value from register */
reg_addr = BME280_CRC_DATA_ADDR; reg_addr = BME280_CRC_DATA_ADDR;
rslt = bme280_get_regs(reg_addr, reg_data, BME280_CRC_DATA_LEN, dev); rslt = bme280_get_regs(reg_addr, reg_data, BME280_CRC_DATA_LEN, dev);
if (rslt == BME280_OK) if (rslt == BME280_OK)
{ {
stored_crc = reg_data[0]; stored_crc = reg_data[0];
/* Calculated CRC value with calibration register */ /* Calculated CRC value with calibration register */
reg_addr = BME280_CRC_CALIB1_ADDR; reg_addr = BME280_CRC_CALIB1_ADDR;
rslt = bme280_get_regs(reg_addr, &reg_data[0], BME280_CRC_CALIB1_LEN, dev); rslt = bme280_get_regs(reg_addr, &reg_data[0], BME280_CRC_CALIB1_LEN, dev);
if (rslt == BME280_OK) if (rslt == BME280_OK)
{ {
reg_addr = BME280_CRC_CALIB2_ADDR; reg_addr = BME280_CRC_CALIB2_ADDR;
rslt = bme280_get_regs(reg_addr, &reg_data[BME280_CRC_CALIB1_LEN], BME280_CRC_CALIB2_LEN, dev); rslt = bme280_get_regs(reg_addr, &reg_data[BME280_CRC_CALIB1_LEN], BME280_CRC_CALIB2_LEN, dev);
if (rslt == BME280_OK) if (rslt == BME280_OK)
{ {
calculated_crc = crc_calculate(reg_data, BME280_CRC_CALIB1_LEN + BME280_CRC_CALIB2_LEN); calculated_crc = crc_calculate(reg_data, BME280_CRC_CALIB1_LEN + BME280_CRC_CALIB2_LEN);
/* Validate CRC */ /* Validate CRC */
if (stored_crc == calculated_crc) if (stored_crc == calculated_crc)
{ {
rslt = BME280_OK; rslt = BME280_OK;
} }
else else
{ {
rslt = BME280_W_SELF_TEST_FAIL; rslt = BME280_W_SELF_TEST_FAIL;
} }
} }
} }
} }
return rslt; return rslt;
} }
/*! /*!
* @brief This API calculates the CRC * @brief This API calculates the CRC
* *
* @param[in] mem_values : reg_data parameter to calculate CRC * @param[in] mem_values : reg_data parameter to calculate CRC
* @param[in] mem_length : Parameter to calculate CRC * @param[in] mem_length : Parameter to calculate CRC
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
static uint8_t crc_calculate(uint8_t *mem_values, uint8_t mem_length) static uint8_t crc_calculate(uint8_t *mem_values, uint8_t mem_length)
{ {
uint32_t crc_reg = 0xFF; uint32_t crc_reg = 0xFF;
uint8_t polynomial = 0x1D; uint8_t polynomial = 0x1D;
uint8_t bitNo, index; uint8_t bitNo, index;
uint8_t din = 0; uint8_t din = 0;
for (index = 0; index < mem_length; index++) for (index = 0; index < mem_length; index++)
{ {
for (bitNo = 0; bitNo < 8; bitNo++) for (bitNo = 0; bitNo < 8; bitNo++)
{ {
if (((crc_reg & 0x80) > 0) != ((mem_values[index] & 0x80) > 0)) if (((crc_reg & 0x80) > 0) != ((mem_values[index] & 0x80) > 0))
{ {
din = 1; din = 1;
} }
else else
{ {
din = 0; din = 0;
} }
/* Truncate 8th bit for crc_reg and mem_values */ /* Truncate 8th bit for crc_reg and mem_values */
crc_reg = (uint32_t)((crc_reg & 0x7F) << 1); crc_reg = (uint32_t)((crc_reg & 0x7F) << 1);
mem_values[index] = (uint8_t)((mem_values[index] & 0x7F) << 1); mem_values[index] = (uint8_t)((mem_values[index] & 0x7F) << 1);
crc_reg = (uint32_t)(crc_reg ^ (polynomial * din)); crc_reg = (uint32_t)(crc_reg ^ (polynomial * din));
} }
} }
return (uint8_t)(crc_reg ^ 0xFF); return (uint8_t)(crc_reg ^ 0xFF);
} }

View File

@ -1,82 +1,82 @@
/**\mainpage /**\mainpage
* Copyright (C) 2018 - 2019 Bosch Sensortec GmbH * Copyright (C) 2018 - 2019 Bosch Sensortec GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* Neither the name of the copyright holder nor the names of the * Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY * OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS * ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
* *
* The information provided is believed to be accurate and reliable. * The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility * The copyright holder assumes no responsibility
* for the consequences of use * for the consequences of use
* of such information nor for any infringement of patents or * of such information nor for any infringement of patents or
* other rights of third parties which may result from its use. * other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or * No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder. * patent rights of the copyright holder.
* *
* File bme280_selftest.h * File bme280_selftest.h
* Date 08 Mar 2019 * Date 26 Aug 2019
* Version 3.3.6 * Version 3.3.7
* *
*/ */
/*! /*!
* @addtogroup bme280_selftest * @addtogroup bme280_selftest
* @brief * @brief
*/ */
#ifndef BME280_SELFTEST_H_ #ifndef BME280_SELFTEST_H_
#define BME280_SELFTEST_H_ #define BME280_SELFTEST_H_
#include "bme280.h" #include "bme280.h"
/*! CPP guard */ /*! CPP guard */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**\name API warning code */ /**\name API warning code */
#define BME280_W_SELF_TEST_FAIL INT8_C(2) #define BME280_W_SELF_TEST_FAIL INT8_C(2)
/*! /*!
* @brief This API reads the stored CRC and then compare with calculated CRC * @brief This API reads the stored CRC and then compare with calculated CRC
* *
* @param[in] dev : Structure instance of bme280_dev. * @param[in] dev : Structure instance of bme280_dev.
* *
* @return Result of API execution status * @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/ */
int8_t bme280_crc_selftest(const struct bme280_dev *dev); int8_t bme280_crc_selftest(const struct bme280_dev *dev);
/*! CPP guard */ /*! CPP guard */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* BME280_SELFTEST_H_ */ #endif /* BME280_SELFTEST_H_ */
/** @}*/ /** @}*/