色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > PIC16F877A驅(qū)動DS18B20溫度采集芯片

          PIC16F877A驅(qū)動DS18B20溫度采集芯片

          作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
          今天開始驅(qū)動DS18B20溫度采集芯片

          從網(wǎng)上收集的資料

          本文引用地址:http://cafeforensic.com/article/201611/317655.htm

          DS18B20的內(nèi)部結(jié)構(gòu)

          DS18B20內(nèi)部結(jié)構(gòu)主要由四部分組成:64位光刻ROM、溫度傳感器、非揮發(fā)的溫度報警觸發(fā)器TH和TL、配置寄存器。DS18B20的管腳排列如下:

          DQ為數(shù)字信號輸入/輸出端;GND為電源地;VDD為外接供電電源輸入端(在寄生電源接線方式時接地)。

          光刻ROM中的64位序列號是出廠前被光刻好的,它可以看作是該DS18B20的地址序列碼。64位光刻ROM的排列是:開始8位(28H)是產(chǎn)品類型標(biāo)號,接著的48位是該DS18B20自身的序列號,最后8位是前面56位的循環(huán)冗余校驗碼(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一個DS18B20都各不相同,這樣就可以實現(xiàn)一根總線上掛接多個DS18B20的目的。

          DS18B20中的溫度傳感器可完成對溫度的測量,以12位轉(zhuǎn)化為例:用16位符號擴(kuò)展的二進(jìn)制補(bǔ)碼讀數(shù)形式提供,以0.0625℃/LSB形式表達(dá),其中S為符號位。

          這是12位轉(zhuǎn)化后得到的12位數(shù)據(jù),存儲在18B20的兩個8比特的RAM中,二進(jìn)制中的前面5位是符號位,如果測得的溫度大于0,這5位為0,只要將測到的數(shù)值乘于0.0625即可得到實際溫度;如果溫度小于0,這5位為1,測到的數(shù)值需要取反加1再乘于0.0625即可得到實際溫度。

          例如+125℃的數(shù)字輸出為07D0H,+25.0625℃的數(shù)字輸出為0191H,-25.0625℃的數(shù)字輸出為FF6FH,-55℃的數(shù)字輸出為FC90H。

          DS18B20溫度傳感器的存儲器

          DS18B20溫度傳感器的內(nèi)部存儲器包括一個高速暫存RAM和一個非易失性的可電擦除的E2RAM,后者存放高溫度和低溫度觸發(fā)器TH、TL和結(jié)構(gòu)寄存器。

          暫存存儲器包含了8個連續(xù)字節(jié),前兩個字節(jié)是測得的溫度信息,第一個字節(jié)的內(nèi)容是溫度的低八位,第二個字節(jié)是溫度的高八位。第三個和第四個字節(jié)是TH、TL的易失性拷貝,第五個字節(jié)是結(jié)構(gòu)寄存器的易失性拷貝,這三個字節(jié)的內(nèi)容在每一次上電復(fù)位時被刷新。第六、七、八個字節(jié)用于內(nèi)部計算。第九個字節(jié)是冗余檢驗字節(jié)。

          該字節(jié)各位的意義如下:

          TM R1 R0 1 1 1 1 1

          低五位一直都是1 ,TM是測試模式位,用于設(shè)置DS18B20在工作模式還是在測試模式。在DS18B20出廠時該位被設(shè)置為0,用戶不要去改動。R1和R0用來設(shè)置分辨率,如下表所示:(DS18B20出廠時被設(shè)置為12位)

          分辨率設(shè)置表:

          R1R0分辨率溫度最大轉(zhuǎn)換時間
          009位93.75ms
          0110位187.5ms
          1011位375ms
          1112位750ms

          根據(jù)DS18B20的通訊協(xié)議,主機(jī)控制DS18B20完成溫度轉(zhuǎn)換必須經(jīng)過三個步驟:每一次讀寫之前都要對DS18B20進(jìn)行復(fù)位,復(fù)位成功后發(fā)送一條ROM指令,最后發(fā)送RAM指令,這樣才能對DS18B20進(jìn)行預(yù)定的操作。復(fù)位要求主CPU將數(shù)據(jù)線下拉500微秒,然后釋放,DS18B20收到信號后等待16~60微秒左右,后發(fā)出60~240微秒的存在低脈沖,主CPU收到此信號表示復(fù)位成功。

          DS1820使用中注意事項

            DS1820雖然具有測溫系統(tǒng)簡單、測溫精度高、連接方便、占用口線少等優(yōu)點(diǎn),但在實際應(yīng)用中也應(yīng)注意以下幾方面的問題:

            (1)較小的硬件開銷需要相對復(fù)雜的軟件進(jìn)行補(bǔ)償,由于DS1820與微處理器間采用串行數(shù)據(jù)傳送,因此,在對DS1820進(jìn)行讀寫編程時,必須嚴(yán)格的保證讀寫時序,否則將無法讀取測溫結(jié)果。在使用PL/M、C等高級語言進(jìn)行系統(tǒng)程序設(shè)計時,對DS1820操作部分最好采用匯編語言實現(xiàn)。

            (2)在DS1820的有關(guān)資料中均未提及單總線上所掛DS1820數(shù)量問題,容易使人誤認(rèn)為可以掛任意多個DS1820,在實際應(yīng)用中并非如此。當(dāng)單總線上所掛DS1820超過8個時,就需要解決微處理器的總線驅(qū)動問題,這一點(diǎn)在進(jìn)行多點(diǎn)測溫系統(tǒng)設(shè)計時要加以注意。

            (3)連接DS1820的總線電纜是有長度限制的。試驗中,當(dāng)采用普通信號電纜傳輸長度超過50m時,讀取的測溫數(shù)據(jù)將發(fā)生錯誤。當(dāng)將總線電纜改為雙絞線帶屏蔽電纜時,正常通訊距離可達(dá)150m,當(dāng)采用每米絞合次數(shù)更多的雙絞線帶屏蔽電纜時,正常通訊距離進(jìn)一步加長。這種情況主要是由總線分布電容使信號波形產(chǎn)生畸變造成的。因此,在用DS1820進(jìn)行長距離測溫系統(tǒng)設(shè)計時要充分考慮總線分布電容和阻抗匹配問題。

            (4)在DS1820測溫程序設(shè)計中,向DS1820發(fā)出溫度轉(zhuǎn)換命令后,程序總要等待DS1820的返回信號,一旦某個DS1820接觸不好或斷線,當(dāng)程序讀該DS1820時,將沒有返回信號,程序進(jìn)入死循環(huán)。這一點(diǎn)在進(jìn)行DS1820硬件連接和軟件設(shè)計時也要給予一定的重視。

          經(jīng)過1天半的奮戰(zhàn)終于完成了DS18B20組網(wǎng)的驅(qū)動!不過只是兩點(diǎn)的組網(wǎng),不過多點(diǎn)組網(wǎng)應(yīng)該也不存在技術(shù)上難題!

          下面是驅(qū)動程序

          頭文件

          #ifndef DS18B20_H
          #define DS18B20_H
          #include "main.h"
          //define port and port direction registor
          #define Dout RD0
          #define DoutDir TRISD0
          //define command word
          #define ROM_READ 0x33
          #define ROM_MATCH 0x55
          #define ROM_SKIP 0xCC
          #define ROM_SERCH 0xF0
          #define ROM_ALARM 0xEC

          #define MEM_WRITE 0x4E
          #define MEM_READ 0xBE
          #define MEM_COPY 0x48
          #define MEM_CONVERT 0x44
          #define MEM_RECALL 0xB8
          #define POWER_READ 0xB4
          //define function
          void configure_ds18b20(uchar flag) ;//configure the accuration of thermometer
          uchar init_ds18b20() ;//初始化ds18b20
          uchar read_ds18b20() ;//read a byte from ds18b20
          void write_ds18b20(uchar data) ;//write a byte to ds18b20
          void get_sequence(uchar *seq) ;//acquire the rom sequence of ds18b20
          char get_configure() ;//acquire the configuration of accuration of thermometer
          uint get_temp() ;//capture temperature from ds18b20
          float process_temp(uint data) ;//process the return value of the get_temp function

          void start_convert() ;//start thermometer convert
          uint read_temp() ;
          void match_rom(uchar data[8]) ;
          uint test(const uchar *data) ;//read temperature from ds18b20 specified by data
          #endif

          子程序

          #include "ds18b20.h"

          const char crc_code[256]={
          0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
          157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
          35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
          190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
          70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
          219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
          101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
          248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
          140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
          17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
          175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
          50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
          202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
          87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
          233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
          116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
          };
          uchar init_ds18b20()
          {
          uchartemp=0 ;
          DoutDir=0 ;
          Dout=1 ;
          DelayUs(1) ;
          Dout=0 ;
          DelayUs(600) ;
          Dout=1 ;
          DoutDir=1 ;
          while(Dout) ;
          while(!Dout) ///這里使用了超時設(shè)置
          {
          DelayUs(24)
          if(temp==10)
          {
          if(Dout)
          {
          DoutDir=0 ;
          return 1 ;
          }
          else
          {
          return 0 ;
          }
          }
          temp++ ;
          }
          DoutDir=0 ;
          return 1 ;
          }

          uchar read_ds18b20()
          {
          uchar temp,i ;
          temp= 0 ;
          DoutDir=0 ;
          for(i=0;i<8;i++)
          {
          Dout=1 ;
          DelayUs(1) ;
          temp=temp>>1 ;
          Dout=0 ;
          DelayUs(1) ;
          Dout=1 ;
          DoutDir=1 ;
          DelayUs(8) ;
          if(Dout)
          temp=temp|0x80 ;
          DelayUs(60) ;
          DoutDir=0 ;
          }
          Dout=1 ;
          return temp ;
          }

          void write_ds18b20(uchar data)
          {
          uchar temp ,i ;
          DoutDir=0 ;
          for(i=0;i<8;i++)
          {
          temp=data&0x01 ;
          if(temp)
          {
          Dout=0 ;
          DelayUs(2) ;
          Dout=1 ;
          DelayUs(57) ;
          }
          else
          {
          Dout=0 ;
          DelayUs(57) ;
          Dout=1 ;
          DelayUs(2) ;
          }
          data=data>>1 ;
          }
          Dout=1 ;
          }

          uint get_temp()
          {
          uchar th,tl ;
          uint temp ;
          th=0 ;
          tl=0 ;
          init_ds18b20() ;
          write_ds18b20(ROM_SKIP) ;
          write_ds18b20(MEM_CONVERT) ;
          init_ds18b20() ;
          write_ds18b20(ROM_SKIP) ;
          write_ds18b20(MEM_READ) ;
          tl=read_ds18b20() ;
          th=read_ds18b20() ;
          if(!(th&0xf0))
          {
          th=th&07 ;
          temp=th*256+tl ;
          return temp ;
          }
          else
          {th=th&0x07 ;
          temp=th*256+tl ;
          return temp ;
          }
          }

          void get_sequence(uchar *seq)
          {
          uchar i ;
          uchar *temp ;
          temp=seq ;
          init_ds18b20() ;
          write_ds18b20(ROM_READ) ;
          for(i=0;i<8;i++)
          {
          *temp++=read_ds18b20() ;
          }
          return ;
          }

          char get_configure()
          {
          char temp,i ;
          i=0 ;
          init_ds18b20() ;
          write_ds18b20(ROM_SKIP) ;
          write_ds18b20(MEM_READ) ;
          temp=0 ;
          while(++i)
          {
          temp=read_ds18b20() ;
          if(i==5)
          return temp ;
          }
          }

          float process_temp(uint data)
          {
          return data*0.0625 ;
          }

          void configure_ds18b20(uchar flag)
          {
          uchar tmp1,tmp2 ;
          init_ds18b20() ;
          write_ds18b20(ROM_SKIP) ;
          write_ds18b20(MEM_READ) ;
          tmp1=read_ds18b20() ;
          tmp2=read_ds18b20() ;
          tmp1=read_ds18b20() ;//get TH
          tmp2=read_ds18b20() ;//get Tl
          init_ds18b20() ;// reset bus
          write_ds18b20(ROM_SKIP) ;//skip rom
          write_ds18b20(MEM_WRITE) ;//write command
          write_ds18b20(tmp1) ;//
          write_ds18b20(tmp2) ;//
          switch(flag)
          {
          case 0 :
          write_ds18b20(0x1F) ;
          break ;
          case 1 :
          write_ds18b20(0x3F) ;
          break ;
          case 2 :
          write_ds18b20(0x5F) ;
          break ;
          case 3 :
          write_ds18b20(0x7F) ;
          break ;
          default :
          write_ds18b20(0x1F) ;
          break ;
          }
          init_ds18b20() ;//reset bus
          write_ds18b20(ROM_SKIP) ;//skip rom
          write_ds18b20(MEM_COPY) ;//copy ram to eeprom
          write_ds18b20(MEM_RECALL) ;//recopy eeprom to ram
          }

          uchar crc_check(uchar *data)
          {
          uchar temp ,i;
          uchar *p=data ;
          //complement ;
          temp=0 ;
          for(i=0;i<7;i++)
          {
          temp=crc_code[temp^*p] ;
          p++ ;
          }
          if(temp==data[7])
          return 1 ;
          else
          return 0 ;
          }

          void start_convert()
          {
          init_ds18b20() ;
          write_ds18b20(ROM_SKIP) ;
          write_ds18b20(MEM_CONVERT) ;
          }
          uint read_temp()
          {
          uchar tl,th ;
          uint temp ;
          tl=0 ;
          th=0 ;
          //init_ds18b20() ;
          //write_ds18b20(0xcc) ;//note that dont skip rom command here ;
          write_ds18b20(MEM_READ) ;
          tl=read_ds18b20() ;
          th=read_ds18b20() ;
          if(!(th&0xf0))
          {
          th=th&07 ;
          temp=th*256+tl ;
          return temp ;
          }
          else
          {th=th&0x07 ;
          temp=th*256+tl ;
          return temp ;
          }
          }

          void match_rom(uchar data[8])
          {
          //uchar *temp=data ;
          uchar i ;
          init_ds18b20() ;
          write_ds18b20(ROM_MATCH) ;
          for(i=0;i<8;i++)
          write_ds18b20(data[i]) ;
          }

          uint test(const uchar *data)//注意這里一定要用const關(guān)鍵字
          {
          uint temp ;
          uchar t,tl,th;
          tl=0 ;
          th=0 ;
          //start_convert() ;
          init_ds18b20() ;
          write_ds18b20(ROM_MATCH) ;
          for(t=0;t<8;t++)
          {
          write_ds18b20(*data++) ;
          }
          write_ds18b20(MEM_READ) ;
          tl=read_ds18b20() ;
          th=read_ds18b20() ;

          if(!(th&0xf0))
          {
          th=th&07 ;
          temp=th*256+tl ;
          return temp ;
          }
          else
          {th=th&0x07 ;
          temp=th*256+tl ;
          return temp ;
          }
          }

          主程序

          #include
          #include


          #include "main.h"
          #include "t232.h"

          #include "ds18b20.h"
          const uchar rom1[8]={0x28,0x94,0xB8,0x1A,0x02,0x00,0x00,0x6E} ;
          const uchar rom2[8]={0x28,0x4B,0xE6,0x1A,0x02,0x00,0x00,0xB9} ;
          void init_all()
          {
          asm("clrwdt");
          init_232() ;
          }

          void main()
          {
          const char str[]="hello world!" ;
          uchar dat[16],td;
          uint data[2] ;
          init_all() ;
          //get ID of DS18b20
          //init_ds18b20() ;
          //write_ds18b20(0x33) ;
          //for(t=0;t<8;t++)
          //{
          //td=read_ds18b20() ;
          //put_char(td) ;
          //}

          //configure_ds18b20(3) ;//configure the accuration of thermometer
          //td=get_configure() ;
          //put_char(td) ;

          while(1)
          {
          start_convert() ;
          data[0]=test(rom1) ;
          data[1]=test(rom2) ;
          DelayMs(70) ;
          sprintf(dat,"temp1 %d temp2 %d",data[0],data[1]) ;
          send_str(dat) ;
          }
          }
          使用DS18B20中容易出現(xiàn)的問題:

          1、讀出的溫度值不變,可能是硬件方面的問題,使用寄生電源方式很容易出現(xiàn)這種問題!建議使用獨(dú)立電源供電,同時別忘了接4.7K上拉電阻

          2、DS18B20讀寫時序很重要,其實驅(qū)動DS18B20只需要寫好三個函數(shù)就可以了,一個初始化函數(shù),一個讀字節(jié)函數(shù),一個寫字節(jié)函數(shù),如果這兩個函數(shù)驗證通過了,你也就成功了一半了,DS18B20的其他功能均是封裝這3個函數(shù)來實現(xiàn)的!只需要按照功能的使用命令即可!



          評論


          技術(shù)專區(qū)

          關(guān)閉