| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- /**
- * @file BMP280_ATY.c
- *
- * @param Project DEVICE_GENERAL_ATY_LIB
- *
- * @author ATY
- *
- * @copyright
- * - Copyright 2017 - 2026 MZ-ATY
- * - This code follows:
- * - MZ-ATY Various Contents Joint Statement -
- * <a href="https://mengze.top/MZ-ATY_VCJS">
- * https://mengze.top/MZ-ATY_VCJS</a>
- * - CC 4.0 BY-NC-SA -
- * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
- * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
- * - Your use will be deemed to have accepted the terms of this statement.
- *
- * @brief functions of BMP280 for C platform
- *
- * @version
- * - 1_01_220804 > ATY
- * -# Preliminary version, first Release
- * - 1_02_231229 > ATY
- * -# add multy addr and channel
- ********************************************************************************
- */
- #ifndef __BMP280_ATY_C
- #define __BMP280_ATY_C
- #include "BMP280_ATY.h"
- /******************************* For user *************************************/
- /******************************************************************************/
- /**
- * @brief BMP280 read id
- * @param addr chip address
- * @param channel chip channel
- * @return id number like 0x58, 0x88
- */
- uint8_t BMP280_ReadId(uint8_t addr, uint8_t channel)
- {
- uint8_t temp_uint8;
- I2C_ReadReg(addr, BMP280_CHIPID_REG, &temp_uint8, 1, channel);
- return temp_uint8;
- }
- /**
- * @brief BMP280 get status
- * @param status_flag the bit to get
- * @param addr chip address
- * @param channel chip channel
- * @return 1 or 0 at bit status_flag
- */
- uint8_t BMP280_GetStatus(uint8_t status_flag, uint8_t addr, uint8_t channel)
- {
- uint8_t flag;
- I2C_ReadReg(addr, BMP280_STATUS_REG, &flag, 1, channel);
- // status_flag = BMP280_MEASURING || BMP280_IM_UPDATE
- // if(flag & status_flag) return 1;
- // else return 0;
- return flag & status_flag;
- }
- /**
- * @brief BMP280 set oversamp
- * @param config Oversample_Mode value
- * @param addr chip address
- * @param channel chip channel
- */
- void BMP280_SetOversamp(BMP280_OVERSAMPLE_MODE* config, uint8_t addr, uint8_t channel)
- {
- uint8_t temp_uint8;
- temp_uint8 = ((config->T_Osample) << 5) |
- ((config->P_Osample) << 2) |
- ((config)->WORKMODE);
- I2C_WriteReg(addr, BMP280_CTRLMEAS_REG, &temp_uint8, 1, channel);
- }
- /**
- * @brief BMP280 set standby filter
- * @param config bmp280 config
- * @param addr chip address
- * @param channel chip channel
- */
- void BMP280_SetStandbyFilter(BMP280_CONFIG* config, uint8_t addr, uint8_t channel)
- {
- uint8_t temp_uint8;
- temp_uint8 = ((config->T_SB) << 5) |
- ((config->FILTER_COEFFICIENT) << 2) |
- ((config->SPI_EN));
- I2C_WriteReg(addr, BMP280_CONFIG_REG, &temp_uint8, 1, channel);
- }
- BMP280_S32_t t_fine; // Use to calc compensation
- #ifdef BMP280_USE_FIXED_POINT_COMPENSATE
- /**
- * @brief BMP280 calculate temperature compensate for signed 32
- * @param adc_T temperature adc origin data
- * @return signed 32 value of temperature
- * @note Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC.
- * t_fine carries fine temperature as global value
- */
- BMP280_S32_t BM280_CompensateT(BMP280_S32_t adc_T)
- {
- BMP280_S32_t var1, var2, T;
- var1 = ((((adc_T >> 3) - ((BMP280_S32_t)bmp280Cc.T1 << 1))) * ((BMP280_S32_t)bmp280Cc.T2)) >> 11;
- var2 = (((((adc_T >> 4) - ((BMP280_S32_t)bmp280Cc.T1)) * ((adc_T >> 4) - ((BMP280_S32_t)bmp280Cc.T1))) >> 12) *
- ((BMP280_S32_t)bmp280Cc.T3)) >> 14;
- t_fine = var1 + var2;
- T = (t_fine * 5 + 128) >> 8;
- return T;
- }
- /**
- * @brief BMP280 calculate pressure compensate for unsigned 32
- * @param adc_P pressure adc origin data
- * @return unsigned 32 value of pressure
- * @note Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
- * Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
- */
- BMP280_U32_t BM280_CompensateP(BMP280_S32_t adc_P)
- {
- BMP280_S64_t var1, var2, p;
- var1 = ((BMP280_S64_t)t_fine) - 128000;
- var2 = var1 * var1 * (BMP280_S64_t)bmp280Cc.P6;
- var2 = var2 + ((var1 * (BMP280_S64_t)bmp280Cc.P5) << 17);
- var2 = var2 + (((BMP280_S64_t)bmp280Cc.P4) << 35);
- var1 = ((var1 * var1 * (BMP280_S64_t)bmp280Cc.P3) >> 8) + ((var1 * (BMP280_S64_t)bmp280Cc.P2) << 12);
- var1 = (((((BMP280_S64_t)1) << 47) + var1)) * ((BMP280_S64_t)bmp280Cc.P1) >> 33;
- if(var1 == 0)
- {
- return 0; // avoid exception caused by division by zero
- }
- p = 1048576 - adc_P;
- p = (((p << 31) - var2) * 3125) / var1;
- var1 = (((BMP280_S64_t)bmp280Cc.P9) * (p >> 13) * (p >> 13)) >> 25;
- var2 = (((BMP280_S64_t)bmp280Cc.P8) * p) >> 19;
- p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)bmp280Cc.P7) << 4);
- return (BMP280_U32_t)p;
- }
- /**
- * @brief BMP280 get temperature
- * @param addr chip address
- * @param channel chip channel
- * @return temperature real value in int32
- */
- BMP280_S32_t BMP280_GetTemperature(uint8_t addr, uint8_t channel)
- {
- uint8_t xlsb, lsb, msb;
- long signed bit32;
- BMP280_S32_t temperature;
- I2C_ReadReg(addr, BMP280_TEMPERATURE_XLSB_REG, &xlsb, 1, channel);
- I2C_ReadReg(addr, BMP280_TEMPERATURE_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_TEMPERATURE_MSB_REG, &msb, 1, channel);
- // The value of a register forming a floating point number
- bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
- temperature = BM280_CompensateT(bit32);
- return temperature;
- }
- /**
- * @brief BMP280 get pressure
- * @param addr chip address
- * @param channel chip channel
- * @return pressure real value in uint32
- */
- BMP280_U32_t BMP280_GetPressure(uint8_t addr, uint8_t channel)
- {
- uint8_t xlsb, lsb, msb;
- long signed bit32;
- BMP280_U32_t pressure;
- I2C_ReadReg(addr, BMP280_PRESSURE_XLSB_REG, &xlsb, 1);
- I2C_ReadReg(addr, BMP280_PRESSURE_LSB_REG, &lsb, 1);
- I2C_ReadReg(addr, BMP280_PRESSURE_MSB_REG, &msb, 1);
- // The value of a register forming a floating point number
- bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
- pressure = BM280_CompensateP(bit32);
- return pressure;
- }
- #else
- /**
- * @brief BMP280 calculate temperature compensate for double
- * @param adc_T temperature adc origin data
- * @return double value of temperature
- * @note Returns temperature in DegC, double precision. Output value of "51.23" equals 51.23 DegC.
- * t_fine carries fine temperature as global value
- */
- double BM280_CompensateT(BMP280_S32_t adc_T)
- {
- double var1, var2, T;
- var1 = (((double)adc_T) / 16384.0 - ((double)bmp280Cc.T1) / 1024.0) * ((double)bmp280Cc.T2);
- var2 = ((((double)adc_T) / 131072.0 - ((double)bmp280Cc.T1) / 8192.0) *
- (((double)adc_T) / 131072.0 - ((double)bmp280Cc.T1) / 8192.0)) * ((double)bmp280Cc.T3);
- t_fine = (BMP280_S32_t)(var1 + var2);
- T = (var1 + var2) / 5120.0;
- return T;
- }
- /**
- * @brief BMP280 calculate pressure compensate for double
- * @param adc_P pressure adc origin data
- * @return double value of pressure
- * @note Returns pressure in Pa as double. Output value of "96386.2" equals 96386.2 Pa = 963.862 hPa
- */
- double BM280_CompensateP(BMP280_S32_t adc_P)
- {
- double var1, var2, p;
- var1 = ((double)t_fine / 2.0) - 64000.0;
- var2 = var1 * var1 * ((double)bmp280Cc.P6) / 32768.0;
- var2 = var2 + var1 * ((double)bmp280Cc.P5) * 2.0;
- var2 = (var2 / 4.0) + (((double)bmp280Cc.P4) * 65536.0);
- var1 = (((double)bmp280Cc.P3) * var1 * var1 / 524288.0 + ((double)bmp280Cc.P2) * var1) / 524288.0;
- var1 = (1.0 + var1 / 32768.0) * ((double)bmp280Cc.P1);
- if(var1 == 0.0)
- {
- return 0; // avoid exception caused by division by zero
- }
- p = 1048576.0 - (double)adc_P;
- p = (p - (var2 / 4096.0)) * 6250.0 / var1;
- var1 = ((double)bmp280Cc.P9) * p * p / 2147483648.0;
- var2 = p * ((double)bmp280Cc.P8) / 32768.0;
- p = p + (var1 + var2 + ((double)bmp280Cc.P7)) / 16.0;
- return p;
- }
- /**
- * @brief BMP280 get temperature
- * @param addr chip address
- * @param channel chip channel
- * @return temperature real value in double
- */
- double BMP280_GetTemperature(uint8_t addr, uint8_t channel)
- {
- uint8_t xlsb, lsb, msb;
- long signed bit32;
- double temperature;
- I2C_ReadReg(addr, BMP280_TEMPERATURE_XLSB_REG, &xlsb, 1, channel);
- I2C_ReadReg(addr, BMP280_TEMPERATURE_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_TEMPERATURE_MSB_REG, &msb, 1, channel);
- // The value of a register forming a floating point number
- bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
- temperature = BM280_CompensateT(bit32);
- return temperature;
- }
- /**
- * @brief BMP280 get pressure
- * @param addr chip address
- * @param channel chip channel
- * @return pressure real value in double
- */
- double BMP280_GetPressure(uint8_t addr, uint8_t channel)
- {
- uint8_t xlsb, lsb, msb;
- long signed bit32;
- double pressure;
- I2C_ReadReg(addr, BMP280_PRESSURE_XLSB_REG, &xlsb, 1, channel);
- I2C_ReadReg(addr, BMP280_PRESSURE_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_PRESSURE_MSB_REG, &msb, 1, channel);
- // The value of a register forming a floating point number
- bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
- pressure = BM280_CompensateP(bit32);
- return pressure;
- }
- #endif
- struct _BMP280_CC bmp280Cc = {0}; // Used to store the compensation parameters stored in the chip ROM
- /**
- * @brief BMP280 initialize
- * @param addr chip address
- * @param channel chip channel
- */
- void BM280_Init(uint8_t addr, uint8_t channel)
- {
- uint8_t lsb, msb;
- // Correction value of the temperature
- I2C_ReadReg(addr, BMP280_DIG_T1_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_T1_MSB_REG, &msb, 1, channel);
- bmp280Cc.T1 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_T2_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_T2_MSB_REG, &msb, 1, channel);
- bmp280Cc.T2 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_T3_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_T3_MSB_REG, &msb, 1, channel);
- bmp280Cc.T3 = (((uint16_t)msb) << 8) + lsb;
- // Correction value of the pressure
- I2C_ReadReg(addr, BMP280_DIG_P1_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P1_MSB_REG, &msb, 1, channel);
- bmp280Cc.P1 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P2_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P2_MSB_REG, &msb, 1, channel);
- bmp280Cc.P2 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P3_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P3_MSB_REG, &msb, 1, channel);
- bmp280Cc.P3 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P4_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P4_MSB_REG, &msb, 1, channel);
- bmp280Cc.P4 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P5_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P5_MSB_REG, &msb, 1, channel);
- bmp280Cc.P5 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P6_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P6_MSB_REG, &msb, 1, channel);
- bmp280Cc.P6 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P7_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P7_MSB_REG, &msb, 1, channel);
- bmp280Cc.P7 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P8_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P8_MSB_REG, &msb, 1, channel);
- bmp280Cc.P8 = (((uint16_t)msb) << 8) + lsb;
- I2C_ReadReg(addr, BMP280_DIG_P9_LSB_REG, &lsb, 1, channel);
- I2C_ReadReg(addr, BMP280_DIG_P9_MSB_REG, &msb, 1, channel);
- bmp280Cc.P9 = (((uint16_t)msb) << 8) + lsb;
- // Reset
- I2C_WriteReg(addr, BMP280_RESET_REG, (uint8_t*)BMP280_RESET_VALUE, 1, channel);
- BMP280_OVERSAMPLE_MODE BMP_OVERSAMPLE_MODEStructure;
- BMP_OVERSAMPLE_MODEStructure.P_Osample = BMP280_P_MODE_3;
- BMP_OVERSAMPLE_MODEStructure.T_Osample = BMP280_T_MODE_1;
- BMP_OVERSAMPLE_MODEStructure.WORKMODE = BMP280_NORMAL_MODE;
- BMP280_SetOversamp(&BMP_OVERSAMPLE_MODEStructure, addr, channel);
- BMP280_CONFIG BMP_CONFIGStructure;
- BMP_CONFIGStructure.T_SB = BMP280_T_SB1;
- BMP_CONFIGStructure.FILTER_COEFFICIENT = BMP280_FILTER_MODE_4;
- BMP_CONFIGStructure.SPI_EN = DISABLE;
- BMP280_SetStandbyFilter(&BMP_CONFIGStructure, addr, channel);
- }
- /**
- * @brief BMP280 check whether the device exists
- * @param addr chip address
- * @param channel chip channel
- * @return errCode, 0: success, !0: error
- */
- uint8_t BMP280_InitAndCheck(uint8_t addr, uint8_t channel)
- {
- BM280_Init(addr, channel);
- DelayMs(50);
- uint8_t bmp280Id = 0;
- bmp280Id = BMP280_ReadId(addr, channel);
- #ifdef __DEBUG_BMP280_ATY
- printf("\r\nBMP280 ID: 0x%02X", bmp280Id);
- #endif /* __DEBUG_BMP280_ATY */
- // 0xD8 = 0x88 | 0x58
- if(bmp280Id & 0xD8 != 0xD8)
- return 1;
- DelayMs(200);
- return 0;
- }
- /**
- * @brief BMP280 read temperature and pressure
- * @param tp data group to save tp value
- * @param addr chip address
- * @param channel chip channel
- * @return errCode, 0: success, !0: error
- */
- uint8_t BMP280_ReadTP(double* tp, uint8_t addr, uint8_t channel)
- {
- uint16_t errCount = 1000;
- for(uint8_t i = 0; i < errCount; i++)
- {
- if(BMP280_GetStatus(BMP280_MEASURING, addr, channel) == 0)
- break;
- if(i == errCount - 1)
- return 2;
- DelayMs(1);
- }
- for(uint8_t i = 0; i < errCount; i++)
- {
- if(BMP280_GetStatus(BMP280_IM_UPDATE, addr, channel) == 0)
- break;
- if(i == errCount - 1)
- return 3;
- DelayMs(1);
- }
- tp[0] = BMP280_GetTemperature(addr, channel);
- tp[1] = BMP280_GetPressure(addr, channel);
- return 0;
- }
- uint8_t bmp280InitFlag = 0;
- /**
- * @brief BMP280 get data flow path
- * @param tp data group to save tp value
- * @param addr chip address
- * @param channel chip channel
- * @return errCode, 0: success, !0: error
- */
- uint8_t BMP280_TempPreGet(uint16_t* tp, uint8_t addr, uint8_t channel)
- {
- double bmp280Value[2];
- if(bmp280InitFlag == 0)
- {
- if(BMP280_InitAndCheck(addr, channel))
- {
- bmp280InitFlag = 2;
- }
- else
- {
- bmp280InitFlag = 1;
- }
- }
- if(bmp280InitFlag == 2)
- {
- #ifdef __DEBUG_BMP280_ATY
- printf("\r\nDevice wrong!");
- #endif /* __DEBUG_BMP280_ATY */
- return 0xFF;
- }
- else if(bmp280InitFlag == 1)
- {
- uint8_t errValue = 0;
- errValue = BMP280_ReadTP(bmp280Value, addr, channel);
- if(errValue == 0)
- {
- if(bmp280Value[1] != 0)
- {
- tp[0] = ((bmp280Value[0] * 1000) + 5) / 10;
- tp[1] = (((bmp280Value[1] - 90000) * 10) + 5) / 10;
- #ifdef __DEBUG_BMP280_ATY
- printf("\r\nTemperature %f C Pressure %f Pa", bmp280Value[0], bmp280Value[1]);
- #endif /* __DEBUG_BMP280_ATY */
- }
- else
- {
- #ifdef __DEBUG_BMP280_ATY
- printf("\r\nData get wrong!");
- #endif /* __DEBUG_AHT20_ATY */
- return 0xFD;
- }
- }
- else
- {
- #ifdef __DEBUG_BMP280_ATY
- printf("\r\nBMP280 timeout! Err: %d", errValue);
- #endif /* __DEBUG_BMP280_ATY */
- return 0xFE;
- }
- }
- return 0;
- }
- // todo: not tested
- #endif /* __BMP280_ATY_C */
- /******************************** End Of File *********************************/
|