Last active
February 23, 2021 22:10
-
-
Save ggirjau/369d1520a21c7cf41413b00352446d61 to your computer and use it in GitHub Desktop.
BMP180 C library using STM32 I2C HAL driver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * bmp180.c | |
| * | |
| * Created on: 27 feb. 2019 | |
| * Author: gheorghe.ghirjev | |
| */ | |
| #include <string.h> | |
| #include <math.h> | |
| #include "bmp180.h" | |
| #include "stm32f7xx_hal.h" | |
| // global struct to store all BMP180 main data. | |
| bmp_t bmp; | |
| extern I2C_HandleTypeDef hi2c1; | |
| /*! | |
| * @brief: - Read and check bmp chip ID.This value is fixed to 0x55, | |
| * and can be used to check whether communication is functioning. | |
| * @param[in] - NONE. | |
| * @return - NO_ERR if chip_id is equal to 0x55, otherwise CHIP_ID_INVALID_ERR. | |
| */ | |
| static bmp_err_t read_chip_id (void) | |
| { | |
| uint8_t out_buff = 0; | |
| uint8_t ret_val = NO_ERR; | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_CHIP_ID_REG, 1, &out_buff, 1, BMP_I2C_TIMEOUT); | |
| if (BMP_CHIP_ID_VAL != out_buff) | |
| { | |
| ret_val = CHIP_ID_INVALID_ERR; | |
| } | |
| return ret_val; | |
| } | |
| /*! | |
| * @brief: - Write oversampling settings to the Control register. | |
| * @param[in] - struct of type oss_t | |
| * @param[in] - enum of type oss_ratio_t | |
| * @return - None | |
| */ | |
| static void set_oss (oss_t * oss, oss_ratio_t ratio) | |
| { | |
| uint8_t in_buff[2] = {0}; | |
| switch (ratio) | |
| { | |
| case ULTRA_LOW_PWR_MODE: | |
| { | |
| oss->wait_time = BMP_OSS0_CONV_TIME; | |
| break; | |
| } | |
| case STANDARD_MODE: | |
| { | |
| oss->wait_time = BMP_OSS1_CONV_TIME; | |
| break; | |
| } | |
| case HIGH: | |
| { | |
| oss->wait_time = BMP_OSS2_CONV_TIME; | |
| break; | |
| } | |
| case ULTRA_HIGH_RESOLUTION: | |
| { | |
| oss->wait_time = BMP_OSS3_CONV_TIME; | |
| break; | |
| } | |
| default: | |
| { | |
| oss->wait_time = BMP_OSS1_CONV_TIME; | |
| break; | |
| } | |
| } | |
| oss->ratio = ratio; | |
| BMP_SET_I2CRW_REG (in_buff[1], BMP_CTRL_OSS_MASK(ratio)); | |
| HAL_I2C_Mem_Write( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, in_buff, 2, BMP_I2C_TIMEOUT ); | |
| } | |
| /*! | |
| * @brief: - Read calibration BMP data. The E2PROM has stored 176 bit of individual calibration data. | |
| * This is used to compensate offset, temperature dependence and other parameters of the sensor. | |
| * @param[in] - struct of type bmp_calib_param_t | |
| * @return - NO_ERR if read calibration data are valid otherwise READ_CALIB_ERR. | |
| */ | |
| static bmp_err_t read_calib_data (short * calib_data) | |
| { | |
| bmp_err_t ret_val = NO_ERR; | |
| uint8_t out_buff[BMP_CALIB_DATA_SIZE] = {0}; | |
| uint8_t i = 0; | |
| uint8_t j = 1; | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_CALIB_ADDR, 1, out_buff, BMP_CALIB_DATA_SIZE, BMP_I2C_TIMEOUT); | |
| // Store read calib data to bmp_calib struct. | |
| for (i = 0; i <= BMP_CALIB_DATA_SIZE / 2; i++, j+2) | |
| { | |
| calib_data[i] = (out_buff[i * 2] << 8) | out_buff[j]; | |
| // checking that none of the words has the value 0 or 0xFFFF. | |
| if ((0 == calib_data[i]) | (-1 == calib_data[i])) | |
| { | |
| ret_val = GET_CALIB_ERR; | |
| } | |
| } | |
| return ret_val; | |
| } | |
| /*! | |
| * @brief: - Performe initial sequence of BMP sensor | |
| * @param[in] - pointer to struct of type bmp_calib_param_t | |
| * @return - None. | |
| */ | |
| void bmp_init (bmp_t * bmp) | |
| { | |
| memset(bmp, 0x00, sizeof(&bmp)); // clear bmp strut; | |
| bmp->err = read_chip_id (); // check chip validity and I2C communication. | |
| bmp->err = read_calib_data ((short *)&bmp->calib); | |
| set_oss (&bmp->oss, HIGH); // set oversampling settings | |
| } | |
| /*! | |
| * @brief: - Get uncompensated temperature value. UT = temperature data (16 bit) | |
| * @param[in] - None. | |
| * @return - uncompensated temp. | |
| */ | |
| int32_t get_ut (void) | |
| { | |
| uint8_t out_buff[2]; | |
| BMP_SET_I2CRW_REG (out_buff[0], BMP_SET_TEMP_CONV); | |
| HAL_I2C_Mem_Write( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, out_buff, 1, BMP_I2C_TIMEOUT ); | |
| HAL_Delay (BMP_TEMP_CONV_TIME); | |
| HAL_I2C_Mem_Read ( &hi2c1, BMP_READ_ADDR, BMP_DATA_MSB_ADDR, 1, out_buff, 2, BMP_I2C_TIMEOUT ); | |
| return (out_buff[0] << BYTE_SHIFT) | out_buff[1]; | |
| } | |
| /*! | |
| * @brief: - Calc true temperature. | |
| * @param[in] - pointer to struct of type bmp_t | |
| * @return - true temp. | |
| */ | |
| float get_temp(bmp_t * bmp) | |
| { | |
| int32_t X1 = 0; | |
| int32_t X2 = 0; | |
| float temp = 0; | |
| X1 = (((int32_t)bmp->uncomp.temp - bmp->calib.AC6) * bmp->calib.AC5) >> 15; | |
| X2 = (bmp->calib.MC << 11) / (X1 + bmp->calib.MD); | |
| bmp->data.B5 = X1 + X2; | |
| temp = ((bmp->data.B5 + 8) >> 4) * 0.1f; | |
| if ((temp <= BMP_MIN_TEMP_THRESHOLD) || (temp >= BMP_MAX_TEMP_THRESHOLD)) | |
| { | |
| bmp->err = GET_TEMP_ERR; | |
| } | |
| return temp; | |
| } | |
| /*! | |
| * @brief: - Get uncompensated pressure value. UP = pressure data (16 to 19 bit) | |
| * @param[in] - struct of type oss_t | |
| * @return - uncompensated pressure. | |
| */ | |
| int32_t get_up (oss_t oss) | |
| { | |
| uint8_t out_buff[3] = {0}; | |
| long up = 0; | |
| BMP_SET_I2CRW_REG (out_buff[0], BMP_SET_PRESS_CONV); | |
| HAL_I2C_Mem_Write ( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, out_buff, 1, BMP_I2C_TIMEOUT ); | |
| HAL_Delay (oss.wait_time); | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_DATA_MSB_ADDR, 1, out_buff, 3, BMP_I2C_TIMEOUT); | |
| up = ((out_buff[0] << SHORT_SHIFT) + (out_buff[1] << BYTE_SHIFT) + out_buff[2]) >> (8 - oss.ratio); | |
| return up; | |
| } | |
| /*! | |
| * @brief: - Calc true pressure. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure in Pa. | |
| */ | |
| int32_t get_pressure(bmp_t bmp) | |
| { | |
| int32_t X1, X2, X3, B3, B6, p = 0; | |
| uint32_t B4, B7 = 0; | |
| B6 = bmp.data.B5 - 4000; | |
| X1 = (bmp.calib.B2 * (B6 * B6 / 0x1000)) / 0x800; | |
| X2 = bmp.calib.AC2 * B6 / 0x800; | |
| X3 = X1 + X2; | |
| B3 = (((bmp.calib.AC1 * 4 + X3) << bmp.oss.ratio) +2) / 4; | |
| X1 = bmp.calib.AC3 * B6 / 0x2000; | |
| X2 = (bmp.calib.B1 * (B6 * B6 / 0x1000)) / 0x10000; | |
| X3 = ((X1 + X2) + 2) / 0x4; | |
| B4 = bmp.calib.AC4 * (unsigned long)(X3 + 32768) / 0x8000; | |
| B7 = ((unsigned long)bmp.uncomp.press - B3) * (50000 >> bmp.oss.ratio); | |
| if (B7 < 0x80000000) | |
| { | |
| p = (B7 * 2) / B4; | |
| } | |
| else | |
| { | |
| p = (B7 / B4) * 2; | |
| } | |
| X1 = (p / 0x100 * (p / 0x100)); | |
| X1 = (X1 * 3038) / 0x10000; | |
| X2 = (-7357 * p) / 0x10000; | |
| p = p + (X1 + X2 + 3791) / 0x10; | |
| return p; | |
| } | |
| /*! | |
| * @brief: - Calc true altitude. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure. | |
| */ | |
| float get_altitude (bmp_t * bmp) | |
| { | |
| float altitude = 0; | |
| altitude = BMP_PRESS_CONST_COEFICIENT * (1.0f - pow((bmp->data.press / BMP_PRESS_CONST_SEA_LEVEL), (1/5.255))); | |
| if ((altitude <= BMP_MIN_ALT_THRESHOLD) || (altitude >= BMP_MAX_ALT_THRESHOLD)) | |
| { | |
| bmp->err = GET_ALTITUDE_ERR; | |
| } | |
| return altitude; | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * bmp180.h | |
| * | |
| * Created on: 27 feb. 2019 | |
| * Author: gheorghe.ghirjev | |
| */ | |
| #ifndef BMP180_H_ | |
| #define BMP180_H_ | |
| #include "stdint.h" | |
| // Data type definitions: | |
| #define BYTE_SHIFT (8U) | |
| #define SHORT_SHIFT (16U) | |
| /* Chip-id [R/O] (register D0h): This value is fixed to 0x55, | |
| * and can be used to check whether communication is functioning. */ | |
| #define BMP_CHIP_ID_REG (0xD0) | |
| #define BMP_CHIP_ID_VAL (0x55) | |
| /* Measurement control [R/W] (register F4h): | |
| * <4:0> - Controls measurements. | |
| * <5> - SCO : Start of conversion. The value of this bit stays “1” during conversion, | |
| * and is reset to “0” after conversion is complete | |
| * <7:6> - OSS : Controls the oversampling ratio of the pressure measurement | |
| */ | |
| #define BMP_CTRL_REG (0xF4) | |
| #define BMP_CTRL_SCO_BIT(reg) ((reg & 0x20) >> 5) | |
| #define BMP_CTRL_OSS_MASK(oss) (oss = (oss & 0x3) << 6) | |
| #define BMP_OSS0_CONV_TIME (5U) | |
| #define BMP_OSS1_CONV_TIME (8U) | |
| #define BMP_OSS2_CONV_TIME (14U) | |
| #define BMP_OSS3_CONV_TIME (26U) | |
| /* Soft reset [W/O] (register E0h): | |
| * If set to 0xB6, will perform the same sequence as power on reset. */ | |
| #define BMP_SOFT_RST_REG (0xE0) | |
| #define BMP_SOFT_RST_VAL (0xB6) | |
| // Calibration data [R/O] (register AAh up to BFh): | |
| #define BMP_CALIB_ADDR (0xAA) | |
| #define BMP_CALIB_DATA_SIZE (22U) | |
| // Device I2C addr register [R/O]: write EEh, read EFh: | |
| #define BMP_READ_ADDR (0xEF) | |
| #define BMP_WRITE_ADDR (0xEE) | |
| #define BMP_I2C_TIMEOUT (50U) | |
| #define BMP_SET_I2CRW_REG(i2c_buff, reg) (i2c_buff = reg) | |
| // BMP measurmenet regs | |
| #define BMP_DATA_MSB_ADDR (0xF6) | |
| #define BMP_DATA_LSB_ADDR (0xF7) | |
| #define BMP_DATA_XLSB_ADDR (0xF8) | |
| // Temp. measurement : | |
| #define BMP_SET_TEMP_CONV (0x2E) | |
| #define BMP_TEMP_CONV_TIME (5U) | |
| #define BMP_MIN_TEMP_THRESHOLD (-40) | |
| #define BMP_MAX_TEMP_THRESHOLD (85U) | |
| // Pressure measurment : | |
| #define BMP_SET_PRESS_CONV (0x34) | |
| #define BMP_PRESS_CONST_SEA_LEVEL (101325.0f) // pressure in Pa | |
| #define BMP_PRESS_CONST_COEFICIENT (44330.0f) | |
| // Altitude measurment : | |
| #define BMP_MIN_ALT_THRESHOLD (-500) // m. relating to sea level) | |
| #define BMP_MAX_ALT_THRESHOLD (9000U) // m. relating to sea level) | |
| struct bmp_calib_param_t | |
| { | |
| int16_t AC1; | |
| int16_t AC2; | |
| int16_t AC3; | |
| uint16_t AC4; | |
| uint16_t AC5; | |
| uint16_t AC6; | |
| int16_t B1; | |
| int16_t B2; | |
| int16_t MB; | |
| int16_t MC; | |
| int16_t MD; | |
| }; | |
| struct measure_data_t | |
| { | |
| float temp; | |
| int32_t press; | |
| /* for uncompensated values do not use below fields: */ | |
| int32_t B5; | |
| float altitude; | |
| }; | |
| typedef enum | |
| { | |
| ULTRA_LOW_PWR_MODE = 0, | |
| STANDARD_MODE, | |
| HIGH, | |
| ULTRA_HIGH_RESOLUTION | |
| } oss_ratio_t; | |
| typedef struct | |
| { | |
| oss_ratio_t ratio; | |
| uint8_t wait_time; | |
| }oss_t; | |
| typedef enum | |
| { | |
| NO_ERR = 0, | |
| CHIP_ID_INVALID_ERR, | |
| GET_CALIB_ERR, | |
| GET_TEMP_ERR, | |
| GET_PRESSURE_ERR, | |
| GET_ALTITUDE_ERR | |
| } bmp_err_t; | |
| typedef struct | |
| { | |
| struct bmp_calib_param_t calib; | |
| struct measure_data_t uncomp; // uncompensated values | |
| struct measure_data_t data; | |
| oss_t oss; | |
| bmp_err_t err; | |
| }bmp_t; | |
| /*! | |
| * @brief: - Performe initial sequence of BMP180 sensor. | |
| * @param[in] - pointer to struct of type bmp_calib_param_t | |
| * @return - None. | |
| */ | |
| void bmp_init (bmp_t * bmp); | |
| /*! | |
| * @brief: - Read oversampling settings from CTRL reg F4h. | |
| * Oss (register F4h <7:6>): controls the oversampling ratio of the pressure measurement | |
| * (00b: single, 01b: 2 times, 10b: 4 times, 11b: 8 times). | |
| * @param[in] - None. | |
| * @return - None. | |
| */ | |
| static void set_oss (oss_t * oss, oss_ratio_t ratio); | |
| /*! | |
| * @brief: - Get uncompensated temperature value. | |
| * @param[in] - None. | |
| * @return - uncompensated temp. | |
| */ | |
| int32_t get_ut (void); | |
| /*! | |
| * @brief: - Calc true temperature. | |
| * @param[in] - pointer to struct of type bmp_t | |
| * @return - true temp. | |
| */ | |
| float get_temp(bmp_t * bmp); | |
| /*! | |
| * @brief: - Get uncompensated pressure value. | |
| * @param[in] - oss - conversion time. | |
| * @return - uncompensated pressure. | |
| */ | |
| int32_t get_up (oss_t oss); | |
| /*! | |
| * @brief: - Calc true pressure. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure in Pa. | |
| */ | |
| int32_t get_pressure(bmp_t bmp); | |
| /*! | |
| * @brief: - Calc true altitude. | |
| * @param[in] - struct of type bmp_t | |
| * @return - altitude in meters. | |
| */ | |
| float get_altitude (bmp_t * bmp); | |
| #endif /* BMP180_H_ */ |
Author
Hello
Sorry for missing "bmp_t bmp;" declaration in main.c file
Thanks @inflamerzt for helping with missing line. I've updated description comment !
Best Regards
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
you must add definition of "bmp" at main.c