单片机-bmp280大气压强与温度传感器使用详解"

转载:

https://blog.csdn.net/sunshinebooming/article/details/79637822

最近实习中一个项目要用到多种传感器,其中就包括BMP280模块,但是发现网上有用的资料非常少,只好从头看datasheet,使用过程中也算积累了相关的知识,分享给大家。在这里也给各位一个建议,使用一个芯片之前最好还是多看看datasheet,写datasheet的人就是制造芯片的人,他们的操作手册比任何人都有权威性。废话不多说,开始正题:

目录

  • 单片机 BMP280大气压强与温度传感器使用详解

    • 目录

      • 模块引脚及相关参数
      • 相关寄存器说明
      • 数据处理基本过程
      • 测量的基本流程
      • STC8A8K64S4A12单片机程序(51单片机,STM32等改一下就行了)

模块引脚及相关参数

  • 本次使用的模块型号为GY-BM E/P 280,淘宝上到处可以买到,这是对德国博世公司的BMP280芯片的一个应用封装(实物图片和封装基本电路都放在下面)。采用的主控芯片为STC8A8K64S4A12单片机,所以写的代码都是最底层的,比较适合小白看(代码贴在后面)。
  • 引脚说明:
    Pin1:VCC(3.3V供电)
    Pin2:GND
    Pin3:SCL(I2C通信模式时钟信号)
    Pin4:SDA(I2C通信模式数据信号)
    Pin5:CSB(SPI通信模式下用到的引脚,本次没用到,可以悬空)
    Pin6:SDO(传感器地址控制位,接GND的时候I2C中器件地址为0xEC,接高电平为0xEC+ 1,本次接GND
  • 传感器测试范围:
    温度:-45℃~+85℃
    大气压强:0~20000hPa(百帕)
  • 测量主要模式:
    Sleep Mode:作电流达到uA级别,典型值为0.1uA,最大值为0.3uA,所有测量工作都停止。
    Normal Mode: 正常工作,相关工作间隔时间可以通过寄存器控制。
    Forced Mode:主控发起一次采集命令,传感器采集一次信号,然后进入Sleep Mode,等待下次唤起(本次没用到)。

相关寄存器说明

BMP280传感器内部所有寄存器及其地址如下图所示:

  • 测量控制寄存器(ctrl_meas)(0xF4):
    Bit7~Bit5:osrs_t[2:0] 控制温度采样模式,主要是采样数据的位数(位数越大,精度越高),具体配置如下(本次三位都配置为1,最大采样位数20Bit):

    Bit4~Bit2:osrs_p[2:0] 控制大气压强采样模式,主要是采样数据的位数(位数越大,精度越高),具体配置如下(本次三位都配置为1,最大采样位数20Bit):

    Bit1~Bit0:mode[1:0] 传感器工作模式控制,00为Sleep Mode,01/10为Forced Mode,11为 Normal Mode(本次配置为11)。
  • 配置寄存器(config)(0xF5):
    Bit7~Bit5:t_sb[2:0] 设置Normal Mode下的转换间隔时间,具体配置如下(本次配置为000,0.5ms转换一次)

    Bit4~Bit2:filter[2:0] 设置传感器接收外界信号时的,前端滤波电路的滤波系数的,我也没仔细研究,就设置了个000,有兴趣的童鞋可以自己研究一下,datasheet上说和稳定度有关,可以有效减少外界环境的干扰:

    Bit0:spi3w_en 与SPI模式有关,本次没用到,没设置。
  • 身份编号寄存器(id)(0xD0):
    寄存器内固定值为0x58,读取0xD0数据的时候,传感器返回0x58,代表身份辨认完毕。
  • 复位寄存器(reset)(0xE0):
    写入0xB6时,所有寄存器(除身份编号寄存器)数据全部清零。
  • 状态寄存器(status)(0xF3):
    具体定义如下,感兴趣的童鞋自己研究,本次没用到:

数据处理基本过程

该传感器是使用测量值和校准值(初始化中获得),通过公式计算得出的,相关公式在datasheet中已经贴出了,还给了样本数据(公式挺复杂的,建议先把公式抄到程序中,然后用样本数据传进去,测试一遍结果对不对,保证公式没抄错)。
数据处理中有个坑,请注意,就是读取补偿值数据的时候,下图的数据存储位是LSB/MSB,即数据是反过来存储的,低位字节在前,高位字节在后,所以处理数据的时候要注意,具体可以见我的代码中bmp280_MultipleReadTwo()函数:

公式的话,datasheet中也很模糊,就贴了一张自己代码中的,配合datasheet中的图片,凑合看吧:

long bmp280_GetValue(void)
{long adc_T;long adc_P;long var1, var2, t_fine, T, p;adc_T = bmp280_MultipleReadThree(BMP280_TEMP_ADDR);adc_P = bmp280_MultipleReadThree(BMP280_PRESS_ADDR);if(adc_P == 0){return 0;}//Temperaturevar1 = (((double)adc_T)/16384.0-((double)dig_T1)/1024.0)*((double)dig_T2);var2 = ((((double)adc_T)/131072.0-((double)dig_T1)/8192.0)*(((double)adc_T)/131072.0-((double)dig_T1)/8192.0))*((double)dig_T3);t_fine = (unsigned long)(var1+var2);T = (var1+var2)/5120.0;//Pressurevar1 = ((double)t_fine/2.0)-64000.0;var2 = var1*var1*((double)dig_P6)/32768.0;var2 = var2 +var1*((double)dig_P5)*2.0;var2 = (var2/4.0)+(((double)dig_P4)*65536.0);var1 = (((double)dig_P3)*var1*var1/524288.0+((double)dig_P2)*var1)/524288.0;var1 = (1.0+var1/32768.0)*((double)dig_P1);p = 1048576.0-(double)adc_P;p = (p-(var2/4096.0))*6250.0/var1;var1 = ((double)dig_P9)*p*p/2147483648.0;var2 = p*((double)dig_P8)/32768.0;p = p+(var1+var2+((double)dig_P7))/16.0;return p;
}

测量的基本流程

  • 初始化
    包括I2C初始化(和传感器通信用),串口初始化(和上位机通信用,查看数据),传感器初始化,两个通信协议就不说了,不会的童鞋可以先去看看相关教程,下面主要说说传感器初始化:

    1. 数据全部清零:写数据0xB6到地址0xE0;
    2. 读芯片ID:读地址0xD0;
    3. 设置测量控制寄存器:写数据0xFF到地址0xF4(测量数据位20Bit,Normal Mode);
    4. 设置配置寄存器:写数据0x00到地址0xF5(测量间隔时间0.5ms,滤波器我没仔细看,感兴趣童鞋自己研究);
    5. 读取补偿值数据
  • I2C循环读取传感器参数,代入公式计算获得结果,并且将结果通过串口输出到上位机。

STC8A8K64S4A12单片机程序(51单片机,STM32等改一下就行了)

注意串口通信引脚用的RXD:P3.0,TXD:P3.1(波特率9600,8位数据位,1位停止位,无奇偶校验位),I2C引脚用的SCL:P1.5,SDA:P1.4,芯片供电电源用的3.3V

#include "intrins.h"
#include "stc8.h"#define BMP280_ADDR         0xec
#define BMP280_TEMP_ADDR    0xfa
#define BMP280_PRESS_ADDR   0xf7unsigned short dig_T1;
short dig_T2;
short dig_T3;
unsigned short dig_P1;
short dig_P2;
short dig_P3;
short dig_P4;
short dig_P5;
short dig_P6;
short dig_P7;
short dig_P8;
short dig_P9;#define FOSC    11059200UL
#define BRT     (256 - FOSC / 9600 / 32)
bit Uart1_BusyFlag;
char bufferPtr;
char Uart1Buffer[16];void delay_ms(int x)
{unsigned char i, j;while(x-- > 0){i = 15;j = 90;do{while (--j);} while (--i);}
}void Uart1Int() interrupt 4 using 1
{if(TI){TI = 0;Uart1_BusyFlag = 0;}if(RI){RI = 0;Uart1Buffer[bufferPtr++] = SBUF;}
}void Uart1Init()
{SCON = 0x50;TMOD = 0x20;TL1 = BRT;TH1 = BRT;AUXR = 0x40;TR1 = 1;bufferPtr = 0;Uart1_BusyFlag = 0;
}void Uart1SendByte(char dat)
{while(Uart1_BusyFlag);Uart1_BusyFlag = 1;SBUF = dat;
}void Uart1SendStr(char *p)
{while(*p){Uart1SendByte(*p++);}
}void I2C_Wait()
{while(!(I2CMSST & 0x40));//Uart1SendStr("i2c wait...\r\n");I2CMSST &= ~0x40;
}void I2C_Start()
{I2CMSCR = 0x01;I2C_Wait();
}void I2C_SendData(char dat)
{I2CTXD = dat;I2CMSCR = 0x02;I2C_Wait();
}void I2C_RecvACK()
{I2CMSCR = 0x03;I2C_Wait();
}char I2C_RecvData()
{I2CMSCR = 0x04;I2C_Wait();return(I2CRXD);
}void I2C_SendACK()
{I2CMSST = 0x00;I2CMSCR = 0x05;I2C_Wait();
}void I2C_SendNAK()
{I2CMSST = 0x01;I2CMSCR = 0x05;I2C_Wait();
}void I2C_Stop()
{I2CMSCR = 0x06;I2C_Wait();
}void I2C_Init()
{P_SW2 = 0x80;I2CCFG = 0xe0;I2CMSST = 0x00;
}void printHex(unsigned char i)
{unsigned char j;for(j = 0;j < 8;j++){if(j == 4){Uart1SendByte(' ');}if(i & 0x80){Uart1SendByte('1');}else{Uart1SendByte('0');}i <<= 1;}Uart1SendByte(' ');
}unsigned char bmp280_ReadByte(unsigned char addr)
{unsigned char temp;I2C_Start();I2C_SendData(BMP280_ADDR);I2C_RecvACK();I2C_SendData(addr);I2C_RecvACK();I2C_Start();I2C_SendData(BMP280_ADDR + 1);I2C_RecvACK();temp = I2C_RecvData();I2C_SendNAK();I2C_Stop();return temp;
}void bmp280_WriteByte(unsigned char addr, unsigned char dat)
{I2C_Start();I2C_SendData(BMP280_ADDR);I2C_RecvACK();I2C_SendData(addr);I2C_RecvACK();I2C_SendData(dat);I2C_RecvACK();I2C_Stop();
}long bmp280_MultipleReadThree(unsigned char addr)
{unsigned char msb, lsb, xlsb;long temp = 0;msb = bmp280_ReadByte(addr);lsb = bmp280_ReadByte(addr + 1);xlsb = bmp280_ReadByte(addr + 2);temp = (long)(((unsigned long)msb << 12)|((unsigned long)lsb << 4)|((unsigned long)xlsb >> 4));return temp;
}short bmp280_MultipleReadTwo(unsigned char addr)
{unsigned char msb, lsb;short temp = 0;lsb = bmp280_ReadByte(addr);msb = bmp280_ReadByte(addr + 1);temp = (short)msb << 8;temp |= (short)lsb;return temp;
}void bmp280_Init(void)
{unsigned char temp = 0;//状态全部清零bmp280_WriteByte(0xe0, 0xb6);//读取ID的时候不知道为啥读不出来了,索性跳过去了
//  temp = bmp280_ReadByte(0xd0);
//  if(temp == 0x58)
//      Uart1SendStr("bmp280 id is right...\r\n");
//  else
//      Uart1SendStr("bmp280 id is error...\r\n");bmp280_WriteByte(0xf4, 0xff);bmp280_WriteByte(0xf5, 0x00);dig_T1 = bmp280_MultipleReadTwo(0x88);dig_T2 = bmp280_MultipleReadTwo(0x8A);dig_T3 = bmp280_MultipleReadTwo(0x8C);dig_P1 = bmp280_MultipleReadTwo(0x8E);dig_P2 = bmp280_MultipleReadTwo(0x90);dig_P3 = bmp280_MultipleReadTwo(0x92);dig_P4 = bmp280_MultipleReadTwo(0x94);dig_P5 = bmp280_MultipleReadTwo(0x96);dig_P6 = bmp280_MultipleReadTwo(0x98);dig_P7 = bmp280_MultipleReadTwo(0x9A);dig_P8 = bmp280_MultipleReadTwo(0x9C);dig_P9 = bmp280_MultipleReadTwo(0x9E);delay_ms(200);
}//  dig_T1 = 27504;
//  dig_T2 = 26435;
//  dig_T3 = -1000;
//  dig_P1 = 36477;
//  dig_P2 = -10685;
//  dig_P3 = 3024;
//  dig_P4 = 2855;
//  dig_P5 = 140;
//  dig_P6 = -7;
//  dig_P7 = 15500;
//  dig_P8 = -14600;
//  dig_P9 = 6000;
//  adc_T = 519888;
//  adc_P = 415148;long bmp280_GetValue(void)
{long adc_T;long adc_P;long var1, var2, t_fine, T, p;adc_T = bmp280_MultipleReadThree(BMP280_TEMP_ADDR);adc_P = bmp280_MultipleReadThree(BMP280_PRESS_ADDR);if(adc_P == 0){return 0;}//Temperaturevar1 = (((double)adc_T)/16384.0-((double)dig_T1)/1024.0)*((double)dig_T2);var2 = ((((double)adc_T)/131072.0-((double)dig_T1)/8192.0)*(((double)adc_T)/131072.0-((double)dig_T1)/8192.0))*((double)dig_T3);t_fine = (unsigned long)(var1+var2);T = (var1+var2)/5120.0;var1 = ((double)t_fine/2.0)-64000.0;var2 = var1*var1*((double)dig_P6)/32768.0;var2 = var2 +var1*((double)dig_P5)*2.0;var2 = (var2/4.0)+(((double)dig_P4)*65536.0);var1 = (((double)dig_P3)*var1*var1/524288.0+((double)dig_P2)*var1)/524288.0;var1 = (1.0+var1/32768.0)*((double)dig_P1);p = 1048576.0-(double)adc_P;p = (p-(var2/4096.0))*6250.0/var1;var1 = ((double)dig_P9)*p*p/2147483648.0;var2 = p*((double)dig_P8)/32768.0;p = p+(var1+var2+((double)dig_P7))/16.0;return p;
}void main()
{long temp;unsigned char u8;I2C_Init();Uart1Init();bmp280_Init();ES = 1;EA = 1;while(1){temp = bmp280_GetValue();Uart1SendStr("test : ");u8 = (temp >> 24) & 0xff;printHex(u8);u8 = (temp >> 16) & 0xff;printHex(u8);u8 = (temp >> 8) & 0xff;printHex(u8);u8 = (temp) & 0xff;printHex(u8);Uart1SendStr("\r\n\r\n\r\n");delay_ms(500);}
}

单片机-bmp280大气压强与温度传感器使用详解相关推荐

  1. 单片机 BMP280(GY-BM E/P 280模块)大气压强与温度传感器使用详解

    单片机 BMP280大气压强与温度传感器使用详解 最近实习中一个项目要用到多种传感器,其中就包括BMP280模块,但是发现网上有用的资料非常少,只好从头看datasheet,使用过程中也算积累了相关的 ...

  2. 基于STM32单片机的大气压强检测仪(Proteus仿真+程序)

    编号:15 基于STM32单片机的大气压强检测仪 功能描述: 本设计由STM32单片机+BMP180大气压强检测模块+1602液晶显示模块组成. 1.主控制器是STM32单片机 2.利用BMP180传 ...

  3. DS18B20温度传感器原理详解及例程代码、漏极开路

    [常用传感器]DS18B20温度传感器原理详解及例程代码_Z小旋的博客-CSDN博客_ds18b20温度传感器 传感器引脚及原理图 DS18B20传感器的引脚及封装图如下: DS18B20一共有三个引 ...

  4. c语言 定时器作用,单片机定时器的作用及使用方法详解

    单片机定时器的作用及使用方法详解 单片机定时器在单片机的功能是很重要的,它一般被用作定时功能,来做定时检测.定时响应和定时控制,并且可以产生毫秒宽的脉冲信号来驱动步进电机.计时和计数的最终功能是通过计 ...

  5. AT89C51单片机流水灯c语言程序及详解(扫盲教程)

    AT89C51单片机是我们学习单片机必学的一个单片机,也是单片机入门的教材,下面给大家展示一下流水灯的编写方法适合初学者 首先先在proteus画出仿真图,方便仿真程序 下面来编写程序,先来写入头函数 ...

  6. 51单片机串口通信发送以及接收代码详解1

    #include <reg51.h> //实验现象:单片接收电脑发送的字符串,并发回给PC端的代码.//函数声明 void uart_init(void); void uart_seng_ ...

  7. 51单片机串口通信发送以及接收代码详解2

    #include <reg51.h> //实验现象:在电脑端没按下发送的时候,单片一直给电脑发送aaa字符串: //实验现象:在电脑端按下发送的时候,结束字符串aaa的发送代码,执行单片接 ...

  8. 【连载】从单片机到操作系统⑥——FreeRTOS任务切换机制详解

    大家晚上好,我是杰杰,最近挺忙的,好久没有更新了,今天周末就吐血更新一下吧! 前言 FreeRTOS是一个是实时内核,任务是程序执行的最小单位,也是调度器处理的基本单位,移植了FreeRTOS,则避免 ...

  9. C51单片机LED显示二进制【核心代码详解】

    文章目录 前言 一.位运算--按位取反 二.代码部分 1.实例代码 2.对核心代码P2=~i 的解释 总结 前言 51单片机独立按键实现LED显示二进制[代码详解] --按位取反 --具体实现原理 提 ...

最新文章

  1. mnist深度学习入门
  2. C#中Hashtable表的应用
  3. 算法之道:形而之上谓之道
  4. 2009计算机统考真题,2009年计算机统考真题(完整版).PDF
  5. servlet的重定向错误
  6. WPF显示富文本emoji表情+文本(类似微信)
  7. jpa 实体映射视图_JPA教程:映射实体–第1部分
  8. 频谱知识图谱:面向未来频谱管理的智能引擎人工智能技术与咨询
  9. PHPCMS V9 按浏览次数排行调用文章
  10. vim查找关键字_vim常用命令及操作
  11. 自动挡轿车等红灯时,是挂D挡踩刹车好还是挂N挡好呢?
  12. 十大震撼谷歌地图卫星照
  13. python的ols_Python Statsmodels 统计包之 OLS 回归
  14. java面试之简述一下 Java 垃圾回收机制?
  15. 如何在电脑上录制qq语音
  16. idea 商业版 社区版_idea社区版和商业版的区别
  17. 第二人生的源码分析(2)第二人生的基本功能
  18. java 发送html格式邮件 样式混乱解决
  19. 【ESP32】arduino中的ESP32实时系统FreeRTOS使用教程(一)
  20. ISO26262标准概览

热门文章

  1. 写在2022的尾巴上
  2. RTC(run time clock)实时时钟
  3. 首发国产软硬件完美兼容STM32F407系列功能简介
  4. python语言表白超炫图形_经验分享 篇二:三分钟教你用Excel制作各种尺寸、底色的证件照...
  5. oracle数据库表数据误删除恢复
  6. 洛谷日报 2020年3月前索引
  7. 可以结束一个循环的关键字是python_python异常处理会使用到哪些关键字?
  8. c语言学生信息结构体录入文件,C语言—学生信息管理系统
  9. eclipes下载与配置中文(超详细2021年最新版)
  10. RK3288源码编译