切换到宽版
爱科技/爱创意/爱折腾;电子/数码爱好者的家!欢迎访问新版数码之家网站
  • 8201阅读
  • 28回复

[ARM]搞搞BMP280气压传感器 [复制链接]

上一主题 下一主题
离线飞向狙沙
 

发帖
13086
M币
7840
专家
48
粉丝
10363
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2018-09-21
大字报:BMP280只有气压和温度测量,BME280支持气压、温度、湿度测量,淘宝买的模块都是BMP,但给的手册是BME,显示支持湿度,被坑了一波,还纳闷咋读不出来湿度。百度也是坑爹,想下个BMP的手册找半天都搞不定,博世官网也找不到,还是谷歌要脸,第一条就是官网提供的pdf。


这两天在测试stm32的硬件I2C,正好有个气压模块,接口支持I2C和SPI,就玩玩I2C。
软硬件环境:
       Keil5,stm32f103cbt6,硬件I2C2,stm32cubemx,HAL库。
相关设置:
      串口1 ,波特率115200
       因为主要是测试硬件I2C,所以这里就不再详细描述I2C的实现细节,直接贴代码,代码中加了不少注释,就不做过多描述了,在这里给广大如我一般的菜鸟提个建议,一定要学会看E文手册,因为光大网友贴教程贴文章时都会有意无意漏掉一些自己觉着不重要的东西,可能就是这些东西让你走向失败。
       因为不打算写什么教程,所以简单扯几句完事,就当一个留档,以后再玩的时候可以直接拿来用
BMP280头文件
  1. #ifndef __BMP280_H
  2. #define __BMP280_H
  3. #include "stm32f1xx_hal.h"
  4. #include "i2c.h"
  5. /*****************************配置区****************************/
  6. //I2C超时
  7. #define TIMEOUT 200
  8. #define ADDR 0xec
  9. //温度过采样
  10. #define osrs_t 1
  11. //湿度过采样
  12. #define osrs_h 1
  13. //压力过采样
  14. #define osrs_p 1
  15. //工作模式(1或2:被动模式,测量完毕进入休眠,需要再次测量时重新设置model=1)
  16. #define mode 3
  17. //主动模式时的转换间隔(4:0.5s)
  18. #define t_sb 4
  19. //滤波器(0:关闭)
  20. #define filter 0
  21. /*******************************配置区*****************************/
  22. //速率/滤波控制寄存器
  23. #define config t_sb<<5|filter<<2
  24. //测量控制寄存器
  25. #define ctrl_meas osrs_t<<5|osrs_p<<2|mode
  26. void BMP280Init(void);
  27. uint8_t BMP280CheckStatus(void);
  28. void BMP280ReadTrim(void);
  29. void BMP280StartMeasure(void);
  30. double BMP280CompensateP(int32_t adc_P);
  31. double BMP280ReadP(void);
  32. double BME280CompensateT(int32_t adc_T);
  33. double BMP280ReadT(void);
  34. double BMP280CompensateH(int32_t adc_H);
  35. double BMP280ReadH(void);
  36. #endif
BMP280 .c文件
  1. #include "stm32f1xx_hal.h"
  2. #include "i2c.h"
  3. #include "BMP280.h"
  4. uint16_t dig_T1;
  5. int16_t dig_T2;
  6. int16_t dig_T3;
  7. uint16_t dig_P1;
  8. int16_t dig_P2;
  9. int16_t dig_P3;
  10. int16_t dig_P4;
  11. int16_t dig_P5;
  12. int16_t dig_P6;
  13. int16_t dig_P7;
  14. int16_t dig_P8;
  15. int16_t dig_P9;
  16. int8_t  dig_H1;
  17. int16_t dig_H2;
  18. int8_t  dig_H3;
  19. int16_t dig_H4;
  20. int16_t dig_H5;
  21. int8_t  dig_H6;
  22. int32_t t_fine;
  23. void BMP280Init(void)
  24. {
  25.     uint8_t tData;
  26.     //软件复位
  27.     tData=0xb6;
  28.     HAL_I2C_Mem_Write(&hi2c2,ADDR,0xe0,1,&tData,1,TIMEOUT);
  29.     HAL_Delay(50);
  30.     
  31.     //id校验 0x58
  32.     //uint8_t id=0;
  33.     //HAL_I2C_Mem_Read(&hi2c2,ADDR,0xd0,1,&id,1,TIMEOUT);
  34.   
  35.     if(osrs_t!=0)
  36.     {
  37.         tData=osrs_h;
  38.         HAL_I2C_Mem_Write(&hi2c2,ADDR,0xf2,1,&tData,1,TIMEOUT);
  39.     }
  40.     
  41.     tData=ctrl_meas;
  42.     HAL_I2C_Mem_Write(&hi2c2,ADDR,0xf4,1,&tData,1,TIMEOUT);
  43.     
  44.     
  45.     if(mode==3)
  46.     {
  47.         tData=config;
  48.         HAL_I2C_Mem_Write(&hi2c2,ADDR,0xf5,1,&tData,1,TIMEOUT);
  49.     }
  50.     BMP280ReadTrim();
  51. }
  52. //检查设备转换状态(1:转换完毕,0:正在转换)
  53. uint8_t BMP280CheckStatus(void)
  54. {
  55.     uint8_t rData;
  56.     HAL_I2C_Mem_Read(&hi2c2,ADDR,0xf3,1,&rData,1,TIMEOUT);
  57.     return (rData&0x40)?0:1;
  58. }
  59. //读取校准值
  60. void BMP280ReadTrim(void)
  61. {
  62.     uint8_t rData[24];
  63.         HAL_I2C_Mem_Read(&hi2c2,ADDR,0x88,1,rData,24,TIMEOUT);
  64.     dig_T1 = (rData[1] << 8) | rData[0];
  65.     dig_T2 = (rData[3] << 8) | rData[2];
  66.     dig_T3 = (rData[5] << 8) | rData[4];
  67.     dig_P1 = (rData[7] << 8) | rData[6];
  68.     dig_P2 = (rData[9] << 8) | rData[8];
  69.     dig_P3 = (rData[11]<< 8) | rData[10];
  70.     dig_P4 = (rData[13]<< 8) | rData[12];
  71.     dig_P5 = (rData[15]<< 8) | rData[14];
  72.     dig_P6 = (rData[17]<< 8) | rData[16];
  73.     dig_P7 = (rData[19]<< 8) | rData[18];
  74.     dig_P8 = (rData[21]<< 8) | rData[20];
  75.     dig_P9 = (rData[23]<< 8) | rData[22];
  76.     HAL_I2C_Mem_Read(&hi2c2,ADDR,0xa1,1,rData,1,TIMEOUT);
  77.         dig_H1=rData[0];
  78.         HAL_I2C_Mem_Read(&hi2c2,ADDR,0xe1,1,rData,7,TIMEOUT);
  79.   
  80.     dig_H2 = (rData[1]<< 8) | rData[0];
  81.     dig_H3 = rData[2];
  82.     dig_H4 = (rData[4]<< 4) | (0x0F & rData[3]);
  83.     dig_H5 = (rData[5] << 4) | ((rData[4] >> 4) & 0x0F);
  84.     dig_H6 = rData[6];  
  85. }
  86. void BMP280StartMeasure(void)
  87. {
  88.     uint8_t tData;
  89.     uint8_t rData;
  90.     if(mode==1||mode==2)
  91.     {
  92.         
  93.         if(osrs_t!=0)
  94.         {
  95.             HAL_I2C_Mem_Read(&hi2c2,ADDR,0xf2,1,&rData,1,TIMEOUT);
  96.             tData=osrs_h;
  97.             HAL_I2C_Mem_Write(&hi2c2,ADDR,0xf2,1,&tData,1,TIMEOUT);
  98.             HAL_I2C_Mem_Read(&hi2c2,ADDR,0xf2,1,&rData,1,TIMEOUT);
  99.         }
  100.         tData=ctrl_meas;
  101.         HAL_I2C_Mem_Write(&hi2c2,ADDR,0xf4,1,&tData,1,TIMEOUT);
  102.         
  103.     }
  104. }
  105. //气压计算
  106. double BMP280CompensateP(int32_t adc_P)
  107. {
  108.     //浮点数计算
  109.     double var1, var2, p;
  110.     var1 = ((double)t_fine/2.0) - 64000.0;
  111.     var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
  112.     var2 = var2 + var1 * ((double)dig_P5) * 2.0;
  113.     var2 = (var2/4.0)+(((double)dig_P4) * 65536.0);
  114.     var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;
  115.     var1 = (1.0 + var1 / 32768.0)*((double)dig_P1);
  116.     if (var1 == 0.0)
  117.     {
  118.         return 0; // avoid exception caused by division by zero
  119.     }
  120.     p = 1048576.0 - (double)adc_P;
  121.     p = (p - (var2 / 4096.0)) * 6250.0 / var1;
  122.     var1 = ((double)dig_P9) * p * p / 2147483648.0;
  123.     var2 = p * ((double)dig_P8) / 32768.0;
  124.     p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;
  125.     return p;
  126. }
  127. //气压读取
  128. double BMP280ReadP(void)
  129. {
  130.     int32_t temp;
  131.     uint8_t rData[3];
  132.     while(!BMP280CheckStatus());
  133.     HAL_I2C_Mem_Read(&hi2c2,ADDR,0xf7,1,rData,3,TIMEOUT);
  134.     
  135.     temp=(rData[0] << 12) | (rData[1] << 4) | (rData[2] >> 4);
  136.     return BMP280CompensateP(temp);
  137. }
  138. //温度计算
  139. double BME280CompensateT(int32_t adc_T)
  140. {
  141.     double var1, var2, T;
  142.     var1 = (((double)adc_T)/16384.0 - ((double)dig_T1)/1024.0) * ((double)dig_T2);
  143.     var2 = ((((double)adc_T)/131072.0 - ((double)dig_T1)/8192.0) *
  144.     (((double)adc_T)/131072.0 - ((double) dig_T1)/8192.0)) * ((double)dig_T3);
  145.     t_fine = (int32_t)(var1 + var2);
  146.     T = (var1 + var2) / 5120.0;
  147.     return T;
  148. }
  149. //温度读取
  150. double BMP280ReadT(void)
  151. {
  152.     int32_t temp;
  153.     uint8_t rData[3];
  154.     while(!BMP280CheckStatus());
  155.     HAL_I2C_Mem_Read(&hi2c2,ADDR,0xfa,1,rData,3,TIMEOUT);
  156.     
  157.     temp=(rData[0] << 12) | (rData[1] << 4) | (rData[2] >> 4);
  158.     return BME280CompensateT(temp);
  159. }
  160. //湿度计算
  161. double BMP280CompensateH(int32_t adc_H)
  162. {
  163.     double var_H;
  164.     var_H = (((double)t_fine) - 76800.0);
  165.     var_H = (adc_H - (((double)dig_H4) * 64.0 + ((double)dig_H5) / 16384.0 * var_H)) *
  166.     (((double)dig_H2) / 65536.0 * (1.0 + ((double)dig_H6) / 67108864.0 * var_H *
  167.     (1.0 + ((double)dig_H3) / 67108864.0 * var_H)));
  168.     var_H = var_H * (1.0 - ((double)dig_H1) * var_H / 524288.0);
  169.     if (var_H > 100.0)
  170.     var_H = 100.0;
  171.     else if (var_H < 0.0)
  172.     var_H = 0.0;
  173.     return var_H;
  174. }
  175. //湿度读取
  176. double BMP280ReadH(void)
  177. {
  178.     int32_t temp;
  179.     uint8_t rData[2];
  180.     while(!BMP280CheckStatus());
  181.     HAL_I2C_Mem_Read(&hi2c2,ADDR,0xfd,1,rData,2,TIMEOUT);
  182.     
  183.     temp=(rData[0] << 8) |rData[1];
  184.     return BMP280CompensateH(temp);
  185. }
使用方法:先调用BMP280Init() 初始化,会设置相关寄存器.
每次使用结果前调用BMP280StartMeasure()执行一次测量任务(被动模式每次测量都要调用一下,主动模式会定时自动测量,不过函数有判断,直接调用就好)
BMP280ReadP()//读取并计算气压值

BMP280ReadT()//读取并计算温度值
BMP280ReadH()//读取并计算湿度值,BME280有效,BMP280无湿度测量功能。


本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共6条打赏M币+86专家+1
huaweiwx 专家 +1 - 2018-12-27
huaweiwx M币 +20 - 2018-12-27
沙漠臭屁虫 M币 +13 謝謝分享 2018-09-22
链接 M币 +13 謝謝分享 2018-09-21
newnet1234 M币 +20 謝謝分享 2018-09-21
yanxue11 M币 +20 優秀文章 2018-09-21
M币换购:大丈夫能屈能伸!数码之家22合一拆机工具(拆客必备系列)
 
离线飞向狙沙

发帖
13086
M币
7840
专家
48
粉丝
10363
只看该作者 1楼 发表于: 2018-09-21
主要是几个寄存器设置

//温度过采样,设置温度采样分辨率,长度3位,设置0表示不采样,即不使用温度传感器,1代表16bit,2代表17。。。5、6、7或8代表20位
#define osrs_t 1
//湿度过采样,同上
#define osrs_h 1
//压力过采样,同上
#define osrs_p 1
//工作模式(1或2:被动模式,测量完毕进入休眠,需要再次测量时重新设置mode=1,3:主动模式,通过下面t_sb设定时间后传感器会定时执行测量任务)
#define mode 3
//主动模式时的转换间隔(4:0.5s)
#define t_sb 4
//滤波器(0:关闭),这个滤波器主要是用来过滤环境原因造成的气压数据干扰,比如开关门。根据使用场景的不同推荐不同的值
//共3bit,
#define filter 0
//根据使用场景推荐的数值,低功耗手持设备,手持设备,气象监测,楼层、电梯等。


[ 此帖被飞向狙沙在2018-09-21 14:57重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
离线飞向狙沙

发帖
13086
M币
7840
专家
48
粉丝
10363
只看该作者 2楼 发表于: 2018-09-21
关闭过滤器


开启过滤器


串口接受到的数值,中午气压比早上低了不少

本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共11条打赏M币+146专家+1
沙漠臭屁虫 M币 +13 謝謝分享 2018-09-22
jsycwnw 专家 +1 謝謝分享 2018-09-22
jsycwnw M币 +13 謝謝分享 2018-09-22
weizaisifang M币 +13 謝謝分享 2018-09-22
数码家园 M币 +13 謝謝分享 2018-09-22
zzy_85569381 M币 +20 謝謝分享 2018-09-21
中心小学 M币 +20 謝謝分享 2018-09-21
链接 M币 +13 虽然我不懂 但看起来很厉害的样子 2018-09-21
ch104517745 M币 +13 認真發帖 2018-09-21
2545889167 M币 +20 不错,支持。好像我也买了个,堆灰 2018-09-21
12
离线flynihou

发帖
295
M币
2093
专家
1
粉丝
49
只看该作者 3楼 发表于: 2018-09-21
虽然看不懂,但这是开发的基础,点赞!
离线2545889167

发帖
13268
M币
21188
专家
302
粉丝
4763
只看该作者 4楼 发表于: 2018-09-21
不错,支持。好像我也买了个,堆灰
离线飞向狙沙

发帖
13086
M币
7840
专家
48
粉丝
10363
只看该作者 5楼 发表于: 2018-09-21
回 2545889167 的帖子
2545889167:不错,支持。好像我也买了个,堆灰 (2018-09-21 16:14) 回 2545889167 的帖子

我也是买了半年多了,话说好些东西都是买东西的时候看着便宜或者想玩就买了,买完可能半年一年的都不碰,然后就忘了
离线13591058

发帖
32
M币
13
专家
0
粉丝
17
只看该作者 6楼 发表于: 2018-09-21
记号一下,楼主写的不错。
离线pxhxkij

发帖
150
M币
109
专家
2
粉丝
8
只看该作者 7楼 发表于: 2018-09-22
虽然不会看,但是很羡慕会写程序的大神。顶
离线40560335

发帖
1059
M币
548
专家
1
粉丝
15
只看该作者 8楼 发表于: 2018-09-23
之前用BMP085,飘的很厉害,换算高度在正负2-4米不停的飘,不知道是不是电源纹波造成的?
离线飞向狙沙

发帖
13086
M币
7840
专家
48
粉丝
10363
只看该作者 9楼 发表于: 2018-09-25
回 40560335 的帖子
40560335:之前用BMP085,飘的很厉害,换算高度在正负2-4米不停的飘,不知道是不是电源纹波造成的? (2018-09-23 16:26) 回 40560335 的帖子

刚才看了下气压换算高度3米大概30多Pa,这个漂移确实太大了,可以研究下漂移的特性,选择个合适的滤波算法。这个280测试的时候漂移还算能接受,开了滤波器之后能好上不少。