气压传感器BMP180的简单应用

news2024/9/25 9:32:11

文章目录

  • 一、BMP180
    • 1.介绍
    • 2.主要特点:
    • 3. 典型应用:
    • 4. 原理图
    • 5. 典型应用电路
    • 6. 测量流程
    • 7. 工作模式
  • 二、软件
    • 1.初始化
    • 2.获取原始温度
    • 3.获取真实温度
    • 4.获取原始气压
    • 5.获取真实气压
    • 6.海拔高度的换算
  • 三、总结


一、BMP180

1.介绍

BMP180是一款高精度、小体积、超低能耗的压力传感器,可以应用在移动设备中。它的性能卓越,绝对精度最低可以达到0.03hPa,并且耗电极低,只有3μA。BMP180采用强大的8-pin陶瓷无引线芯片承载(LCC)超薄封装,可以通过I2C总线直接与各种微处理器相连。

在这里插入图片描述

2.主要特点:

  1. 压力范围:300-1100hPa(海拔9000米~-500米)
  2. 电源电压:1.8V-3.6V(VDDA),1.62V~3.6V(VDDD)
  3. LCC8封装:无铅陶瓷载体封装(LCC)
  4. 尺寸:3.6mmx3.8x0.93mm
  5. 低功耗:5μA,在标准模式
  6. 高精度:低功耗模式下,分辨率为0.06hPa(0.5米)
  7. 高线性模式下,分辨率为0.03hPa(0.25米)
  8. 含温度输出
  9. I2C接口
  10. 温度补偿
  11. 无铅,符合RoHS规范
  12. MSL 1反应时间:7.5ms
  13. 待机电流:0.1μA
  14. 无需外部时钟电路

3. 典型应用:

  1. GPS精确导航(航位推算,上下桥检测等)
  2. 室内室外导航
  3. 休闲、体育和医疗健康等监测
  4. 天气预报
  5. 垂直速度指示(上升/下沉速度)
  6. 风扇功率控制

4. 原理图

在这里插入图片描述
从原理图可以看出,SCL和SDA是I2C总线的通信引脚,VDD和GND用来接电源的正负极,接3.3V即可。

5. 典型应用电路

BMP180的压力和温度数据,必须通过传感器的校准数据进行补偿计算,校准数据可以通过读取其内部的EEPROM存储器来获取。

BMP180由一个压阻传感器、一个模数转换器和一个控制单元组成与E2PROM和串行I2C接口。如下图所示:

在这里插入图片描述

6. 测量流程

在这里插入图片描述

7. 工作模式

它有4钟工作模式,由过采样率(OSRS)表示,其实就是最大转换时间的不同,如

  1. 超低功耗(ultra low power)= 0,最大转换时间为4.5ms;
  2. 标准(standard) = 1,最大转换时间为7.5ms;
  3. 高精度(high)= 2,最大转换时间为13.5ms;
  4. 超高精度(ultra high resolution))= 3,最大转换时间为25.5ms。

在这里插入图片描述

二、软件

以下代码来自野火–F407_霸天虎开发板。

1.初始化

BMP180的从机地址为0x77

在这里插入图片描述

示例代码如下:

#define BMP180_I2C_ADDR          0x77
#define BMP180_PROM_START__ADDR  0xaa
#define BMP180_PROM_DATA__LEN    22

 /**
  * @brief	初始化,获取校准参数			
  * @note		在第一次转换前要先调用这个函数,然后用于真实值计算
  */
static void bmp180Init(void)
{
	uint8_t data[22];		
		
	/*	从器件中读取22个校准数据	*/
    i2cRead(BMP180_I2C_ADDR, BMP180_PROM_START__ADDR, BMP180_PROM_DATA__LEN, data);

    /*parameters AC1-AC6*/
    calParam.ac1 = (data[0] << 8) | data[1];
    calParam.ac2 = (data[2] << 8) | data[3];
    calParam.ac3 = (data[4] << 8) | data[5];
    calParam.ac4 = (data[6] << 8) | data[7];
    calParam.ac5 = (data[8] << 8) | data[9];
    calParam.ac6 = (data[10] << 8) | data[11];

    /*parameters B1,B2*/
    calParam.b1 = (data[12] << 8) | data[13];
    calParam.b2 = (data[14] << 8) | data[15];

    /*parameters MB,MC,MD*/
    calParam.mb = (data[16] << 8) | data[17];
    calParam.mc = (data[18] << 8) | data[19];
    calParam.md = (data[20] << 8) | data[21];
}

2.获取原始温度

要获得温度数据,必须先向控制寄存器(地址0xF4)写0x2E,然后等待至少4.5ms,才可以从地址0xF6和0xF7读取十六位的温度数据。

在这里插入图片描述

#define BMP180_I2C_ADDR           0x77
#define BMP180_T_MEASURE          0x2E                // temperature measurent 
#define BMP180_CTRL_MEAS_REG      0xF4
#define BMP180_ADC_OUT_MSB_REG    0xF6

 /**
  * @brief	获取未偏移的原始温度数据,需要等待4.5ms才转换完成		
  * @note		本函数要被循环调用
	*					用到了systick的millis函数获取时间。	
	*	@retval convDone:		ture:转换完成			_FAIL:转换未完成
  */
static uint8_t bmp180GetUT(void)
{
    uint8_t data[2]; 
		
		static uint8_t convDone = _FAIL;	//静态变量,用于标志是否转换完成
		static uint32_t convTime=0;		//静态变量,用于记录开始转换用了多长时间		

		if(convTime==0)								//第一次调用本函数
		{		
			convDone = _FAIL;						//重置标志位		
			i2cWrite(BMP180_I2C_ADDR, BMP180_CTRL_MEAS_REG, BMP180_T_MEASURE);		//控制开始转换温度
			convTime= millis();					//记录开始转换时刻
		}	
		
		if((millis()-convTime) > 5)		//温度转换需要4.5ms	
		{
			i2cRead(BMP180_I2C_ADDR, BMP180_ADC_OUT_MSB_REG, 2, data);						//读取温度转换的数据
			bmp180Val.ut = (data[0] << 8) | data[1];																	//温度数据格式
			
			convDone 	= _SUCCESS;						//转换完成标志
			convTime	= 0;							//重置转换时间
		}
		
		return convDone;
}

3.获取真实温度

在这里插入图片描述

 /**
  * @brief	计算真实温度值		
  * @note		datasheet有公式
  * @param	ut:未偏移的原始温度数据,由bmp180_get_ut	函数得到	
  * @retval	temperature:真实的温度值,单位:0.1摄氏度
  */
static void bmp180CalTemperature(void)
{
    int16_t temperature;
    int32_t x1, x2;
		
	/*	根据转换公式计算参数	*/
    x1 = (((int32_t) bmp180Val.ut - (int32_t) calParam.ac6) * (int32_t) calParam.ac5) >> 15;
    x2 = ((int32_t) calParam.mc << 11) / (x1 + calParam.md);
		
    bmp180Val.paramB5 = x1 + x2;
		
	/*	计算真实温度值	*/
    temperature = (( bmp180Val.paramB5 + 8) >> 4);  // 温度值单位: 0.1 C
		
	bmp180Val.temperature = temperature; //计算完才赋值,减少上层函数调用get时,交给上层中间数据的概率
}

4.获取原始气压

要获得气压数据,必须先向控制寄存器(地址0xF4)写0x34(0x74、0xB4、0xF4),然后等待至少4.5ms,才可以从地址0xF6和0xF6读取16位的气压数据。
在这里插入图片描述

#define BMP180_I2C_ADDR           0x77
#define BMP180_P_MEASURE          0x34                // pressure measurement
#define BMP180_CTRL_MEAS_REG      0xF4
#define BMP180_ADC_OUT_MSB_REG    0xF6

 /**
  * @brief	获取未偏移的原始压力数据
  * @note		获取压力前调用,等待时间:
	*					模式0,4.5ms 模式1,7.5ms	模式2,13.5ms 模式3,25.5ms	
	*					用到了systick的millis函数获取时间。
	*					本函数要被循环调用
	*	@retval convDone:		ture:转换完成			_FAIL:转换未完成
  */
static uint8_t bmp180GetUP(void)
{

     uint8_t data[3]; 
			//uint8_t ctrl=0x0f;
		static uint8_t convDone = _FAIL;	//静态变量,用于标志是否转换完成
		static uint32_t convTime = 0;		//静态变量,用于记录开始转换用了多长时间		

		if(convTime == 0)								//第一次调用本函数
		{		
			convDone = _FAIL;						//重置标志位	BMP180_CTRL_MEAS_REG	
			i2cWrite(BMP180_I2C_ADDR,BMP180_CTRL_MEAS_REG ,(BMP180_P_MEASURE + (OSS<< 6)));	//开始压力转换
			convTime = millis();					//记录开始转换时刻
		}
		if((millis()-convTime) > OSS_TIME)		//判断是否转换完成
		{
			i2cRead(BMP180_I2C_ADDR, BMP180_ADC_OUT_MSB_REG, 3, data);
			bmp180Val.up = (((uint32_t) data[0] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[2]) >> (8 - OSS);
			
			convDone 	= _SUCCESS;						//转换完成标志
			convTime	= 0;							//重置转换时间
		}	
		return convDone;
}

5.获取真实气压

在这里插入图片描述

 /**
  * @brief	计算真实压力数据		
  * @note		datasheet有公式	
  * @param	up:未偏移的原始压力数据,由bmp180GetUp函数得到
  * @retval	pressure:真实的压力值,单位:Pa
  */
static void bmp180CalPressure(void)
{
    int32_t  pressure,x1, x2, x3, b3, b6;
    uint32_t b4, b7;
		
	/*	根据公式计算参数	*/
    b6 = bmp180Val.paramB5 - 4000;
    // *****calculate B3************
    x1 = (b6 * b6) >> 12;
    x1 *= calParam.b2;
    x1 >>= 11;

    x2 = (calParam.ac2 * b6);
    x2 >>= 11;

    x3 = x1 + x2;

    b3 = (((((int32_t)calParam.ac1) * 4 + x3) << OSS) + 2) >> 2;

    // *****calculate B4************
    x1 = (calParam.ac3 * b6) >> 13;
    x2 = (calParam.b1 * ((b6 * b6) >> 12) ) >> 16;
    x3 = ((x1 + x2) + 2) >> 2;
    b4 = (calParam.ac4 * (uint32_t) (x3 + 32768)) >> 15;
     
    b7 = ((uint32_t)(bmp180Val.up - b3) * (50000 >> OSS));
    if (b7 < 0x80000000) 
	{
		pressure = (b7 << 1) / b4;
    }
	else 
	{ 
		pressure = (b7 / b4) << 1;
    }

    x1 = pressure >> 8;
    x1 *= x1;
    x1 = (x1 * SMD500_PARAM_MG) >> 16;
    x2 = (pressure * SMD500_PARAM_MH) >> 16;
		
	/*	计算真实压力值	*/
    pressure += (x1 + x2 + SMD500_PARAM_MI) >> 4;   // 压力值单位: Pa
		
	bmp180Val.pressure = pressure; //计算完才赋值,减少错误地把中间数据交给上层的概率 (上层使用get函数获取数据)
}

6.海拔高度的换算

BMP180传感器提供温度和压力的绝对测量值,但不提供海拔高度的直接输出。

由于大气压力随高度升高而降低。

在这里插入图片描述
由上图我们可知,气压与海平面的高度具有近似线性的反比,因此如果我们测量了某地的气压,我们可以使用简单的数学运算从海平面计算海拔高度。

 /**
  * @brief		更新气压、温度计数据	
  * @note			本函数要被循环调用,整个转换时间30ms
  * @param		tempData,温度数据指针,若数据更新了,本函数会把tempData的isNew标志置1
  * @retval	
  */
static void bmp180TempUpdate(SENSOR_DATA_T *tempData)
{
	static uint8_t state = 0;
	
	isNew = tempData ->isNew;			//isNew静态变量用来同步tempData的isNew变量
										//isNew静态变量同步得的信息在后面会在presUpdate和altiUpdate函数使用	
	switch(state)
	{
		case 0:
				if(bmp180GetUT() == _SUCCESS)		//温度转换
					state++;						//温度转换完成,进入压力转换状态
					break;					
		case 1:
				if(bmp180GetUP() == _SUCCESS)		//压力转换
					state++;						//压力转换完成,开始真实值计算
					break;					
		case 2:
				bmp180CalTemperature();			//真实值计算
				bmp180CalPressure();
											
				bmp180Val.altitude = (1.0f - pow(bmp180Val.pressure / 101325.0f, 0.190295f)) * 44330.0f; 
				//根据压力值计算海拔高度公式由datasheet而来,	单位为:米																																																	      //公式中的1hPa=0.01Pa,由传感器算出的压力值单位为Pa,代码这里在使用datasheet的公式时化了单位	
				tempData->isNew = isNew = _SUCCESS ;	//更新数据状态
				state = 0;				
				break;
	}
}

通过当地的气象服务中可以得到海平面压力P0,利用传感器读取的压力P和该海平面压力P0的值,通过上面的公式可以计算传感器所在位置的高度。

注意:海平面压力P0的值不是固定的,跟所属区域及环境温度和天气情况的变化而变化。


三、总结

今天主要讲了气压传感器BMP180的简单应用。

感谢你的观看!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1533893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【考研数学】全年复习懒人包+资料分享

题主要真是能把这两样做透了&#xff0c;别说90&#xff0c;120都不是问题呀&#xff01;那么我们就先来说说你如何能把这1800做透吧。这可是人称考研数学路上最厚的一本习题册了。经常有人是做到一半就被劝退的&#xff01;假设你是挑题出来做&#xff0c;那也行&#xff0c;不…

ThreaTrace复现记录

1. 环境配置 服务器环境 需要10.2的cuda版本 conda环境 包的版本&#xff1a; python 3.6.13 pytorch 1.9.1 torch-cluster 1.5.9 torch-scatter 2.0.9 torch-sparse 0.6.12 torch-spline-conv 1.2.1 torch-geometric 1.4.3 环境bug 这里环境搭建好以后&#xff0c;就可以正…

ssm基于Vue.js的在线购物系统的设计与实现论文

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线购物系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了在线购物系统&#xff0c;它彻底改变了过去传统的…

【数据结构】——线性表(顺序表加链表),万字解读(加链表oj详解)

前言 由于之前存在过对两者的区别考虑&#xff0c;所以把他们放在一起来说&#xff0c;更加容易区别和理解 对于有关线性表的概念这里就不展示了&#xff0c;这里主要是介绍线性表里面的这两个结构的知识点 一.顺序表 1.顺序表介绍 顺序表的存储结构和逻辑结构都是相邻的&a…

【前端寻宝之路】学习和总结JavaScript的书写形式

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-oO1UdfWcWZUMkIDr {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

【C语言进阶篇】自定义类型:联合体和枚举

【C语言进阶篇】自定义结构体类型&#xff1a;联合体和枚举 &#x1f308;个人主页&#xff1a;开敲 &#x1f525;所属专栏&#xff1a;C语言 &#x1f33c;文章目录&#x1f33c; 1. 联合体 1.1 联合体类型的声明 1.2 联合体的特点 1.3 联合体大小的计算 2. 枚举 2.1 枚举…

2.5、栅格布局(GridRow/GridCol)

概述 栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用。主要优势包括: 提供可循的规律:栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题。通过将页面划分为等宽的列数和行数,可以方便地对页面元素进行定位和排版。 统一的定…

设计模式 模板方法模式

01.如果接到一个任务&#xff0c;要求设计不同型号的悍马车 02.设计一个悍马车的抽象类&#xff08;模具&#xff0c;车模&#xff09; public abstract class HummerModel {/** 首先&#xff0c;这个模型要能够被发动起来&#xff0c;别管是手摇发动&#xff0c;还是电力发动…

AI训练,为什么需要GPU?

随着人工智能热潮&#xff0c;GPU成为了AI大模型训练平台的基石&#xff0c;决定了算力能力。为什么GPU能力压CPU&#xff0c;成为炙手可热的主角呢&#xff1f;首先我们要先了解一下GPU的分类。提到分类&#xff0c;就得提及到芯片。 半导体芯片分为数字芯片和模拟芯片。其中&…

浅谈亚信安慧AntDB-M条件下推

概述 “下推”是数据库管理系统优化查询性能的一种思路&#xff0c;集中式数据库支持谓词下推和投影下推&#xff0c;通过将Filter&#xff08;过滤&#xff09;和Project&#xff08;映射&#xff09;算子在算子数中向下移动&#xff0c;提前对行/列进行裁剪&#xff0c;减少…

从嵌套事务的日志看MyBatis的sqlSession生命周期

service层业务代码 Override public void test(){QueryWrapper<StoreRebateCalculateLog> queryWrapper;queryWrapper new QueryWrapper<>();queryWrapper.eq("delete_flag", 0);//执行查询A,以非事务方式执行List<StoreRebateCalculateLog> sto…

代码学习第24天----回溯算法

随想录日记part24 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.10 主要内容&#xff1a;回溯算法在代码学习中尤其重要&#xff0c;所以今天继续加深对其的理解&#xff1a;1&#xff1a;递增子序列 &#xff1b;2.全排列 &#xff1b;3.全排列II 491.递…

Android:adb命令

执行adb命令的窗口如下 Mac或Linux系统里的终端窗口&#xff1b; window系统运行输入cmd打开的指令窗口&#xff1b; Android Studio 里控制下面的Terminal窗口 1. 查看已链接的设备和模拟器 adb devices -l 2. 查看Android内核版本号 adb shell getprop ro.build.version.re…

近期TRO案件盘点,外观专利又双叒叕成维权高发地

近期&#xff0c;多个权利人进行外观专利维权&#xff0c;众多国内卖家被告&#xff0c;建议卖家自查。 案例一&#xff1a;尿布收纳袋——商标外观专利版权 案例关于这款尿布收纳袋&#xff0c;涉及商标、外观专利和版权。 &#xff08;图源网络&#xff0c;侵删&#xff09…

HarmonyOS NEXT应用开发之跨文件样式复用和组件复用

介绍 本示例主要介绍了跨文件样式复用和组件复用的场景。在应用开发中&#xff0c;我们通常需要使用相同功能和样式的ArkUI组件&#xff0c;例如购物页面中会使用相同样式的Button按钮、Text显示文字&#xff0c;我们常用的方法是抽取公共样式或者封装成一个自定义组件到公共组…

汽车KL15、KL30、ACC的区别

文章目录 前言一、KL30是什么&#xff1f;二、KL15是什么&#xff1f;KL15信号的演变 三、为啥用KL15、KL30呢&#xff1f; 前言 相信刚接触汽车电子的伙伴都会有一个疑惑&#xff0c;什么是KL15?什么是KL30? 内心一脸懵逼…… KL是德语Klemme的缩写&#xff0c;指的是ECU的…

软件测评中心分享:软件鉴定测试与验收测试有什么联系和区别?

1、软件鉴定测试   软件鉴定测试是在软件开发完成后进行的一个核心环节&#xff0c;是通过对软件进行功能性、性能、安全性等方面的综合测试&#xff0c;来验证软件是否符合规定的需求和标准。 2、软件验收测试   软件验收测试是软件开发工作结束后的最后一个环节&#xf…

深入理解 CSS:基础概念、注释、选择器及优先级

在构建网页的过程中&#xff0c;我们不仅需要HTML来搭建骨架&#xff0c;还需要CSS来装扮我们的网页。那么&#xff0c;什么是CSS呢&#xff1f;本文将带大家了解css的基础概念&#xff0c;注释、选择器及优先级。 一、CSS简介 1.1 什么是CSS CSS&#xff0c;全称为Cascadin…

IoT 物联网场景中 LoRa + 蓝牙Bluetooth 室内场馆高精定位技术全面解析

基于LoRa蓝牙的室内场景定位技术&#xff0c;蓝牙主要负责位置服务&#xff0c;LoRa主要负责数据传输。 01 LoRa和蓝牙技术 LoRa全称 “Long Rang”&#xff0c;是一种成熟的基于扩频技术的低功耗、超长距离的LPWAN无线通信技术。LoRa主要采用的是窄带扩频技术&#xff0c;抗干…

VS2019 C++ NetCDF配置

原链接1 原链接2 做个备份 1.下载对应的NetCDF-C和C库 官网下载 选择64位的NetCDF4安装版&#xff08;没有DAP的&#xff09; 现在官网已经没有NetCDF-C 4.7.3 版本了&#xff0c;网上别人提供了新的下载地址&#xff1a;NetCDF各个版本&#xff08;Index of /library/net…