在測(cè)量海拔高度時(shí),傳統(tǒng)的做法是通過(guò)測(cè)量某一高度的大氣壓力,再經(jīng)過(guò)換算才能得到高度數(shù)據(jù)。為了測(cè)量大氣壓力,就得用上氣壓傳感器,下面就來(lái)討論一下氣壓傳感器的應(yīng)用。 氣壓傳感器是壓力傳感器中的一種,它專(zhuān)用于測(cè)量氣體的絕對(duì)壓強(qiáng)。目前市場(chǎng)上能見(jiàn)到的氣壓傳感器有很多種,下面就以市場(chǎng)上常見(jiàn)的Bosch公司推出的BMP180來(lái)進(jìn)行討論。BMP180不僅可以實(shí)時(shí)的測(cè)量大氣壓力,還能測(cè)量實(shí)時(shí)溫度。同時(shí)它還具有IIC總線的接口,便于單片機(jī)進(jìn)行訪問(wèn)。另外它的使用也很方便,不需要太多的操作就可讀取到氣壓及測(cè)量數(shù)據(jù)。 BMP180采用強(qiáng)大的8腳陶瓷無(wú)引線芯片承載(LCC)超薄封裝,它性能卓越,內(nèi)置有校準(zhǔn)補(bǔ)償,絕對(duì)精度最低可以達(dá)到0.03hPa(0.25米),并且耗電極低,只有3μA。氣壓測(cè)量范圍從300hPa到1100hPa,換算成高度為海拔9000米到500米。下圖是其封裝外形和引腳排列。 引腳各功能如下:1腳(GND)接電源地,2腳(EOC)為完成轉(zhuǎn)換輸出,3腳(VDDA)為正電源,4腳(VDDD)為數(shù)字正電源,5腳為空,6腳(SCL)為IIC的時(shí)鐘端,7腳(SDA)為IIC的數(shù)據(jù)端,8腳(XCLR)為主清除信號(hào)輸入端,低電平有效,用來(lái)復(fù)位BMP180和初始化寄存器和控制器,在不用的情況下可以空置。 BMP180的工作電壓為1.8V~3.6V,典型工作電壓為2.5V,其與單片機(jī)相連的典型電路如下圖所示。 從上圖中可以看到,BMP180內(nèi)包含有電阻式壓力傳感器、AD轉(zhuǎn)換器和控制單元,其中控制單元包括了EEPROM和IIC接口。讀取BMP180時(shí)會(huì)直接傳送沒(méi)有經(jīng)過(guò)補(bǔ)償?shù)臏囟戎岛蛪毫χ怠6贓EPROM中則儲(chǔ)存了176位單獨(dú)的校準(zhǔn)數(shù)據(jù),這些數(shù)據(jù)將對(duì)讀取的溫度壓力值進(jìn)行補(bǔ)償。176位的EEPROM被劃分為11個(gè)字,每個(gè)字16位,這樣就包含有11個(gè)校準(zhǔn)系數(shù)。每個(gè)器件模塊都有自己?jiǎn)为?dú)的校準(zhǔn)系數(shù),在第一次計(jì)算溫度壓力數(shù)據(jù)之前,單片機(jī)就應(yīng)該先讀出讀出EEPROM中的這些校準(zhǔn)數(shù)據(jù),然后再開(kāi)始采集數(shù)據(jù)溫度和壓力數(shù)據(jù)。 和所有的IIC總線器件一樣,BMP180也有一個(gè)器件的固定地址,根據(jù)其數(shù)據(jù)手冊(cè),出廠時(shí)默認(rèn)BMP180的從機(jī)地址為0xEE(寫(xiě)入方向),或0xEF(讀出方向)。溫度數(shù)據(jù)UT和壓力數(shù)據(jù)UP都存儲(chǔ)在寄存器的第0到15位之中,壓力數(shù)據(jù)UP的精度還可擴(kuò)展至16~19位。
上圖中左邊是Bosch公司技術(shù)手冊(cè)上提供的讀取順序的流程圖,右邊是EEPROM中的校準(zhǔn)數(shù)據(jù)。 從流程圖中可以看出,單片機(jī)發(fā)送開(kāi)始信號(hào)啟動(dòng)溫度和壓力測(cè)量,經(jīng)過(guò)一定的轉(zhuǎn)換時(shí)間(4.5ms)后,從IIC接口讀出結(jié)果。為了將溫度的單位換算成℃和將壓力的單位換算成hPa,需要用到EEPROM中的校準(zhǔn)數(shù)據(jù)來(lái)進(jìn)行補(bǔ)償計(jì)算,這些數(shù)據(jù)也可以從IIC接口讀出。事實(shí)上,EEPROM中的這些校準(zhǔn)數(shù)據(jù)應(yīng)該在程序初始化的時(shí)候就讀出,以方便后面的計(jì)算。 在同一個(gè)采樣周期中BMP180可以采128次壓力值和1次溫度值,并且這些值在讀取后會(huì)被及時(shí)更新掉。若不想等待到最大轉(zhuǎn)化時(shí)間之后才讀取數(shù)據(jù),可以有效利用BMP180的輸出管腳EOC來(lái)檢查轉(zhuǎn)化是否完畢。若為1表示轉(zhuǎn)換完成,為0表示轉(zhuǎn)換正在進(jìn)行中。 要得到溫度或氣壓的值,必須要訪問(wèn)地址為0xF4的控制寄存器。它根據(jù)寫(xiě)入數(shù)據(jù)的不同,回應(yīng)的值也不一樣,具體如下表所示。 從圖中可以看出,要獲得溫度數(shù)據(jù),必須先向控制寄存器(地址0xF4)寫(xiě)0x2E,然后等待至少4.5ms,才可以從地址0xF6和0xF7讀取十六位的溫度數(shù)據(jù)。同樣,要獲得氣壓數(shù)據(jù),必須先向控制寄存器(地址0xF4)寫(xiě)0x34,然后等待至少4.5ms,才可以從地址0xF6和0xF7讀取16位的氣壓數(shù)據(jù),若要擴(kuò)展分辨率,還可繼續(xù)讀取0xF8(XLSB)擴(kuò)展16位數(shù)據(jù)到19位。獲取到的數(shù)據(jù)還要根據(jù)EEPROM中的校準(zhǔn)數(shù)據(jù)來(lái)進(jìn)行補(bǔ)償后才能用,EEPROM的數(shù)據(jù)讀取可根據(jù)上圖中的地址來(lái)進(jìn)行,地址從0xAA~0xBF,具體的補(bǔ)償算法可參看官方的數(shù)據(jù)手冊(cè),這里就不贅述了。 下面以一個(gè)例子來(lái)看一下BMP180的具體應(yīng)用。 例子:利用單片機(jī)讀取來(lái)自BMP180的溫度和氣壓數(shù)據(jù),并把它們通過(guò)LCD1602顯示出來(lái)。 BMP180的SDA、SCL端分別接到ATMega16的TWI端(PC1、PC0),EOC和XCLR端懸空,LCD1602的接法與前面的一致。參考代碼如下。 - #include <iom16.h>
- //=========================定義從器件地址和讀寫(xiě)方式=============================
- #define rd_device_add 0xef //即11101111,1110111是BMP180器件的固定地址,最后的1表示對(duì)從器件進(jìn)行讀操作
- #define wr_device_add 0xee //即11101110,1110111是BMP180器件的固定地址,最后的0表示對(duì)從器件時(shí)行寫(xiě)操作
- //===============================TWI狀態(tài)定義==================================
- #define START 0x08
- #define RE_START 0x10
- #define MT_SLA_ACK 0x18
- #define MT_SLA_NOACK 0x20
- #define MT_DATA_ACK 0x28
- #define MT_DATA_NOACK 0x30
- #define MR_SLA_ACK 0x40
- #define MR_SLA_NOACK 0x48
- #define MR_DATA_ACK 0x50
- #define MR_DATA_NOACK 0x58
- //=============================常用TWI操作定義================================
- #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
- #define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
- #define Wait() {while(!(TWCR&(1<<TWINT)));}
- #define TestAck() (TWSR&0xf8)
- #define SetAck() (TWCR|=(1<<TWEA))
- #define SetNoAck() (TWCR&=~(1<<TWEA))
- #define Twi() (TWCR=(1<<TWINT)|(1<<TWEN))
- #define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
- //============引腳電平的宏定義===============
- #define LCM_RS_1 PORTB_Bit0=1 //RS腳輸出高電平
- #define LCM_RS_0 PORTB_Bit0=0 //RS腳輸出低電平
- #define LCM_RW_1 PORTB_Bit1=1 //RW腳輸出高電平
- #define LCM_RW_0 PORTB_Bit1=0 //RW腳輸出低電平
- #define LCM_EN_1 PORTB_Bit2=1 //EN腳輸出高電平
- #define LCM_EN_0 PORTB_Bit2=0 //EN腳輸出低電平
- #define DataPort PORTA //PORTA為數(shù)據(jù)端口
- #define Busy 0x80 //忙信號(hào)
- //==============定義全局變量================
- unsigned char ge,shi,bai,qian,wan,shiwan; //顯示變量
- unsigned char ReadTemp[2]; //接收到的溫度數(shù)據(jù)緩沖區(qū)
- unsigned char ReadPressure[2]; //接收到的氣壓數(shù)據(jù)緩沖區(qū)
- int ac1;
- int ac2;
- int ac3;
- unsigned int ac4;
- unsigned int ac5;
- unsigned int ac6;
- int b1;
- int b2;
- int mb;
- int mc;
- int md;
- //==============定義顯示字符串================
- const unsigned char str0[]={" T: . C "}; //顯示溫度
- const unsigned char str1[]={" P: . Kpa "}; //顯示氣壓
- //===============1mS延時(shí)===================
- void delay_1ms(void)
- {
- unsigned int i;
- for(i=1;i<(unsigned int)(8*143-2);i++)
- ;
- }
- //=============n*1mS延時(shí)===============
- void delay_nms(unsigned int n)
- {
- unsigned int i=0;
- while(i<n)
- {delay_1ms();
- i++;
- }
- }
- //===============IIC總線寫(xiě)n個(gè)字節(jié)(成功返回0,失敗返回1)=====================
- unsigned char I2C_Write(unsigned char RomAddress,unsigned char *buf,unsigned char len)
- {
- unsigned char i;
- Start(); //啟動(dòng)I2C總線
- Wait(); //等待回應(yīng)
- if(TestAck()!=START)
- return 1; //若回應(yīng)的不是啟動(dòng)信號(hào),則失敗返回1
- Write8Bit(wr_device_add); //寫(xiě)I2C從器件地址、寫(xiě)方向
- Wait(); //等待回應(yīng)
- if(TestAck()!=MT_SLA_ACK)
- return 1; //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
- Write8Bit(RomAddress); //寫(xiě)B(tài)MP180的ROM地址
- Wait(); //等待回應(yīng)
- if(TestAck()!=MT_DATA_ACK)
- return 1; //若回應(yīng)的不是ACK信號(hào)則失敗返回值1
- for(i=0;i<len;i++)
- {
- Write8Bit(buf[i]); //寫(xiě)數(shù)據(jù)到BMP180的ROM中
- Wait(); //等待回應(yīng)
- if(TestAck()!=MT_DATA_ACK)
- {return 1;} //若回應(yīng)的不是ACK信號(hào)則失敗返回值1
- delay_nms(10);
- }
- Stop(); //停止I2C總線
- delay_nms(10); //延時(shí)等待BMP180寫(xiě)完
- return 0; //寫(xiě)入成功,返回值0
- }
- //====================IIC總線讀n個(gè)字節(jié)(成功返回0,失敗返回1)=========================
- unsigned char I2C_Read(unsigned char RomAddress,unsigned char *buf,unsigned char len)
- {
- unsigned char i;
- Start(); //啟動(dòng)I2C總線
- Wait(); //等待回應(yīng)
- if(TestAck()!=START)
- return 1; //若回應(yīng)的不是啟動(dòng)信號(hào),則失敗返回1
- Write8Bit(wr_device_add); //寫(xiě)I2C從器件地址、寫(xiě)方向
- Wait(); //等待回應(yīng)
- if(TestAck()!=MT_SLA_ACK)
- return 1; //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
- Write8Bit(RomAddress); //寫(xiě)B(tài)MP180的ROM地址
- Wait(); //等待回應(yīng)
- if(TestAck()!=MT_DATA_ACK)
- return 1; //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
- Start(); //重新啟動(dòng)I2C總線
- Wait(); //等待回應(yīng)
- if(TestAck()!=RE_START)
- return 1; //若回應(yīng)的不是重復(fù)啟動(dòng)信號(hào),則失敗返回1
- Write8Bit(rd_device_add); //寫(xiě)I2C從器件地址、讀方向
- Wait(); //等待回應(yīng)
- if(TestAck()!=MR_SLA_ACK)
- return 1; //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
- for(i=0;i<len;i++)
- {
- Twi(); //啟動(dòng)I2C讀方式
- SetAck(); //設(shè)置接收自動(dòng)應(yīng)答
- delay_nms(10);
- Wait(); //等待回應(yīng)
- delay_nms(10);
- *(buf+i)=TWDR; //把連續(xù)讀取的len個(gè)字節(jié)數(shù)據(jù)依次存入對(duì)應(yīng)的地址單元(數(shù)組)中
- }
- SetNoAck(); //讀數(shù)據(jù)的最后一位后緊跟的是無(wú)應(yīng)答
- delay_nms(10);
- Stop(); //停止I2C總線
- return 0; //成功返回值0
- }
- //================檢測(cè)LCD忙信號(hào)子函數(shù)================
- void WaitForEnable(void)
- {
- unsigned char val;
- DataPort=0xff; //數(shù)據(jù)線電平拉高
- LCM_RS_0; //選擇指令寄存器
- LCM_RW_1; //選擇寫(xiě)方式
- __asm("NOP"); //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
- LCM_EN_1; //使能端拉高電平
- __asm("NOP");
- __asm("NOP"); //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
- DDRA=0x00; //改變數(shù)據(jù)線方向成輸入
- val=PINA; //讀取數(shù)據(jù)
- while(val&Busy)
- val=PINA; //當(dāng)DB7位為1時(shí)表示忙,循環(huán)檢測(cè)
- LCM_EN_0; //忙信號(hào)結(jié)束,拉低使能端電平
- DDRA=0xff; //改變數(shù)據(jù)線方向成輸出
- }
- //================寫(xiě)數(shù)據(jù)到LCD子函數(shù)=================
- void LcdWriteData(unsigned char dataW) //寫(xiě)數(shù)據(jù)dataW到LCD中
- {
- WaitForEnable(); //檢測(cè)忙信號(hào)
- LCM_RS_1; //選擇數(shù)據(jù)寄存器
- LCM_RW_0; //選擇讀方式
- __asm("NOP"); //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
- DataPort=dataW; //把顯示數(shù)據(jù)送到數(shù)據(jù)線上
- __asm("NOP"); //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
- LCM_EN_1; //使能端拉高電平
- __asm("NOP");
- __asm("NOP"); //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
- LCM_EN_0; //拉低使能端,執(zhí)行寫(xiě)入動(dòng)作
- }
- //================寫(xiě)命令到LCD子函數(shù)================
- void LcdWriteCommand(unsigned char CMD,unsigned char Attribc) //寫(xiě)命令CMD到LCD中,Arribc為1時(shí)檢測(cè)忙信號(hào),否則不檢測(cè)
- {
- if(Attribc)
- WaitForEnable(); //檢測(cè)忙信號(hào)
- LCM_RS_0; //選擇指令寄存器
- LCM_RW_0; //選擇寫(xiě)方式
- __asm("NOP"); //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
- DataPort=CMD; //把命令數(shù)據(jù)送到數(shù)據(jù)線上
- __asm("NOP"); //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
- LCM_EN_1; //使能端拉高電平
- __asm("NOP");
- __asm("NOP"); //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
- LCM_EN_0; //拉低使能端,執(zhí)行寫(xiě)入動(dòng)作
- }
- //================顯示光標(biāo)定位子函數(shù)================
- void LocateXY(char posx,char posy) //定位位置到地址x列y行
- {
- unsigned char temp;
- temp=posx&0x0f; //屏蔽高4位,限定x坐標(biāo)的范圍為0~15
- posy&=0x01; //屏蔽高7位,限定y坐標(biāo)的范圍為0~1
- if(posy)
- temp|=0x40; //若要顯示的是第二行,則地址碼+0x40,因?yàn)榈诙衅鹗嫉刂窞?x40
- temp|=0x80; //指令碼為地址碼+0x80,因?yàn)閷?xiě)DDRAM時(shí)DB7恒為1(即0x80)
- LcdWriteCommand(temp,1); //把temp寫(xiě)入LCD中,檢測(cè)忙信號(hào)
- }
- //===========顯示指定座標(biāo)的一個(gè)字符子函數(shù)============
- void DisplayOneChar(unsigned char x,unsigned char y,unsigned char Wdata) //在x列y行處顯示變量Wdata中的一個(gè)字符
- {
- LocateXY(x,y); //定位要顯示的位置
- LcdWriteData(Wdata); //將要顯示的數(shù)據(jù)Wdata寫(xiě)入LCD
- }
- //==========顯示指定座標(biāo)的一串字符子函數(shù)===========
- void ePutstr(unsigned char x,unsigned char y,unsigned char const *ptr) //在x列y行處顯示ptr指向的字符串
- {
- unsigned char i,j=0;
- while(ptr[j]>31)
- j++; //ptr[j]>31時(shí)為ASCII碼,j累加,計(jì)算出字符串長(zhǎng)度
- for(i=0;i<j;i++)
- {
- DisplayOneChar(x++,y,ptr[i]); //顯示單個(gè)字符,同時(shí)x坐標(biāo)遞增
- if(x==16)
- {
- x=0;
- y^=1; //當(dāng)每行顯示超過(guò)16個(gè)字符時(shí)換行繼續(xù)顯示
- }
- }
- }
- //==================LCD初始化子函數(shù)==================
- void InitLcd(void)
- {
- LcdWriteCommand(0x38,0); //8位數(shù)據(jù)方式,雙行顯示,5X7字形,不檢測(cè)忙信號(hào)
- delay_nms(5); //延時(shí)5ms
- LcdWriteCommand(0x38,0);
- delay_nms(5);
- LcdWriteCommand(0x38,0);
- delay_nms(5); //重復(fù)三次
- LcdWriteCommand(0x38,1); //8位數(shù)據(jù)方式,雙行顯示,5X7字形,檢測(cè)忙信號(hào)
- LcdWriteCommand(0x08,1); //關(guān)閉顯示,檢測(cè)忙信號(hào)
- LcdWriteCommand(0x01,1); //清屏,檢測(cè)忙信號(hào)
- LcdWriteCommand(0x06,1); //顯示光標(biāo)右移設(shè)置,檢測(cè)忙信號(hào)
- LcdWriteCommand(0x0C,1); //打開(kāi)顯示,光標(biāo)不顯示,不閃爍,檢測(cè)忙信號(hào)
- }
- //==================轉(zhuǎn)換子函數(shù)====================
- void conversion(long temp_data)
- {
- shiwan=temp_data/100000+0x30 ;
- temp_data=temp_data%100000; //取余運(yùn)算
- wan=temp_data/10000+0x30 ;
- temp_data=temp_data%10000; //取余運(yùn)算
- qian=temp_data/1000+0x30 ;
- temp_data=temp_data%1000; //取余運(yùn)算
- bai=temp_data/100+0x30 ;
- temp_data=temp_data%100; //取余運(yùn)算
- shi=temp_data/10+0x30 ;
- temp_data=temp_data%10; //取余運(yùn)算
- ge=temp_data+0x30;
- }
- //===================BMP180讀溫度=====================
- void BMP180ReadTemp(void)
- {
- unsigned char t=0x2e;
- I2C_Write(0xf4,&t,1); //向地址0xf4寫(xiě)0x2e,進(jìn)行溫度轉(zhuǎn)換
- delay_nms(5); //延時(shí)大于4.5ms
- I2C_Read(0xf6,ReadTemp,2); //從地址0xf6開(kāi)始讀出溫度數(shù)據(jù)并存到數(shù)組ReadTemp中,共2個(gè)字節(jié)
- }
- //===================BMP180讀氣壓=====================
- void BMP180ReadPressure(void)
- {
- unsigned char t=0x34;
- I2C_Write(0xf4,&t,1); //向地址0xf4寫(xiě)0x34,進(jìn)行第一次氣壓轉(zhuǎn)換
- delay_nms(5); //延時(shí)大于4.5ms
- I2C_Read(0xf6,ReadPressure,2); //從地址0xf6開(kāi)始讀出氣壓數(shù)據(jù)并存到數(shù)組ReadPressure中,共2個(gè)字節(jié)
- }
- //==================初始化BMP180====================
- void Init_BMP180(void)
- {
- unsigned char temp[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];
- I2C_Read(0xbe,temp,2);
- md = (temp[0]<<8)|temp[1]; //連續(xù)讀取EEPROM中的校準(zhǔn)數(shù)據(jù),并存放到相應(yīng)的變量中,以供后面補(bǔ)償使用
- }
- //===================轉(zhuǎn)換子函數(shù)=====================
- void BMP180Convert()
- {
- long ut,up,temperature,pressure; //定義長(zhǎng)整型變量
- long x1, x2, b5, b6, x3, b3, p;
- unsigned long b4, b7; //定義無(wú)符號(hào)長(zhǎng)整型變量
- BMP180ReadTemp(); //讀取溫度
- ut=ReadTemp[0]<<8|ReadTemp[1]; //合成溫度數(shù)據(jù)
- x1=((long)ut-ac6)*ac5>>15; //以下根據(jù)EEPROM中的值對(duì)獲取的溫度數(shù)據(jù)的進(jìn)行補(bǔ)償換算
- x2=((long)mc<<11)/(x1+md);
- b5=x1+x2;
- temperature=(b5+8)>>4;
- conversion(temperature); //調(diào)用溫度顯示轉(zhuǎn)換函數(shù)
- DisplayOneChar(5,0,bai); //顯示溫度十位
- DisplayOneChar(6,0,shi); //顯示溫度個(gè)位
- DisplayOneChar(8,0,ge); //顯示溫度小數(shù)后一位
- BMP180ReadPressure(); //讀取氣壓
- up=ReadPressure[0]<<8|ReadPressure[1]; //合成氣壓數(shù)據(jù)
- up&=0x0000FFFF;
- b6=b5-4000; //以下根據(jù)EEPROM中的值對(duì)獲取的氣壓數(shù)據(jù)的進(jìn)行補(bǔ)償換算
- x1=(b2*(b6*b6>>12))>>11;
- x2=ac2*b6>>11;
- x3=x1+x2;
- b3=(((long)ac1*4+x3)+2)/4;
- x1=ac3*b6>>13;
- x2=(b1*(b6*b6>>12))>>16;
- x3=((x1+x2)+2)>>2;
- b4=(ac4*(unsigned long)(x3+32768))>>15;
- b7=((unsigned long)up-b3)*(50000>>0);
- if(b7<0x80000000)
- p=(b7*2)/b4;
- else
- p=(b7/b4)*2;
- x1=(p>>8)*(p>>8);
- x1=(x1*3038)>>16;
- x2=(-7357*p)>>16;
- pressure=p+((x1+x2+3791)>>4);
- conversion(pressure); //調(diào)用氣壓顯示轉(zhuǎn)換函數(shù)
- DisplayOneChar(4,1,shiwan); //顯示氣壓的百位
- DisplayOneChar(5,1,wan); //顯示氣壓的十位
- DisplayOneChar(6,1,qian); //顯示氣壓的個(gè)位
- DisplayOneChar(8,1,bai); //顯示氣壓小數(shù)后一位
- DisplayOneChar(9,1,shi); //顯示氣壓小數(shù)后二位
- }
- //==================主函數(shù)=====================
- void main(void)
- {
- delay_nms(400); //延時(shí)400ms等待電源穩(wěn)定
- DDRA=0xff;PORTA=0x00;
- DDRB=0xff;PORTB=0x00;
- DDRC=0xff;PORTC=0xff;
- DDRD=0xff;PORTD=0xff; //初始化I/O口
- InitLcd(); //LCD初始化
- Init_BMP180(); //BMP180初始化
- ePutstr(0,0,str0); //顯示溫度
- delay_nms(10);
- DisplayOneChar(10,0,0xdf); //顯示特殊符號(hào)
- delay_nms(10);
- ePutstr(0,1,str1); //顯示氣壓
- while(1)
- {
- BMP180Convert(); //調(diào)用轉(zhuǎn)換
- delay_nms(1000);
- }
- }
復(fù)制代碼 上述程序中,是運(yùn)用延時(shí)來(lái)等待數(shù)據(jù)轉(zhuǎn)換完成的,并沒(méi)使用EOC腳來(lái)檢查轉(zhuǎn)化是否完畢。同時(shí),程序利用EEPROM中的值對(duì)獲取的數(shù)據(jù)進(jìn)行補(bǔ)償換算的方法是直接來(lái)自BMP180的數(shù)據(jù)手冊(cè),若對(duì)換算代碼有問(wèn)題可參看其手冊(cè)。氣壓數(shù)據(jù)采用了常規(guī)的16位數(shù)據(jù),并沒(méi)有擴(kuò)展到19位。另外,由于在程序中大量使用了長(zhǎng)整型數(shù)據(jù)格式,所以在IAR開(kāi)發(fā)環(huán)境中編譯時(shí)仍然要把編譯優(yōu)化選項(xiàng)改成Low或Medium(具體參見(jiàn)第一章),系統(tǒng)才能正常運(yùn)行。若選擇不優(yōu)化(None)時(shí),可能在液晶屏得不到任何顯示。究其原因可能與IAR的編譯環(huán)境有關(guān),這一點(diǎn)要非常注意!!
把程序下載到單片機(jī)中,按要求接好連線,給系統(tǒng)上電,就可以在液晶屏上看到實(shí)時(shí)的溫度和氣壓數(shù)據(jù)了
以上的Word格式文檔51黑下載地址:
BMP180中文資料.doc
(166.5 KB, 下載次數(shù): 59)
2020-4-23 13:49 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|