久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 7607|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

BMP180測(cè)量海拔高度傳感器單片機(jī)程序+資料

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:698437 發(fā)表于 2020-4-23 13:49 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
在測(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的接法與前面的一致。參考代碼如下。
  1. #include <iom16.h>
  2. //=========================定義從器件地址和讀寫(xiě)方式=============================
  3. #define rd_device_add 0xef //即11101111,1110111是BMP180器件的固定地址,最后的1表示對(duì)從器件進(jìn)行讀操作
  4. #define wr_device_add 0xee //即11101110,1110111是BMP180器件的固定地址,最后的0表示對(duì)從器件時(shí)行寫(xiě)操作
  5. //===============================TWI狀態(tài)定義==================================
  6. #define START 0x08
  7. #define RE_START  0x10
  8. #define MT_SLA_ACK  0x18
  9. #define MT_SLA_NOACK  0x20
  10. #define MT_DATA_ACK 0x28
  11. #define MT_DATA_NOACK 0x30
  12. #define MR_SLA_ACK  0x40
  13. #define MR_SLA_NOACK  0x48
  14. #define MR_DATA_ACK 0x50
  15. #define MR_DATA_NOACK 0x58
  16. //=============================常用TWI操作定義================================
  17. #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
  18. #define Stop()  (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
  19. #define Wait()  {while(!(TWCR&(1<<TWINT)));}
  20. #define TestAck() (TWSR&0xf8)
  21. #define SetAck()  (TWCR|=(1<<TWEA))
  22. #define SetNoAck()  (TWCR&=~(1<<TWEA))
  23. #define Twi() (TWCR=(1<<TWINT)|(1<<TWEN))
  24. #define Write8Bit(x)  {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
  25. //============引腳電平的宏定義===============
  26. #define LCM_RS_1 PORTB_Bit0=1     //RS腳輸出高電平
  27. #define LCM_RS_0 PORTB_Bit0=0       //RS腳輸出低電平
  28. #define LCM_RW_1 PORTB_Bit1=1       //RW腳輸出高電平
  29. #define LCM_RW_0 PORTB_Bit1=0       //RW腳輸出低電平
  30. #define LCM_EN_1 PORTB_Bit2=1      //EN腳輸出高電平  
  31. #define LCM_EN_0 PORTB_Bit2=0       //EN腳輸出低電平
  32. #define DataPort PORTA          //PORTA為數(shù)據(jù)端口
  33. #define Busy 0x80         //忙信號(hào)
  34. //==============定義全局變量================
  35. unsigned char ge,shi,bai,qian,wan,shiwan;    //顯示變量
  36. unsigned char ReadTemp[2];                   //接收到的溫度數(shù)據(jù)緩沖區(qū)
  37. unsigned char ReadPressure[2];              //接收到的氣壓數(shù)據(jù)緩沖區(qū)
  38. int ac1;
  39. int ac2;
  40. int ac3;
  41. unsigned int ac4;
  42. unsigned int ac5;
  43. unsigned int ac6;
  44. int b1;
  45. int b2;
  46. int mb;
  47. int mc;
  48. int md;
  49. //==============定義顯示字符串================
  50. const unsigned char str0[]={"  T:   .   C    "};    //顯示溫度
  51. const unsigned char str1[]={"  P:   .   Kpa  "};    //顯示氣壓
  52. //===============1mS延時(shí)===================
  53. void delay_1ms(void)  
  54. {   
  55.   unsigned int i;
  56.   for(i=1;i<(unsigned int)(8*143-2);i++)
  57.     ;
  58. }
  59. //=============n*1mS延時(shí)===============
  60. void delay_nms(unsigned int n)  
  61. {
  62.   unsigned int i=0;
  63.   while(i<n)
  64.    {delay_1ms();
  65.     i++;
  66.    }
  67. }
  68. //===============IIC總線寫(xiě)n個(gè)字節(jié)(成功返回0,失敗返回1)=====================
  69. unsigned char I2C_Write(unsigned char RomAddress,unsigned char *buf,unsigned char len)
  70. {
  71.   unsigned char i;
  72.   Start();                                                  //啟動(dòng)I2C總線
  73.   Wait();                                                   //等待回應(yīng)
  74.   if(TestAck()!=START)                        
  75.     return 1;                                              //若回應(yīng)的不是啟動(dòng)信號(hào),則失敗返回1
  76.   Write8Bit(wr_device_add);                    //寫(xiě)I2C從器件地址、寫(xiě)方向
  77.   Wait();                                                   //等待回應(yīng)
  78.   if(TestAck()!=MT_SLA_ACK)                 
  79.     return 1;                                               //若回應(yīng)的不是ACK信號(hào),則失敗返回值1                                
  80.   Write8Bit(RomAddress);                         //寫(xiě)B(tài)MP180的ROM地址
  81.   Wait();                                                     //等待回應(yīng)
  82.   if(TestAck()!=MT_DATA_ACK)
  83.     return 1;                                                 //若回應(yīng)的不是ACK信號(hào)則失敗返回值1
  84.   for(i=0;i<len;i++)
  85.     {
  86.       Write8Bit(buf[i]);                          //寫(xiě)數(shù)據(jù)到BMP180的ROM中
  87.       Wait();                                                      //等待回應(yīng)
  88.       if(TestAck()!=MT_DATA_ACK)
  89.         {return 1;}                                     //若回應(yīng)的不是ACK信號(hào)則失敗返回值1
  90.       delay_nms(10);
  91.     }
  92.   Stop();                                                      //停止I2C總線
  93.   delay_nms(10);                                          //延時(shí)等待BMP180寫(xiě)完
  94.   return 0;                                                   //寫(xiě)入成功,返回值0
  95. }
  96. //====================IIC總線讀n個(gè)字節(jié)(成功返回0,失敗返回1)=========================
  97. unsigned char I2C_Read(unsigned char RomAddress,unsigned char *buf,unsigned char len)
  98. {
  99.   unsigned char i;
  100.   Start();                                                     //啟動(dòng)I2C總線
  101.   Wait();                                                      //等待回應(yīng)
  102.   if(TestAck()!=START)
  103.     return 1;                                                  //若回應(yīng)的不是啟動(dòng)信號(hào),則失敗返回1
  104.   Write8Bit(wr_device_add);                        //寫(xiě)I2C從器件地址、寫(xiě)方向
  105.   Wait();                                                       //等待回應(yīng)
  106.   if(TestAck()!=MT_SLA_ACK)
  107.     return 1;                                                   //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
  108.   Write8Bit(RomAddress);                             //寫(xiě)B(tài)MP180的ROM地址
  109.   Wait();                                                         //等待回應(yīng)
  110.   if(TestAck()!=MT_DATA_ACK)
  111.     return 1;                                                     //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
  112.   Start();                                                          //重新啟動(dòng)I2C總線
  113.   Wait();                                                           //等待回應(yīng)
  114.   if(TestAck()!=RE_START)
  115.     return 1;                                                      //若回應(yīng)的不是重復(fù)啟動(dòng)信號(hào),則失敗返回1
  116.   Write8Bit(rd_device_add);                            //寫(xiě)I2C從器件地址、讀方向
  117.   Wait();                                                           //等待回應(yīng)
  118.   if(TestAck()!=MR_SLA_ACK)
  119.     return 1;                                                       //若回應(yīng)的不是ACK信號(hào),則失敗返回值1
  120.   for(i=0;i<len;i++)
  121.     {
  122.       Twi();                                                              //啟動(dòng)I2C讀方式
  123.       SetAck();                                           //設(shè)置接收自動(dòng)應(yīng)答
  124.       delay_nms(10);
  125.       Wait();                                                            //等待回應(yīng)
  126.       delay_nms(10);
  127.       *(buf+i)=TWDR;                                  //把連續(xù)讀取的len個(gè)字節(jié)數(shù)據(jù)依次存入對(duì)應(yīng)的地址單元(數(shù)組)中
  128.     }
  129.   SetNoAck();                                         //讀數(shù)據(jù)的最后一位后緊跟的是無(wú)應(yīng)答
  130.   delay_nms(10);
  131.   Stop();                                                            //停止I2C總線
  132.   return 0;                                                    //成功返回值0
  133. }
  134. //================檢測(cè)LCD忙信號(hào)子函數(shù)================
  135. void WaitForEnable(void)
  136. {
  137.     unsigned char val;
  138.     DataPort=0xff;        //數(shù)據(jù)線電平拉高
  139.     LCM_RS_0;             //選擇指令寄存器
  140.     LCM_RW_1;             //選擇寫(xiě)方式
  141.     __asm("NOP");         //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
  142.     LCM_EN_1;             //使能端拉高電平
  143.     __asm("NOP");
  144.     __asm("NOP");         //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
  145.     DDRA=0x00;            //改變數(shù)據(jù)線方向成輸入
  146.     val=PINA;             //讀取數(shù)據(jù)
  147.     while(val&Busy)
  148.       val=PINA;           //當(dāng)DB7位為1時(shí)表示忙,循環(huán)檢測(cè)
  149.     LCM_EN_0;             //忙信號(hào)結(jié)束,拉低使能端電平
  150.     DDRA=0xff;            //改變數(shù)據(jù)線方向成輸出
  151. }
  152. //================寫(xiě)數(shù)據(jù)到LCD子函數(shù)=================
  153. void LcdWriteData(unsigned char dataW)      //寫(xiě)數(shù)據(jù)dataW到LCD中
  154. {
  155.     WaitForEnable();        //檢測(cè)忙信號(hào)
  156.     LCM_RS_1;               //選擇數(shù)據(jù)寄存器   
  157.     LCM_RW_0;               //選擇讀方式
  158.     __asm("NOP");           //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
  159.     DataPort=dataW;         //把顯示數(shù)據(jù)送到數(shù)據(jù)線上
  160.     __asm("NOP");           //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
  161.     LCM_EN_1;               //使能端拉高電平
  162.     __asm("NOP");
  163.     __asm("NOP");           //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
  164.     LCM_EN_0;               //拉低使能端,執(zhí)行寫(xiě)入動(dòng)作
  165. }
  166. //================寫(xiě)命令到LCD子函數(shù)================
  167. void LcdWriteCommand(unsigned char CMD,unsigned char Attribc)   //寫(xiě)命令CMD到LCD中,Arribc為1時(shí)檢測(cè)忙信號(hào),否則不檢測(cè)
  168. {
  169.     if(Attribc)
  170.       WaitForEnable();        //檢測(cè)忙信號(hào)
  171.     LCM_RS_0;                 //選擇指令寄存器
  172.     LCM_RW_0;                 //選擇寫(xiě)方式
  173.     __asm("NOP");             //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定
  174.     DataPort=CMD;             //把命令數(shù)據(jù)送到數(shù)據(jù)線上
  175.     __asm("NOP");             //調(diào)用匯編指令延時(shí)一個(gè)空指令周期,等待穩(wěn)定   
  176.     LCM_EN_1;                 //使能端拉高電平
  177.     __asm("NOP");
  178.     __asm("NOP");             //調(diào)用匯編指令延時(shí)兩個(gè)空指令周期,等待穩(wěn)定
  179.     LCM_EN_0;                 //拉低使能端,執(zhí)行寫(xiě)入動(dòng)作
  180. }
  181. //================顯示光標(biāo)定位子函數(shù)================
  182. void LocateXY(char posx,char posy)      //定位位置到地址x列y行
  183. {
  184.     unsigned char temp;
  185.     temp=posx&0x0f;       //屏蔽高4位,限定x坐標(biāo)的范圍為0~15
  186.     posy&=0x01;           //屏蔽高7位,限定y坐標(biāo)的范圍為0~1
  187.     if(posy)        
  188.       temp|=0x40;         //若要顯示的是第二行,則地址碼+0x40,因?yàn)榈诙衅鹗嫉刂窞?x40
  189.     temp|=0x80;           //指令碼為地址碼+0x80,因?yàn)閷?xiě)DDRAM時(shí)DB7恒為1(即0x80)
  190.     LcdWriteCommand(temp,1);    //把temp寫(xiě)入LCD中,檢測(cè)忙信號(hào)
  191. }
  192. //===========顯示指定座標(biāo)的一個(gè)字符子函數(shù)============
  193. void DisplayOneChar(unsigned char x,unsigned char y,unsigned char Wdata)    //在x列y行處顯示變量Wdata中的一個(gè)字符
  194. {
  195.     LocateXY(x,y);          //定位要顯示的位置
  196.     LcdWriteData(Wdata);    //將要顯示的數(shù)據(jù)Wdata寫(xiě)入LCD
  197. }
  198. //==========顯示指定座標(biāo)的一串字符子函數(shù)===========
  199. void ePutstr(unsigned char x,unsigned char y,unsigned char const *ptr)    //在x列y行處顯示ptr指向的字符串
  200. {
  201.     unsigned char i,j=0;
  202.     while(ptr[j]>31)
  203.       j++;                         //ptr[j]>31時(shí)為ASCII碼,j累加,計(jì)算出字符串長(zhǎng)度
  204.     for(i=0;i<j;i++)
  205.     {
  206.       DisplayOneChar(x++,y,ptr[i]);       //顯示單個(gè)字符,同時(shí)x坐標(biāo)遞增
  207.       if(x==16)
  208.         {
  209.           x=0;
  210.           y^=1;         //當(dāng)每行顯示超過(guò)16個(gè)字符時(shí)換行繼續(xù)顯示
  211.         }
  212.     }
  213. }
  214. //==================LCD初始化子函數(shù)==================
  215. void InitLcd(void)
  216. {
  217.     LcdWriteCommand(0x38,0);      //8位數(shù)據(jù)方式,雙行顯示,5X7字形,不檢測(cè)忙信號(hào)
  218.     delay_nms(5);                          //延時(shí)5ms
  219.     LcdWriteCommand(0x38,0);
  220.     delay_nms(5);
  221.     LcdWriteCommand(0x38,0);
  222.     delay_nms(5);                          //重復(fù)三次
  223.     LcdWriteCommand(0x38,1);      //8位數(shù)據(jù)方式,雙行顯示,5X7字形,檢測(cè)忙信號(hào)
  224.     LcdWriteCommand(0x08,1);      //關(guān)閉顯示,檢測(cè)忙信號(hào)
  225.     LcdWriteCommand(0x01,1);      //清屏,檢測(cè)忙信號(hào)
  226.     LcdWriteCommand(0x06,1);      //顯示光標(biāo)右移設(shè)置,檢測(cè)忙信號(hào)
  227.     LcdWriteCommand(0x0C,1);      //打開(kāi)顯示,光標(biāo)不顯示,不閃爍,檢測(cè)忙信號(hào)
  228. }
  229. //==================轉(zhuǎn)換子函數(shù)====================
  230. void conversion(long temp_data)  
  231. {  
  232.     shiwan=temp_data/100000+0x30 ;
  233.     temp_data=temp_data%100000;   //取余運(yùn)算
  234.     wan=temp_data/10000+0x30 ;
  235.     temp_data=temp_data%10000;   //取余運(yùn)算
  236.     qian=temp_data/1000+0x30 ;
  237.     temp_data=temp_data%1000;    //取余運(yùn)算
  238.     bai=temp_data/100+0x30   ;
  239.     temp_data=temp_data%100;     //取余運(yùn)算
  240.     shi=temp_data/10+0x30    ;
  241.     temp_data=temp_data%10;      //取余運(yùn)算
  242.     ge=temp_data+0x30;  
  243. }
  244. //===================BMP180讀溫度=====================
  245. void BMP180ReadTemp(void)
  246. {
  247.   unsigned char t=0x2e;  
  248.   I2C_Write(0xf4,&t,1);                          //向地址0xf4寫(xiě)0x2e,進(jìn)行溫度轉(zhuǎn)換
  249.   delay_nms(5);                                    //延時(shí)大于4.5ms
  250.   I2C_Read(0xf6,ReadTemp,2);             //從地址0xf6開(kāi)始讀出溫度數(shù)據(jù)并存到數(shù)組ReadTemp中,共2個(gè)字節(jié)
  251. }
  252. //===================BMP180讀氣壓=====================
  253. void BMP180ReadPressure(void)
  254. {
  255.   unsigned char t=0x34;
  256.   I2C_Write(0xf4,&t,1);                             //向地址0xf4寫(xiě)0x34,進(jìn)行第一次氣壓轉(zhuǎn)換
  257.   delay_nms(5);                                      //延時(shí)大于4.5ms
  258.   I2C_Read(0xf6,ReadPressure,2);         //從地址0xf6開(kāi)始讀出氣壓數(shù)據(jù)并存到數(shù)組ReadPressure中,共2個(gè)字節(jié)
  259. }

  260. //==================初始化BMP180====================
  261. void Init_BMP180(void)
  262. {
  263.   unsigned char temp[2];
  264.   I2C_Read(0xaa,temp,2);
  265.   ac1 = (temp[0]<<8)|temp[1];
  266.   I2C_Read(0xac,temp,2);
  267.   ac2 = (temp[0]<<8)|temp[1];
  268.   I2C_Read(0xae,temp,2);
  269.   ac3 = (temp[0]<<8)|temp[1];
  270.   I2C_Read(0xb0,temp,2);
  271.   ac4 = (temp[0]<<8)|temp[1];
  272.   I2C_Read(0xb2,temp,2);
  273.   ac5 = (temp[0]<<8)|temp[1];
  274.   I2C_Read(0xb4,temp,2);
  275.   ac6 = (temp[0]<<8)|temp[1];
  276.   I2C_Read(0xb6,temp,2);
  277.   b1 = (temp[0]<<8)|temp[1];
  278.   I2C_Read(0xb8,temp,2);
  279.   b2 = (temp[0]<<8)|temp[1];
  280.   I2C_Read(0xba,temp,2);
  281.   mb = (temp[0]<<8)|temp[1];
  282.   I2C_Read(0xbc,temp,2);
  283.   mc = (temp[0]<<8)|temp[1];
  284.   I2C_Read(0xbe,temp,2);
  285.   md = (temp[0]<<8)|temp[1];         //連續(xù)讀取EEPROM中的校準(zhǔn)數(shù)據(jù),并存放到相應(yīng)的變量中,以供后面補(bǔ)償使用
  286. }
  287. //===================轉(zhuǎn)換子函數(shù)=====================
  288. void BMP180Convert()
  289. {
  290.   long ut,up,temperature,pressure;    //定義長(zhǎng)整型變量
  291.   long x1, x2, b5, b6, x3, b3, p;
  292.   unsigned long b4, b7;           //定義無(wú)符號(hào)長(zhǎng)整型變量
  293.   BMP180ReadTemp();         //讀取溫度
  294.   ut=ReadTemp[0]<<8|ReadTemp[1];  //合成溫度數(shù)據(jù)
  295.   x1=((long)ut-ac6)*ac5>>15;      //以下根據(jù)EEPROM中的值對(duì)獲取的溫度數(shù)據(jù)的進(jìn)行補(bǔ)償換算
  296.   x2=((long)mc<<11)/(x1+md);
  297.   b5=x1+x2;
  298.   temperature=(b5+8)>>4;      
  299.   conversion(temperature);    //調(diào)用溫度顯示轉(zhuǎn)換函數(shù)
  300.   DisplayOneChar(5,0,bai);    //顯示溫度十位   
  301.   DisplayOneChar(6,0,shi);    //顯示溫度個(gè)位
  302.   DisplayOneChar(8,0,ge);     //顯示溫度小數(shù)后一位

  303.   BMP180ReadPressure();           //讀取氣壓
  304.   up=ReadPressure[0]<<8|ReadPressure[1];  //合成氣壓數(shù)據(jù)
  305.   up&=0x0000FFFF;
  306.   b6=b5-4000;                     //以下根據(jù)EEPROM中的值對(duì)獲取的氣壓數(shù)據(jù)的進(jìn)行補(bǔ)償換算
  307.   x1=(b2*(b6*b6>>12))>>11;
  308.   x2=ac2*b6>>11;
  309.   x3=x1+x2;
  310.   b3=(((long)ac1*4+x3)+2)/4;
  311.   x1=ac3*b6>>13;
  312.   x2=(b1*(b6*b6>>12))>>16;
  313.   x3=((x1+x2)+2)>>2;
  314.   b4=(ac4*(unsigned long)(x3+32768))>>15;
  315.   b7=((unsigned long)up-b3)*(50000>>0);
  316.   if(b7<0x80000000)
  317.     p=(b7*2)/b4;
  318.   else  
  319.     p=(b7/b4)*2;
  320.   x1=(p>>8)*(p>>8);
  321.   x1=(x1*3038)>>16;
  322.   x2=(-7357*p)>>16;
  323.   pressure=p+((x1+x2+3791)>>4);
  324.   conversion(pressure);           //調(diào)用氣壓顯示轉(zhuǎn)換函數(shù)
  325.   DisplayOneChar(4,1,shiwan);     //顯示氣壓的百位
  326.   DisplayOneChar(5,1,wan);        //顯示氣壓的十位
  327.   DisplayOneChar(6,1,qian);       //顯示氣壓的個(gè)位
  328.   DisplayOneChar(8,1,bai);        //顯示氣壓小數(shù)后一位
  329.   DisplayOneChar(9,1,shi);        //顯示氣壓小數(shù)后二位
  330. }
  331. //==================主函數(shù)=====================
  332. void main(void)   
  333. {
  334.   delay_nms(400);                    //延時(shí)400ms等待電源穩(wěn)定
  335.   DDRA=0xff;PORTA=0x00;
  336.   DDRB=0xff;PORTB=0x00;
  337.   DDRC=0xff;PORTC=0xff;
  338.   DDRD=0xff;PORTD=0xff;         //初始化I/O口
  339.   InitLcd();                                 //LCD初始化
  340.   Init_BMP180();            //BMP180初始化
  341.   ePutstr(0,0,str0);        //顯示溫度
  342.   delay_nms(10);
  343.   DisplayOneChar(10,0,0xdf);  //顯示特殊符號(hào)
  344.   delay_nms(10);
  345.   ePutstr(0,1,str1);        //顯示氣壓
  346.   while(1)
  347.   {
  348.     BMP180Convert();        //調(diào)用轉(zhuǎn)換
  349.     delay_nms(1000);
  350.   }
  351. }
復(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)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:738031 發(fā)表于 2020-4-25 21:34 | 只看該作者
謝謝  正需要這個(gè)吶
回復(fù)

使用道具 舉報(bào)

板凳
ID:739196 發(fā)表于 2020-4-27 12:12 來(lái)自手機(jī) | 只看該作者
很好,謝謝樓主
回復(fù)

使用道具 舉報(bào)

地板
ID:749513 發(fā)表于 2020-5-13 21:47 | 只看該作者
謝謝樓主的無(wú)私分享
回復(fù)

使用道具 舉報(bào)

5#
ID:825883 發(fā)表于 2021-5-23 15:56 | 只看該作者
好貼留名。不過(guò)這個(gè)傳感器范圍不滿足需要,500米~9000米,應(yīng)是0米到20000米。
回復(fù)

使用道具 舉報(bào)

6#
ID:934382 發(fā)表于 2021-6-7 23:50 來(lái)自手機(jī) | 只看該作者
感謝樓主,寫(xiě)的很詳細(xì),感謝
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩免费视频 | 久久99精品久久久久久 | 一区二区三区日韩 | 色999视频| 久草在线在线精品观看 | 国产精品久久久久久久久久免费看 | 精品视频一区二区三区四区 | 亚洲天天干| 亚洲欧洲中文日韩 | 91av在线免费看 | 欧美午夜在线 | 伊人成人免费视频 | 超碰欧美 | 精品无码久久久久久久动漫 | www.97国产| 在线观看国产h | 欧美一区二区三区在线观看 | 欧美日韩一卡 | 自拍偷拍小视频 | 亚洲成人免费在线 | 免费一级网站 | 狠狠的操 | 精品国产欧美在线 | av黄色在线观看 | 99精品国产一区二区青青牛奶 | 国产精品一区久久久 | 天天色天天色 | 久久精品99久久 | 国产成人免费在线 | 综合久久综合久久 | 国产精品国产三级国产播12软件 | 56pao在线| www.jizzjizz | 亚洲三区在线观看 | 婷婷在线免费 | 国产精品久久久久久久久污网站 | 婷婷综合五月天 | 国产精品精品视频一区二区三区 | 日日干日日操 | 日韩欧美国产一区二区三区 | 欧美13videosex性极品 |