bmp085要点.docx
- 文档编号:3326363
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:12
- 大小:115.84KB
bmp085要点.docx
《bmp085要点.docx》由会员分享,可在线阅读,更多相关《bmp085要点.docx(12页珍藏版)》请在冰豆网上搜索。
bmp085要点
气压传感器(BMP085)
在测量海拔高度时,传统的做法是通过测量某一高度的大气压力,再经过换算才能得到高度数据。
为了测量大气压力,就得用上气压传感器,下面就来讨论一下气压传感器的应用。
气压传感器是压力传感器中的一种,它专用于测量气体的绝对压强。
目前市场上能见到的气压传感器有很多种,下面就以市场上常见的Bosch公司推出的BMP085来进行讨论。
BMP085不仅可以实时的测量大气压力,还能测量实时温度。
同时它还具有IIC总线的接口,便于单片机进行访问。
另外它的使用也很方便,不需要太多的操作就可读取到气压及测量数据。
BMP085采用强大的8脚陶瓷无引线芯片承载(LCC)超薄封装,它性能卓越,内置有校准补偿,绝对精度最低可以达到0.03hPa(0.25米),并且耗电极低,只有3μA。
气压测量范围从300hPa到1100hPa,换算成高度为海拔9000米到500米。
下图是其封装外形和引脚排列。
引脚各功能如下:
1脚(GND)接电源地,2脚(EOC)为完成转换输出,3脚(VDDA)为正电源,4脚(VDDD)为数字正电源,5脚为空,6脚(SCL)为IIC的时钟端,7脚(SDA)为IIC的数据端,8脚(XCLR)为主清除信号输入端,低电平有效,用来复位BMP085和初始化寄存器和控制器,在不用的情况下可以空置。
BMP085的工作电压为1.8V~3.6V,典型工作电压为2.5V,其与单片机相连的典型电路如下图所示。
从上图中可以看到,BMP085内包含有电阻式压力传感器、AD转换器和控制单元,其中控制单元包括了EEPROM和IIC接口。
读取BMP085时会直接传送没有经过补偿的温度值和压力值。
而在EEPROM中则储存了176位单独的校准数据,这些数据将对读取的温度压力值进行补偿。
176位的EEPROM被划分为11个字,每个字16位,这样就包含有11个校准系数。
每个器件模块都有自己单独的校准系数,在第一次计算温度压力数据之前,单片机就应该先读出读出EEPROM中的这些校准数据,然后再开始采集数据温度和压力数据。
和所有的IIC总线器件一样,BMP085也有一个器件的固定地址,根据其数据手册,出厂时默认BMP085的从机地址为0xEE(写入方向),或0xEF(读出方向)。
温度数据UT和压力数据UP都存储在寄存器的第0到15位之中,压力数据UP的精度还可扩展至16~19位。
上图中左边是Bosch公司技术手册上提供的读取顺序的流程图,右边是EEPROM中的校准数据。
从流程图中可以看出,单片机发送开始信号启动温度和压力测量,经过一定的转换时间(4.5ms)后,从IIC接口读出结果。
为了将温度的单位换算成℃和将压力的单位换算成hPa,需要用到EEPROM中的校准数据来进行补偿计算,这些数据也可以从IIC接口读出。
事实上,EEPROM中的这些校准数据应该在程序初始化的时候就读出,以方便后面的计算。
在同一个采样周期中BMP085可以采128次压力值和1次温度值,并且这些值在读取后会被及时更新掉。
若不想等待到最大转化时间之后才读取数据,可以有效利用BMP085的输出管脚EOC来检查转化是否完毕。
若为1表示转换完成,为0表示转换正在进行中。
要得到温度或气压的值,必须要访问地址为0xF4的控制寄存器。
它根据写入数据的不同,回应的值也不一样,具体如下表所示。
从图中可以看出,要获得温度数据,必须先向控制寄存器(地址0xF4)写0x2E,然后等待至少4.5ms,才可以从地址0xF6和0xF7读取十六位的温度数据。
同样,要获得气压数据,必须先向控制寄存器(地址0xF4)写0x34,然后等待至少4.5ms,才可以从地址0xF6和0xF7读取16位的气压数据,若要扩展分辨率,还可继续读取0xF8(XLSB)扩展16位数据到19位。
获取到的数据还要根据EEPROM中的校准数据来进行补偿后才能用,EEPROM的数据读取可根据上图中的地址来进行,地址从0xAA~0xBF,具体的补偿算法可参看官方的数据手册,这里就不赘述了。
下面以一个例子来看一下BMP085的具体应用。
例子:
利用单片机读取来自BMP085的温度和气压数据,并把它们通过LCD1602显示出来。
BMP085的SDA、SCL端分别接到ATMega16的TWI端(PC1、PC0),EOC和XCLR端悬空,LCD1602的接法与前面的一致。
参考代码如下。
#include
//=========================定义从器件地址和读写方式=============================
#definerd_device_add0xef//即11101111,1110111是BMP085器件的固定地址,最后的1表示对从器件进行读操作
#definewr_device_add0xee//即11101110,1110111是BMP085器件的固定地址,最后的0表示对从器件时行写操作
//===============================TWI状态定义==================================
#defineSTART0x08
#defineRE_START0x10
#defineMT_SLA_ACK0x18
#defineMT_SLA_NOACK0x20
#defineMT_DATA_ACK0x28
#defineMT_DATA_NOACK0x30
#defineMR_SLA_ACK0x40
#defineMR_SLA_NOACK0x48
#defineMR_DATA_ACK0x50
#defineMR_DATA_NOACK0x58
//=============================常用TWI操作定义================================
#defineStart()(TWCR=(1< #defineStop()(TWCR=(1< #defineWait(){while(! (TWCR&(1< #defineTestAck()(TWSR&0xf8) #defineSetAck()(TWCR|=(1< #defineSetNoAck()(TWCR&=~(1< #defineTwi()(TWCR=(1< #defineWrite8Bit(x){TWDR=(x);TWCR=(1< //============引脚电平的宏定义=============== #defineLCM_RS_1PORTB_Bit0=1//RS脚输出高电平 #defineLCM_RS_0PORTB_Bit0=0//RS脚输出低电平 #defineLCM_RW_1PORTB_Bit1=1//RW脚输出高电平 #defineLCM_RW_0PORTB_Bit1=0//RW脚输出低电平 #defineLCM_EN_1PORTB_Bit2=1//EN脚输出高电平 #defineLCM_EN_0PORTB_Bit2=0//EN脚输出低电平 #defineDataPortPORTA//PORTA为数据端口 #defineBusy0x80//忙信号 //==============定义全局变量================ unsignedcharge,shi,bai,qian,wan,shiwan;//显示变量 unsignedcharReadTemp[2];//接收到的温度数据缓冲区 unsignedcharReadPressure[2];//接收到的气压数据缓冲区 intac1; intac2; intac3; unsignedintac4; unsignedintac5; unsignedintac6; intb1; intb2; intmb; intmc; intmd; //==============定义显示字符串================ constunsignedcharstr0[]={"T: .C"};//显示温度 constunsignedcharstr1[]={"P: .Kpa"};//显示气压 //===============1mS延时=================== voiddelay_1ms(void) { unsignedinti; for(i=1;i<(unsignedint)(8*143-2);i++) ; } //=============n*1mS延时=============== voiddelay_nms(unsignedintn) { unsignedinti=0; while(i {delay_1ms(); i++; } } //===============IIC总线写n个字节(成功返回0,失败返回1)===================== unsignedcharI2C_Write(unsignedcharRomAddress,unsignedchar*buf,unsignedcharlen) { unsignedchari; Start();//启动I2C总线 Wait();//等待回应 if(TestAck()! =START) return1;//若回应的不是启动信号,则失败返回1 Write8Bit(wr_device_add);//写I2C从器件地址、写方向 Wait();//等待回应 if(TestAck()! =MT_SLA_ACK) return1;//若回应的不是ACK信号,则失败返回值1 Write8Bit(RomAddress);//写BMP085的ROM地址 Wait();//等待回应 if(TestAck()! =MT_DATA_ACK) return1;//若回应的不是ACK信号则失败返回值1 for(i=0;i { Write8Bit(buf[i]);//写数据到BMP085的ROM中 Wait();//等待回应 if(TestAck()! =MT_DATA_ACK) {return1;}//若回应的不是ACK信号则失败返回值1 delay_nms(10); } Stop();//停止I2C总线 delay_nms(10);//延时等待BMP085写完 return0;//写入成功,返回值0 } //====================IIC总线读n个字节(成功返回0,失败返回1)========================= unsignedcharI2C_Read(unsignedcharRomAddress,unsignedchar*buf,unsignedcharlen) { unsignedchari; Start();//启动I2C总线 Wait();//等待回应 if(TestAck()! =START) return1;//若回应的不是启动信号,则失败返回1 Write8Bit(wr_device_add);//写I2C从器件地址、写方向 Wait();//等待回应 if(TestAck()! =MT_SLA_ACK) return1;//若回应的不是ACK信号,则失败返回值1 Write8Bit(RomAddress);//写BMP085的ROM地址 Wait();//等待回应 if(TestAck()! =MT_DATA_ACK) return1;//若回应的不是ACK信号,则失败返回值1 Start();//重新启动I2C总线 Wait();//等待回应 if(TestAck()! =RE_START) return1;//若回应的不是重复启动信号,则失败返回1 Write8Bit(rd_device_add);//写I2C从器件地址、读方向 Wait();//等待回应 if(TestAck()! =MR_SLA_ACK) return1;//若回应的不是ACK信号,则失败返回值1 for(i=0;i { Twi();//启动I2C读方式 SetAck();//设置接收自动应答 delay_nms(10); Wait();//等待回应 delay_nms(10); *(buf+i)=TWDR;//把连续读取的len个字节数据依次存入对应的地址单元(数组)中 } SetNoAck();//读数据的最后一位后紧跟的是无应答 delay_nms(10); Stop();//停止I2C总线 return0;//成功返回值0 } //================检测LCD忙信号子函数================ voidWaitForEnable(void) { unsignedcharval; DataPort=0xff;//数据线电平拉高 LCM_RS_0;//选择指令寄存器 LCM_RW_1;//选择写方式 __asm("NOP");//调用汇编指令延时一个空指令周期,等待稳定 LCM_EN_1;//使能端拉高电平 __asm("NOP"); __asm("NOP");//调用汇编指令延时两个空指令周期,等待稳定 DDRA=0x00;//改变数据线方向成输入 val=PINA;//读取数据 while(val&Busy) val=PINA;//当DB7位为1时表示忙,循环检测 LCM_EN_0;//忙信号结束,拉低使能端电平 DDRA=0xff;//改变数据线方向成输出 } //================写数据到LCD子函数================= voidLcdWriteData(unsignedchardataW)//写数据dataW到LCD中 { WaitForEnable();//检测忙信号 LCM_RS_1;//选择数据寄存器 LCM_RW_0;//选择读方式 __asm("NOP");//调用汇编指令延时一个空指令周期,等待稳定 DataPort=dataW;//把显示数据送到数据线上 __asm("NOP");//调用汇编指令延时一个空指令周期,等待稳定 LCM_EN_1;//使能端拉高电平 __asm("NOP"); __asm("NOP");//调用汇编指令延时两个空指令周期,等待稳定 LCM_EN_0;//拉低使能端,执行写入动作 } //================写命令到LCD子函数================ voidLcdWriteCommand(unsignedcharCMD,unsignedcharAttribc)//写命令CMD到LCD中,Arribc为1时检测忙信号,否则不检测 { if(Attribc) WaitForEnable();//检测忙信号 LCM_RS_0;//选择指令寄存器 LCM_RW_0;//选择写方式 __asm("NOP");//调用汇编指令延时一个空指令周期,等待稳定 DataPort=CMD;//把命令数据送到数据线上 __asm("NOP");//调用汇编指令延时一个空指令周期,等待稳定 LCM_EN_1;//使能端拉高电平 __asm("NOP"); __asm("NOP");//调用汇编指令延时两个空指令周期,等待稳定 LCM_EN_0;//拉低使能端,执行写入动作 } //================显示光标定位子函数================ voidLocateXY(charposx,charposy)//定位位置到地址x列y行 { unsignedchartemp; temp=posx&0x0f;//屏蔽高4位,限定x坐标的范围为0~15 posy&=0x01;//屏蔽高7位,限定y坐标的范围为0~1 if(posy) temp|=0x40;//若要显示的是第二行,则地址码+0x40,因为第二行起始地址为0x40 temp|=0x80;//指令码为地址码+0x80,因为写DDRAM时DB7恒为1(即0x80) LcdWriteCommand(temp,1);//把temp写入LCD中,检测忙信号 } //===========显示指定座标的一个字符子函数============ voidDisplayOneChar(unsignedcharx,unsignedchary,unsignedcharWdata)//在x列y行处显示变量Wdata中的一个字符 { LocateXY(x,y);//定位要显示的位置 LcdWriteData(Wdata);//将要显示的数据Wdata写入LCD } //==========显示指定座标的一串字符子函数=========== voidePutstr(unsignedcharx,unsignedchary,unsignedcharconst*ptr)//在x列y行处显示ptr指向的字符串 { unsignedchari,j=0; while(ptr[j]>31) j++;//ptr[j]>31时为ASCII码,j累加,计算出字符串长度 for(i=0;i { DisplayOneChar(x++,y,ptr[i]);//显示单个字符,同时x坐标递增 if(x==16) { x=0; y^=1;//当每行显示超过16个字符时换行继续显示 } } } //==================LCD初始化子函数================== voidInitLcd(void) { LcdWriteCommand(0x38,0);//8位数据方式,双行显示,5X7字形,不检测忙信号 delay_nms(5);//延时5ms LcdWriteCommand(0x38,0); delay_nms(5); LcdWriteCommand(0x38,0); delay_nms(5);//重复三次 LcdWriteCommand(0x38,1);//8位数据方式,双行显示,5X7字形,检测忙信号 LcdWriteCommand(0x08,1);//关闭显示,检测忙信号 LcdWriteCommand(0x01,1);//清屏,检测忙信号 LcdWriteCommand(0x06,1);//显示光标右移设置,检测忙信号 LcdWriteCommand(0x0C,1);//打开显示,光标不显示,不闪烁,检测忙信号 } //==================转换子函数==================== voidconversion(longtemp_data) { shiwan=temp_data/100000+0x30; temp_data=temp_data%100000;//取余运算 wan=temp_data/10000+0x30; temp_data=temp_data%10000;//取余运算 qian=temp_data/1000+0x30; temp_data=temp_data%1000;//取余运算 bai=temp_data/100+0x30; temp_data=temp_data%100;//取余运算 shi=temp_data/10+0x30; temp_data=temp_data%10;//取余运算 ge=temp_data+0x30; } //===================BMP085读温度===================== voidbmp085ReadTemp(void) { unsignedchart=0x2e; I2C_Write(0xf4,&t,1);//向地址0xf4写0x2e,进行温度转换 delay_nms(5);//延时大于4.5ms I2C_Read(0xf6,ReadTemp,2);//从地址0xf6开始读出温度数据并存到数组ReadTemp中,共2个字节 } //===================BMP085读气压===================== voidbmp085ReadPressure(void) { unsignedchart=0x34; I2C_Write(0xf4,&t,1);//向地址0xf4写0x34,进行第一次气压转换 delay_nms(5);//延时大于4.5ms I2C_Read(0xf6,ReadPressure,2);//从地址0xf6开始读出气压数据并存到数组ReadPressure中,共2个字节 } //==================初始化BMP085==================== voidInit_BMP085(void) { unsignedchartemp[2]; I2C_Read(0xaa,temp,2); ac1=(temp[0]<<8)|temp[1]; I2C_Read(0xac,temp,2); ac2=(temp[0]<<8)|temp[1]; I2C_Read(0xae,temp,2); ac3=(temp[0]<<8)|temp[1]; I2C_Read(0xb0,temp,2); ac4=(temp[0]<<8)|temp[1]; I2C_Read(0xb2,temp,2); ac5=(temp[0]<<8)|temp[1]; I2C_Read(0xb4,temp,2); ac6=(temp[0]<<8)|temp[1]; I2C_Read(0xb6,temp,2); b1=(temp[0]<<8)|temp[1]; I2C_Read(0xb8,temp,2); b2=(temp[0]<<8)|temp[1]; I2C_Read(0xba,temp,2); mb=(temp[0]<<8)|temp[1]; I2C_Read(0xbc,temp,2); mc=(temp[0]<<8)|temp[1]
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- bmp085 要点