气压传感器BMP180的简单应用

文章目录

  • 一、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的简单应用。

感谢你的观看!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

int数组最大能设置为多长?以及能存储的数字为多大?

在编译器里&#xff0c;每种类型的变量定义数组的时候都有一个数组大小&#xff0c;而这个大小对于不同的变量而言有不同的上限&#xff0c;这里的最大长度更准确的来说应该是系统堆的最大值。 一个字符占1byte大小&#xff0c;8位&#xff0c;所以&#xff0c;理论上&#xff…

【小白入门篇2】总有一款AI工具适合你

上一篇《【小白入门篇1】GPT到底是怎样练成&#xff1f;》介绍了GPT的形成&#xff0c;直到今日&#xff0c;GPT工具层出不穷&#xff0c;搞得很多初学者眼花缭乱&#xff0c;今天梳理一下国内外比较出名的GPT工具&#xff0c;适用各个领域非专业的同学选择。GPT工具目前基本以…

安捷伦Agilent DSA91304A高性能示波器

181/2461/8938产品概述&#xff1a; DSA91304A示波器&#xff1a;13GHz 带宽。Keysight Infiniium 90000 系列示波器具有业界较低的本底噪声&#xff0c;能够提供现有示波器中更高的实时抖动测量精度。 DSA91304A Infiniium 高性能示波器&#xff1a;13 GHz Keysight Infini…

docker一键部署若依前后端分离版本

比如这里把文件放到/xin/docker/jiaoZ/的目录下&#xff0c;jar包和下面的配置文件都放在这个文件夹下。 注意要把jar端口改为你实际启动的&#xff0c;映射端口也可以改为你想要的。 这里的映射端口为&#xff1a;nginx监听80端口&#xff0c;jar在8620端口&#xff0c;mysq…

Python分析人民日报关于台湾的报道

【项目背景】 《人民日报》数据挖掘&#xff0c;时间&#xff1a;1949.10.1-2023.12.31 标题含有“台湾”的报道 需要以下内容 1、标题&#xff0c;即上述时间段的报道标题和相应的报道时间、版面 2、包含标题、时间、版面的所有报道内容 3、报道的年份和数量的趋势图 4、…

new mars3d.layer.BusineDataLayer({加载动态的.png图标

问题&#xff1a; 用BillboardEntity或者BusineDataLayer方法加载图标是静态的&#xff0c;如果用div的话&#xff0c;400个就会很卡顿 解决方案&#xff1a; 目前BillboardEntity加载是静态的&#xff0c;无法加载动图&#xff0c;网上搜了下&#xff0c;可以使用apngjs.js…

javaSE练习题(一)

1、BMI是根据体重测量健康的方式。通过以千克为单位的体重除以以米为单位的身高的平方计算出BMI。下面是16 岁以上人群的BMI图表: 编写一个java程序&#xff0c;提示用户输人以磅为单位的体重和以英寸为单位的身高&#xff0c;然后显示BMI值。注意: 1磅是0.453592 37千克而1英寸…

GPU云服务器的优势和应用

GPU即图形处理器&#xff0c;是一种高性能计算加速器&#xff0c;主要用于处理复杂的图像、视频等。GPU云服务器&#xff0c;指的是在云计算环境下&#xff0c;通过云平台提供GPU计算能力的虚拟服务器。随着科技的迅猛发展&#xff0c;科技领域对其的讨论和应用也日益热烈、广泛…

高德地图——轨迹回放和电子围栏

功能点 地图的初始化显示电子围栏(先初始化在调接口显示电子围栏)显示定位显示轨迹轨迹回放 (回放速度无法控制是因为高德地图的版本问题,不要设置版本,使用默认的即可生效)获取当前城市及天气情况设置地图样式坐标拾取器重点 默认当前城市地图加载完成的生命周期this.ma…

Linux课程____进程管理

记录工作日志 script 240319.log CTRLd 退出 cat 240319.log //查看 一、查看进程 1.静态 ps -aux ps -elf 2.动态 top 3.pgrep 查看特定条件的进程 pgrep -l “log” pgrep -l "ssh" pgrep -l -U redhat 4.pstree 查看进程树 pstree -aup 所有…

element plus等框架中属性值是组件如何传入,替换分页图标

在 Vue 中替换element plus 分页图标 正常写法引入组件 import prevIcon from /components/xx.vue;<el-pagination layout"prev, pager, next" :prev-icon"prevIcon" :total"5" />利用 h 函数写法 const prevIcon h(div, [xr]);可以写…

排序算法:归并排序(递归)

文章目录 一、归并排序的思路二、代码编写 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦&#xff01; 所属专栏:排序算法 一、归并排序的思路 单…

第二话 让屏幕显示想要的东西

上一话搭建了可说是可以开发了 接下来想办法 让 屏幕显示想要的东西 但是报错: ************************************************************************** * Looking for Adafruit_ILI9341.h dependency? Check our library registry! * * CLI > platformio lib se…

【DataWhale学习笔记-蝴蝶书共读】大语言模型背后

从图灵测试到ChatGPT 1950年&#xff0c;艾伦•图灵(Alan Turing)发表论文《计算机器与智能》&#xff08; Computing Machinery and Intelligence&#xff09;&#xff0c;提出并尝试回答“机器能否思考”这一关键问题。在论文中&#xff0c;图灵提出了“模仿游戏”&#xff…

AD软件中怎么添加不同元素之间的间距规则呢

AD软件中怎么添加不同元素之间的间距规则呢 答&#xff1a;AD软件提供了某一个元素针对其他元素之间的间距规则的设置。 首先执行菜单命令【设计】-【规则】或者快捷键DR打开规则约束编辑器&#xff0c;然后在间距规则Clearance里面添加一个新的规则&#xff0c;如图1所示 图…

阅读MySQL知识2

1、三大范式 2、DML 语句和 DDL 语句区别 3、主键和外键的区别 4、drop、delete、truncate 区别 5、基础架构 6、MyISAM 和 InnoDB 有什么区别&#xff1f; 7、推荐自增id作为主键问题 8、为什么 MySQL 的自增主键不连续 9、redo log 是做什么的? 10、redo log 的刷盘…

19---时钟电路设计

视频链接 时钟硬件电路设计01_哔哩哔哩_bilibili 时钟电路设计 晶振是数字电路的心脏&#xff0c;数字电路需要一个稳定的工作时钟信号&#xff0c;时钟电路至关重要&#xff01; 1、晶振概述 晶振一般指晶体振荡器。晶体振荡器是指从一块石英晶体上按一定方位角切下薄片&…

H6603实地架构降压芯片100V耐压 80V 72V 60V 48V单片机/模块供电应用

H6603 是一款内置功率 MOSFET降压开关转换器。在宽输入范围内&#xff0c;其最大持续输出电流 0.8A&#xff0c;具有极好的负载和线性调整率。电流控制模式提供了快速瞬态响应&#xff0c;并使环路更易稳定。故障保护包括逐周期限流保护和过温保护。H6603 最大限度地减少了现有…

传输层/UDP/TCP协议

再谈端口号 TCP/IP协议用“源IP”&#xff0c;“源端口号”&#xff0c;“目的IP”&#xff0c;“目的端口号”&#xff0c;“协议号”&#xff0c;这样一个五元组来标识一个通信&#xff08;可以用netstat -n来查看&#xff09;。 端口号的划分和知名端口号 我们之前就说过&am…

数据泄露问题怎么解决?迅软DSE加密软件助您守护重要信息

企业信息泄露的危害 企业数据泄露事件不仅给企业带来了经济损失和声誉损害&#xff0c;还可能导致用户个人信息的泄露&#xff0c;引起社会广泛关注。 因此&#xff0c;企业需要采取更加严格的数据保护措施&#xff0c;使用数据加密系统以防范潜在的数据泄露风险。同时&#…