来到本文章,相信您对BMP180的使用存在某些疑惑,或者想要学习使用BMP180,或许本文将帮助您完成对BMP180的学习和控制!
BMP180可以用来干什么?
长话短说,通过阅读手册我们知道BMP180可以为我们提供温度和气压数据的测量与检测,通过对气压数据的进一步加工,可以计算出海拔高度信息。
BMP180该怎么用?
BMP180做为一个独立的芯片,能够为我们提供气压和温度信息的测量。对于任何一个独立的模块,我们可以将它想象成一个黑盒,可以为我们提供一些信息,而不需要考虑其内部是怎么实现的,只需要和它进行沟通(通信)即可获得我们想要知道的东西。
- 如何与BMP180取得联系?
作为一个人,我们想要彼此之间的想法,语言是沟通的渠道,内容就是载体。比如普通话便是语言的一种规范。但不同地区的人存在不同的方言,发音用词都有所差异,但是只要彼此都承认这种规范(常常说听得懂彼此的话),便可以取得有效的沟通,到达交换信息的目的。而想要与BMP180取得联系,我就必须遵循IIc通讯协议(一个只能理解IIc得小家伙),所以IIc通讯协议便是与BMP180沟通的规范。接下来让我们来看一看什么是IIc通讯协议! - 让我们来看看什么是IIc通讯协议!
IIc是通讯协议是基于IIc总线的通讯规范,总线包括两根双向信号线,一根是数据线(SDA),一根是时钟线(SCL ),在总线上可以挂接多个设备,利用设备地址的方式来识别不同的器件。那么请你记住:BMP180在这个总线上的地址是0xEE。依据IIc通讯协议所规定的时序,一位一位将数据传送完毕。如果你还没有接触过IIc通讯协议,可以参考有关IIc的文档进行学习,以下是IIc通讯协议的详细介绍。
https://www.nxp.com.cn/docs/en/user-guide/UM10204.pdf
- 让我们用51单片机实现软件模拟IIc进行通讯
我们使用模块化编程的思想实现对BMP180的驱动,请大概阅读实现IIc的头文件,你不用完全理解每一行代码的意思,能够利用头文件提供的四个函数进行基本的通讯即可。
/***********************************************************
本程序实现了软件模拟IIC通讯,数据传送时,先传送最高位(MSB)
每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)
作者联系方式:1932857334 By QQ
***********************************************************/
#ifndef _IIC_INCLUDE_H_
#define _IIC_INCLUDE_H_
/* 引用51标准头文件 */
#include <reg52.h>
/* 自定义宏 */
#define IIc_write 0 //IIc写方向位
#define IIc_read 1 //IIc读方向位
#define IIc_WaitTime 4 //时序时间控制IIc速度
/* IIC通讯协议接口声明 */
sbit SDA = P1^0; //时钟总线
sbit SCL = P1^1; //数据总线
/* 函数声明 */
void IIc_Start(void); //IIc起始信号发生函数
void IIc_Stop(void); //IIc终止信号发生函数
unsigned char IIc_ReadByte(bit ACK); //IIc接收一字节数据 返回一字节数据 并发送应答信号
bit IIc_SendByte(unsigned char Data); //IIc发送一字节数据 发送一字节数据 并返回应答信号
#endif /*_IIC_INCLUDE_H_*/
如果说头文件是一张宏图,向外界展示了自身的功能与实力,那么C文件便是默默奉献的员工,将宏图里的想法一一实现,接下来我们再来来看看这些员工吧,你可以完全不用关心他们是怎么工作的,今后我们只会使用提供给外界的函数。
#include "IIc.h"
#include "Delay.h"
#define SET 1
#define RESET 0
/* 释放IIc总线 */
static void IIc_ReleaseWire(void)
{
SCL = RESET;//下拉数据线
SDA = SET;//上拉数据线
}
/* IIc接收应答信号函数 返回应答信号 */
static bit IIc_ReadACK(void)
{
bit ACK;//应答标志位
SCL = SET;//拉高时钟总线 准备读取应答信号
ACK = SDA;//获取应答信号
IIc_ReleaseWire(); //释放总线
if(!ACK)
return SET;//应答返回1
return RESET;//返回非应答
}
/* IIc应答发生信号函数 主机发送应答信号 */
static void IIc_SendACK(bit ACK)
{
SDA = ~ACK;//装载应答信号
SCL = SET;//拉高时钟线 发送应答信号
Delay_Us(IIc_WaitTime);//保持稳定
IIc_ReleaseWire();//释放总线
}
/* IIc起始信号发生函数 */
void IIc_Start(void)
{ //时钟线处于高电平期间,数据线由高到低进行变化
SCL = SET;
SDA = SET;
Delay_Us(IIc_WaitTime);//高电平期间
SDA = RESET;
IIc_ReleaseWire();//释放总线
}
/* IIc终止信号发生函数 */
void IIc_Stop(void)
{ //时钟线处于高电平期间,数据线由低到高进行变化
SDA = RESET;
SCL = SET;
Delay_Us(IIc_WaitTime); //高电平期间
SDA = SET;
Delay_Us(IIc_WaitTime); //低电平期间
//终止之后,两根线均处于高电平状态,IIc通讯进入空闲状态
}
/* IIc接收一字节数据 返回一字节数据并发送应答信号 */
unsigned char IIc_ReadByte(bit ACK)
{
unsigned char index,Data=0;//定义数据变量
for(index=0;index<8;index++)//循环读取一字节数据
{
SCL = SET;//拉高时钟线 准备读取数据
Data <<= 1;//数据右移
if(SDA) Data |=0x01;//读取1 否则为0
IIc_ReleaseWire(); //释放总线
}
IIc_SendACK(ACK);//发送应答信号
return Data;//返回数据
}
/* IIc发送一字节数据并返回应答信号 */
bit IIc_SendByte(unsigned char Data)
{
unsigned char index;//for循环变量
for(index=0;index<8;index++)//循环发送一字节数据
{
if(Data&0x80)
SDA = SET;
else
SDA = RESET;
SCL = SET;//拉高数据线,发送一位数据
Delay_Us(IIc_WaitTime);//稳定数据,确保读取
Data <<= 1;//数据右移
IIc_ReleaseWire(); //释放总线
}
return IIc_ReadACK();//读取从机应答信号
}
- 是时候拜访寄存器了!
说了那么多,是时候和寄存器打交道了。控制BMP180的唯一方法便是读写内部的寄存器,利用IIc通讯协议访问寄存器的方法是:BMP180地址+寄存器地址(详细可以参考手册或者参考代码)。在BMP180内部拥有28个可以为我们提供信息的寄存器,请因为数量而不要担心,耐心的看一看每个寄存器的功能。他们分别是三个数据输出寄存器(out_xlsb、out_lsb、out_msb)、控制寄存器(ctrl_meas)、复位寄存器(soft_reset)、ID寄存器、22个数据校正EEPROM。每一个寄存器都有自己的标识,通常叫做地址,通过下面这个表格来看看他们的地址都是啥?
- 这些寄存器有啥用?
数据输出寄存器:它属于只读寄存器,我们通过读取寄存器里面的数据可以获得有关温度和气压的原始数据。注意是原始数据,需要通过EEROM中的数据进行补偿计算才能得到我们想要的信息。
控制寄存器:它属于可读可写的寄存器,通过控制寄存器中的某些位,我们可以控制让BMP180执行温度转换和气压转换,以及气压转换精度。
ID寄存器:这是一个只读寄存器,里面存储了固定的0x55,可以用来进行识别设备。
校正数据寄存器:22字节的校正参数,用来校正原始数据,不同的器件可能校正参数不相等。 - 是时候来看看BMP180的宏图了!
同样的道理,你可以不用关心内部怎么实现的,利用头文件提供的函数即可实现我们想要的功能。利用BMP180_Init() 对器件执行初始化操作,然后就可以利用BMP180_GetTemperature()来获得温度信息,BMP180_GetAirPressure()来获得气压信息,BMP180_GetElevation()来获得海拔信息,在后期使用这些数据的时候一定要定期使用BMP180_UpData()来将传感器的数据刷新到缓冲区里面,否则每次获得的都是相同的数据,同时在运用他们的时候请注意他们的单位!
/***********************************************************
本程序实现了对气压传感器BMP180的基本操作
可以进行温度、气压、海拔数据信息的测量及计算
作者联系方式:1932857334 By QQ
***********************************************************/
#ifndef _INCLUDE_BMP180_H_
#define _INCLUDE_BMP180_H_
/* 设备地址 */
#define BMP180_Address 0xEE
/* 部分寄存器地址宏定义 */
#define ID_Address 0xD0
#define MSB_Address 0xF6
#define LSB_Address 0xF7
#define XLSB_Address 0xF8
#define Cotrol_Address 0xF4
#define SOFT_RESET_Address 0xE0
/* 内部标志符 */
#define BMP180_ID 0x55
#define BMP180_SCO 0x20
#define BMP180_TEMP_CON 0x0E
#define BMP180_AIRP_CON 0x14
#define BMP180_SOFT_RESET 0xB6
/* 气压采集精度 */
#define U_L_P 0x00 //低功耗
#define STANDARD 0x01 //标准
#define HIGH_RES 0x02 //高分辨率
#define U_H_RES 0x03 //超高分辨率
#define OSS U_H_RES
/* 气压传感器BMP180数据结构体 */
typedef struct {
/* BMP180 EEPROM中的数据 */
short AC1;
short AC2;
short AC3;
unsigned short AC4;
unsigned short AC5;
unsigned short AC6;
short B1;
short B2;
short MB;
short MC;
short MD;
/* 补偿值 */
long B5;
/* 温度气压原始值 */
long UP; //气压原始值
long UT; //温度原始值
/* 温度和气压与海拔 */
float Temp;//温度 单位摄氏度
float AirP;//气压 单位帕斯卡
float Height;//海拔高度 单位米
}BMP180;
/* 函数声明 */
bit BMP180_Init(void);//气压传感器初始化操作
void BMP180_UpData(void);//刷新气压传感器数据
float BMP180_GetElevation(void);//获得海拔数据 单位:M
float BMP180_GetAirPressure(void);//获得气压数据 单位:Pa
float BMP180_GetTemperature(void);//获得温度数据 单位:摄氏度
#endif /*_INCLUDE_BMP180_H_*/
细心的小伙伴可能发现在里面都没有看到IIc的身影,它哪里去了呢?
原来通过模块化编程已经一步步把每一个板块进行的封装,这样可以让我们的程序具有很好的移植性,假设有一天需要将51的代码移植到32上面,只需要将IIc的驱动进行更改(原头文件的内容不改变,改变实现方式——C文件),不需要对BMP180的操作驱动进行任何修改即可完成移植,大大的提高了工作效率。或者有一个新的项目需要基于BMP180来实现,那么我们可以直接使用这一份代码,在新的板块里运用函数接口来实现新的功能!
比如:我们需要显示气压信息,只需要先读取气压,然后显示就结束了,是不是很方便?
写在最后的话
非常感谢你的阅读,希望能够帮助到你,需要详细的了解如果有任何建议都可以私信我,后续将逐步完善一些常用模块的时候心得,如果有需要的可以评论优先安排哈哈哈~~