BMP280_ATY.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /**
  2. * @file BMP280_ATY.c
  3. *
  4. * @param Project DEVICE_GENERAL_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2023 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief Familiar functions of BMP280 for all embedded device
  20. *
  21. * @version
  22. * - 1_01_220804 > ATY
  23. * -# Preliminary version, first Release
  24. ********************************************************************************
  25. */
  26. #ifndef __BMP280_ATY_C
  27. #define __BMP280_ATY_C
  28. #include "BMP280_ATY.h"
  29. /******************************* For user *************************************/
  30. /******************************************************************************/
  31. /**
  32. * @brief BMP280 read id
  33. * @return id number like 0x58, 0x88
  34. */
  35. uint8_t BMP280_ReadId(void)
  36. {
  37. uint8_t temp_uint8;
  38. I2C_ReadReg(BMP280_ADDRESS, BMP280_CHIPID_REG, &temp_uint8, 1);
  39. return temp_uint8;
  40. }
  41. /**
  42. * @brief BMP280 get status
  43. * @param status_flag the bit to get
  44. * @return 1 or 0 at bit status_flag
  45. */
  46. uint8_t BMP280_GetStatus(uint8_t status_flag)
  47. {
  48. uint8_t flag;
  49. I2C_ReadReg(BMP280_ADDRESS, BMP280_STATUS_REG, &flag, 1);
  50. // status_flag = BMP280_MEASURING || BMP280_IM_UPDATE
  51. // if(flag & status_flag) return 1;
  52. // else return 0;
  53. return flag & status_flag;
  54. }
  55. /**
  56. * @brief BMP280 set oversamp
  57. * @param config Oversample_Mode value
  58. */
  59. void BMP280_SetOversamp(BMP280_OVERSAMPLE_MODE* config)
  60. {
  61. uint8_t temp_uint8;
  62. temp_uint8 = ((config->T_Osample) << 5) |
  63. ((config->P_Osample) << 2) |
  64. ((config)->WORKMODE);
  65. I2C_WriteReg(BMP280_ADDRESS, BMP280_CTRLMEAS_REG, &temp_uint8, 1);
  66. }
  67. /**
  68. * @brief BMP280 set standby filter
  69. * @param config bmp280 config
  70. */
  71. void BMP280_SetStandbyFilter(BMP280_CONFIG* config)
  72. {
  73. uint8_t temp_uint8;
  74. temp_uint8 = ((config->T_SB) << 5) |
  75. ((config->FILTER_COEFFICIENT) << 2) |
  76. ((config->SPI_EN));
  77. I2C_WriteReg(BMP280_ADDRESS, BMP280_CONFIG_REG, &temp_uint8, 1);
  78. }
  79. BMP280_S32_t t_fine; // Use to calc compensation
  80. #ifdef BMP280_USE_FIXED_POINT_COMPENSATE
  81. /**
  82. * @brief BMP280 calculate temperature compensate for signed 32
  83. * @param adc_T temperature adc origin data
  84. * @return signed 32 value of temperature
  85. * @note Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC.
  86. * t_fine carries fine temperature as global value
  87. */
  88. BMP280_S32_t BM280_CompensateT(BMP280_S32_t adc_T)
  89. {
  90. BMP280_S32_t var1, var2, T;
  91. var1 = ((((adc_T >> 3) - ((BMP280_S32_t)bmp280Cc.T1 << 1))) * ((BMP280_S32_t)bmp280Cc.T2)) >> 11;
  92. var2 = (((((adc_T >> 4) - ((BMP280_S32_t)bmp280Cc.T1)) * ((adc_T >> 4) - ((BMP280_S32_t)bmp280Cc.T1))) >> 12) *
  93. ((BMP280_S32_t)bmp280Cc.T3)) >> 14;
  94. t_fine = var1 + var2;
  95. T = (t_fine * 5 + 128) >> 8;
  96. return T;
  97. }
  98. /**
  99. * @brief BMP280 calculate pressure compensate for unsigned 32
  100. * @param adc_P pressure adc origin data
  101. * @return unsigned 32 value of pressure
  102. * @note Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
  103. * Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
  104. */
  105. BMP280_U32_t BM280_CompensateP(BMP280_S32_t adc_P)
  106. {
  107. BMP280_S64_t var1, var2, p;
  108. var1 = ((BMP280_S64_t)t_fine) - 128000;
  109. var2 = var1 * var1 * (BMP280_S64_t)bmp280Cc.P6;
  110. var2 = var2 + ((var1 * (BMP280_S64_t)bmp280Cc.P5) << 17);
  111. var2 = var2 + (((BMP280_S64_t)bmp280Cc.P4) << 35);
  112. var1 = ((var1 * var1 * (BMP280_S64_t)bmp280Cc.P3) >> 8) + ((var1 * (BMP280_S64_t)bmp280Cc.P2) << 12);
  113. var1 = (((((BMP280_S64_t)1) << 47) + var1)) * ((BMP280_S64_t)bmp280Cc.P1) >> 33;
  114. if(var1 == 0)
  115. {
  116. return 0; // avoid exception caused by division by zero
  117. }
  118. p = 1048576 - adc_P;
  119. p = (((p << 31) - var2) * 3125) / var1;
  120. var1 = (((BMP280_S64_t)bmp280Cc.P9) * (p >> 13) * (p >> 13)) >> 25;
  121. var2 = (((BMP280_S64_t)bmp280Cc.P8) * p) >> 19;
  122. p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)bmp280Cc.P7) << 4);
  123. return (BMP280_U32_t)p;
  124. }
  125. /**
  126. * @brief BMP280 get temperature
  127. * @return temperature real value in int32
  128. */
  129. BMP280_S32_t BMP280_GetTemperature(void)
  130. {
  131. uint8_t xlsb, lsb, msb;
  132. long signed bit32;
  133. BMP280_S32_t temperature;
  134. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_XLSB_REG, &xlsb, 1);
  135. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_LSB_REG, &lsb, 1);
  136. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_MSB_REG, &msb, 1);
  137. // The value of a register forming a floating point number
  138. bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
  139. temperature = BM280_CompensateT(bit32);
  140. return temperature;
  141. }
  142. /**
  143. * @brief BMP280 get pressure
  144. * @return pressure real value in uint32
  145. */
  146. BMP280_U32_t BMP280_GetPressure(void)
  147. {
  148. uint8_t xlsb, lsb, msb;
  149. long signed bit32;
  150. BMP280_U32_t pressure;
  151. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_XLSB_REG, &xlsb, 1);
  152. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_LSB_REG, &lsb, 1);
  153. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_MSB_REG, &msb, 1);
  154. // The value of a register forming a floating point number
  155. bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
  156. pressure = BM280_CompensateP(bit32);
  157. return pressure;
  158. }
  159. #else
  160. /**
  161. * @brief BMP280 calculate temperature compensate for double
  162. * @param adc_T temperature adc origin data
  163. * @return double value of temperature
  164. * @note Returns temperature in DegC, double precision. Output value of "51.23" equals 51.23 DegC.
  165. * t_fine carries fine temperature as global value
  166. */
  167. double BM280_CompensateT(BMP280_S32_t adc_T)
  168. {
  169. double var1, var2, T;
  170. var1 = (((double)adc_T) / 16384.0 - ((double)bmp280Cc.T1) / 1024.0) * ((double)bmp280Cc.T2);
  171. var2 = ((((double)adc_T) / 131072.0 - ((double)bmp280Cc.T1) / 8192.0) *
  172. (((double)adc_T) / 131072.0 - ((double)bmp280Cc.T1) / 8192.0)) * ((double)bmp280Cc.T3);
  173. t_fine = (BMP280_S32_t)(var1 + var2);
  174. T = (var1 + var2) / 5120.0;
  175. return T;
  176. }
  177. /**
  178. * @brief BMP280 calculate pressure compensate for double
  179. * @param adc_P pressure adc origin data
  180. * @return double value of pressure
  181. * @note Returns pressure in Pa as double. Output value of "96386.2" equals 96386.2 Pa = 963.862 hPa
  182. */
  183. double BM280_CompensateP(BMP280_S32_t adc_P)
  184. {
  185. double var1, var2, p;
  186. var1 = ((double)t_fine / 2.0) - 64000.0;
  187. var2 = var1 * var1 * ((double)bmp280Cc.P6) / 32768.0;
  188. var2 = var2 + var1 * ((double)bmp280Cc.P5) * 2.0;
  189. var2 = (var2 / 4.0) + (((double)bmp280Cc.P4) * 65536.0);
  190. var1 = (((double)bmp280Cc.P3) * var1 * var1 / 524288.0 + ((double)bmp280Cc.P2) * var1) / 524288.0;
  191. var1 = (1.0 + var1 / 32768.0) * ((double)bmp280Cc.P1);
  192. if(var1 == 0.0)
  193. {
  194. return 0; // avoid exception caused by division by zero
  195. }
  196. p = 1048576.0 - (double)adc_P;
  197. p = (p - (var2 / 4096.0)) * 6250.0 / var1;
  198. var1 = ((double)bmp280Cc.P9) * p * p / 2147483648.0;
  199. var2 = p * ((double)bmp280Cc.P8) / 32768.0;
  200. p = p + (var1 + var2 + ((double)bmp280Cc.P7)) / 16.0;
  201. return p;
  202. }
  203. /**
  204. * @brief BMP280 get temperature
  205. * @return temperature real value in double
  206. */
  207. double BMP280_GetTemperature(void)
  208. {
  209. uint8_t xlsb, lsb, msb;
  210. long signed bit32;
  211. double temperature;
  212. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_XLSB_REG, &xlsb, 1);
  213. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_LSB_REG, &lsb, 1);
  214. I2C_ReadReg(BMP280_ADDRESS, BMP280_TEMPERATURE_MSB_REG, &msb, 1);
  215. // The value of a register forming a floating point number
  216. bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
  217. temperature = BM280_CompensateT(bit32);
  218. return temperature;
  219. }
  220. /**
  221. * @brief BMP280 get pressure
  222. * @return pressure real value in double
  223. */
  224. double BMP280_GetPressure(void)
  225. {
  226. uint8_t xlsb, lsb, msb;
  227. long signed bit32;
  228. double pressure;
  229. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_XLSB_REG, &xlsb, 1);
  230. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_LSB_REG, &lsb, 1);
  231. I2C_ReadReg(BMP280_ADDRESS, BMP280_PRESSURE_MSB_REG, &msb, 1);
  232. // The value of a register forming a floating point number
  233. bit32 = ((long)(msb << 12)) | ((long)(lsb << 4)) | (xlsb >> 4);
  234. pressure = BM280_CompensateP(bit32);
  235. return pressure;
  236. }
  237. #endif
  238. struct _BMP280_CC bmp280Cc = {0}; // Used to store the compensation parameters stored in the chip ROM
  239. /**
  240. * @brief BMP280 initialize
  241. */
  242. void BM280_Init(void)
  243. {
  244. uint8_t lsb, msb;
  245. // Correction value of the temperature
  246. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T1_LSB_REG, &lsb, 1);
  247. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T1_MSB_REG, &msb, 1);
  248. bmp280Cc.T1 = (((uint16_t)msb) << 8) + lsb;
  249. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T2_LSB_REG, &lsb, 1);
  250. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T2_MSB_REG, &msb, 1);
  251. bmp280Cc.T2 = (((uint16_t)msb) << 8) + lsb;
  252. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T3_LSB_REG, &lsb, 1);
  253. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_T3_MSB_REG, &msb, 1);
  254. bmp280Cc.T3 = (((uint16_t)msb) << 8) + lsb;
  255. // Correction value of the pressure
  256. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P1_LSB_REG, &lsb, 1);
  257. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P1_MSB_REG, &msb, 1);
  258. bmp280Cc.P1 = (((uint16_t)msb) << 8) + lsb;
  259. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P2_LSB_REG, &lsb, 1);
  260. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P2_MSB_REG, &msb, 1);
  261. bmp280Cc.P2 = (((uint16_t)msb) << 8) + lsb;
  262. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P3_LSB_REG, &lsb, 1);
  263. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P3_MSB_REG, &msb, 1);
  264. bmp280Cc.P3 = (((uint16_t)msb) << 8) + lsb;
  265. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P4_LSB_REG, &lsb, 1);
  266. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P4_MSB_REG, &msb, 1);
  267. bmp280Cc.P4 = (((uint16_t)msb) << 8) + lsb;
  268. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P5_LSB_REG, &lsb, 1);
  269. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P5_MSB_REG, &msb, 1);
  270. bmp280Cc.P5 = (((uint16_t)msb) << 8) + lsb;
  271. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P6_LSB_REG, &lsb, 1);
  272. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P6_MSB_REG, &msb, 1);
  273. bmp280Cc.P6 = (((uint16_t)msb) << 8) + lsb;
  274. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P7_LSB_REG, &lsb, 1);
  275. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P7_MSB_REG, &msb, 1);
  276. bmp280Cc.P7 = (((uint16_t)msb) << 8) + lsb;
  277. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P8_LSB_REG, &lsb, 1);
  278. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P8_MSB_REG, &msb, 1);
  279. bmp280Cc.P8 = (((uint16_t)msb) << 8) + lsb;
  280. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P9_LSB_REG, &lsb, 1);
  281. I2C_ReadReg(BMP280_ADDRESS, BMP280_DIG_P9_MSB_REG, &msb, 1);
  282. bmp280Cc.P9 = (((uint16_t)msb) << 8) + lsb;
  283. // Reset
  284. I2C_WriteReg(BMP280_ADDRESS, BMP280_RESET_REG, (uint8_t*)BMP280_RESET_VALUE, 1);
  285. BMP280_OVERSAMPLE_MODE BMP_OVERSAMPLE_MODEStructure;
  286. BMP_OVERSAMPLE_MODEStructure.P_Osample = BMP280_P_MODE_3;
  287. BMP_OVERSAMPLE_MODEStructure.T_Osample = BMP280_T_MODE_1;
  288. BMP_OVERSAMPLE_MODEStructure.WORKMODE = BMP280_NORMAL_MODE;
  289. BMP280_SetOversamp(&BMP_OVERSAMPLE_MODEStructure);
  290. BMP280_CONFIG BMP_CONFIGStructure;
  291. BMP_CONFIGStructure.T_SB = BMP280_T_SB1;
  292. BMP_CONFIGStructure.FILTER_COEFFICIENT = BMP280_FILTER_MODE_4;
  293. BMP_CONFIGStructure.SPI_EN = DISABLE;
  294. BMP280_SetStandbyFilter(&BMP_CONFIGStructure);
  295. }
  296. /**
  297. * @brief BMP280 check whether the device exists
  298. * @return errCode, 0: success, !0: error
  299. */
  300. uint8_t BMP280_InitAndCheck(void)
  301. {
  302. BM280_Init();
  303. DelayMs(50);
  304. uint8_t bmp280Id = 0;
  305. bmp280Id = BMP280_ReadId();
  306. #ifdef __DEBUG_BMP280_ATY
  307. printf("\r\nBMP280 ID: 0x%02X", bmp280Id);
  308. #endif /* __DEBUG_BMP280_ATY */
  309. // 0xD8 = 0x88 | 0x58
  310. if(bmp280Id & 0xD8 != 0xD8)
  311. return 1;
  312. DelayMs(200);
  313. return 0;
  314. }
  315. /**
  316. * @brief BMP280 read temperature and pressure
  317. * @param tp data group to save tp value
  318. * @return errCode, 0: success, !0: error
  319. */
  320. uint8_t BMP280_ReadTP(double* tp)
  321. {
  322. uint16_t errCount = 1000;
  323. for(uint8_t i = 0; i < errCount; i++)
  324. {
  325. if(BMP280_GetStatus(BMP280_MEASURING) == 0)
  326. break;
  327. if(i == errCount - 1)
  328. return 2;
  329. DelayMs(1);
  330. }
  331. for(uint8_t i = 0; i < errCount; i++)
  332. {
  333. if(BMP280_GetStatus(BMP280_IM_UPDATE) == 0)
  334. break;
  335. if(i == errCount - 1)
  336. return 3;
  337. DelayMs(1);
  338. }
  339. tp[0] = BMP280_GetTemperature();
  340. tp[1] = BMP280_GetPressure();
  341. return 0;
  342. }
  343. uint8_t bmp280InitFlag = 0;
  344. /**
  345. * @brief BMP280 get data flow path
  346. * @param tp data group to save tp value
  347. * @return errCode, 0: success, !0: error
  348. */
  349. uint8_t BMP280_TempPreGet(uint16_t* tp)
  350. {
  351. double bmp280Value[2];
  352. if(bmp280InitFlag == 0)
  353. {
  354. if(BMP280_InitAndCheck())
  355. {
  356. bmp280InitFlag = 2;
  357. }
  358. else
  359. {
  360. bmp280InitFlag = 1;
  361. }
  362. }
  363. if(bmp280InitFlag == 2)
  364. {
  365. #ifdef __DEBUG_BMP280_ATY
  366. printf("\r\nDevice wrong!");
  367. #endif /* __DEBUG_BMP280_ATY */
  368. return 0xFF;
  369. }
  370. else if(bmp280InitFlag == 1)
  371. {
  372. uint8_t errValue = 0;
  373. errValue = BMP280_ReadTP(bmp280Value);
  374. if(errValue == 0)
  375. {
  376. if(bmp280Value[1] != 0)
  377. {
  378. tp[0] = ((bmp280Value[0] * 1000) + 5) / 10;
  379. tp[1] = (((bmp280Value[1] - 90000) * 10) + 5) / 10;
  380. #ifdef __DEBUG_BMP280_ATY
  381. printf("\r\nTemperature %f C Pressure %f Pa", bmp280Value[0], bmp280Value[1]);
  382. #endif /* __DEBUG_BMP280_ATY */
  383. }
  384. else
  385. {
  386. #ifdef __DEBUG_BMP280_ATY
  387. printf("\r\nData get wrong!");
  388. #endif /* __DEBUG_AHT20_ATY */
  389. return 0xFD;
  390. }
  391. }
  392. else
  393. {
  394. #ifdef __DEBUG_BMP280_ATY
  395. printf("\r\nBMP280 timeout! Err: %d", errValue);
  396. #endif /* __DEBUG_BMP280_ATY */
  397. return 0xFE;
  398. }
  399. }
  400. return 0;
  401. }
  402. #endif /* __BMP280_ATY_C */
  403. /******************************** End Of File *********************************/