1. 程式人生 > >DS18B20 (by 51微控制器)

DS18B20 (by 51微控制器)

依舊是接著藍橋杯的機會來學習一下DS18B20和單匯流排技術,平臺依舊是IAP15F2K61S2微控制器

DS18B20單線數字溫度計以9位數字量的形式反映器件的溫度值,DS18B20通過一個單線介面傳送或者接受資訊,因此在中央微處理器和DS18B20之間只需要一根連線。下圖為其引腳功能說明:


器件框圖如下所示:


從圖中可以看出,DS18B20主要由三個數字部件構成,分別是64位鐳射ROM,溫度感測器,非易失性溫度報警觸發器TH和TL。

DS18B20所使用的匯流排技術為單匯流排技術,目前微控制器與外設之間進行資料傳輸的序列匯流排主要由SCI,I2C和SPI匯流排,其中SCI匯流排總是以非同步方式進行通訊(一條資料輸入線,一條資料輸出線),而I2C匯流排以同步序列二線方式進行通訊(一條時鐘線,一條資料線),SPI匯流排則以同步序列三線方式進行通訊(一條資料輸入線,一條資料輸出線)。這些匯流排都需要至少兩條或兩條以上的訊號線,而DS18B20使用的單匯流排技術與上述匯流排不同,它採用單條訊號線,既可傳輸時鐘,有可傳輸資料,而且資料傳輸是雙向的,因而這種單匯流排技術具有線路簡單,硬體開銷少,成本低廉,便於匯流排擴充套件和維護等優點。單匯流排適用於單主機系統,能夠控制一個或多個從機裝置。

還是老方法,先對DS18B20進行初始化,然後對DS18B20進行讀寫操作。

首先我們來看看控制DS18B20的指令。

33H-----讀ROM:讀DS18B20溫度感測器ROM中的編碼。

55H-----匹配ROM。發出此命令之後,接著發出64位ROM的編碼,訪問單總線上與該編碼相對應的DS18B20並使之做出響應,為下一步對該DS18B20的讀/寫做準備。

F0H-----搜尋ROM。用於確定掛接在同一總線上DS18B20的個數,識別64位ROM地址,為操作各器件做好準備。

CCH-----跳過ROM。忽略64位ROM地址,直接向DS18B20發溫度變換命令,適用於一個從機工作。

ECH-----告警搜尋命令。執行後只有溫度超過設定值上限或下限晶片才會做出反應。

以上指令是針對總線上掛接多個DS18B20的情況,但如果總線上只掛接了一個DS18B20,就不需要以上ROM指令,直接進行如下的溫度轉換和讀取操作。

44H----溫度轉換。啟動DS18B20進行溫度轉換,12位轉換時長最長為750ms,9位為93.75ms,結果存入內部9位元組的RAM中。

BEH----讀暫存器。讀內部ROM中9位元組的溫度資料。

4EH----寫暫存器。發出向內部RAM的第二三位元組寫上下線溫度資料的命令,緊跟該命令之後,是傳送兩位元組的資料。

48H----複製暫存器。將RAM中第2,3位元組的內容複製到EEPROM中。

B8H----重調EEPROM。將EEPROM中內容恢復到RAM中的第三四位元組。

B4H----讀供電方式。讀DS18B20的供電模式。寄生供電時,DS18B20傳送0;外接電源供電時,DS18B20傳送1。

和DS18B20的任何通訊都需要以初始化序列開始,初始化序列見下圖:


上圖含義如下:

1.先將資料線置高電平1

2.延時(時間要求不嚴格,但儘可能短些)

3.資料線拉到低電平0

4.延時750us(該時間範圍可以在480~960us)

5.資料線拉到高電平1

6.延時等待。如果初始化成功,則在15~60us內產生一個由DS18B20返回的低電平0,據該狀態可以確定它的存在,但是應注意,不能無限地等待,不然會使程式進入死迴圈,所以要進行超時判斷。

7.若CPU讀到資料線上的低電平0後,還有進行延時,其延時的時間從發出高電平算起至少要480us。

8.將資料線再次拉到高電平1後結束。

DS18B20寫資料,時序如下圖所示:


其含義如下:

1.資料線先置低電平0

2.延時確定的時間為15us

3.按從低位到高位的順序傳送資料(一次只發送一位)

4.延時時間為45us

5.將資料線拉到高電平1

6.重複1~5步驟,直到傳送完整個位元組

7.最後將資料線拉高到1

DS18B20讀資料,時序圖如下:


含義如下:

1.將資料線拉高到1

2.延時2us

3.將資料線拉低到0

4.延時6us

5.將資料線拉高到1

6.延時4us

7.讀資料線的狀態得到一個狀態位,並進行資料處理

8.延時30us

9.重複1~7步驟,直到讀取完一個位元組

下面我們一起分析一下藍橋杯官方給出的程式碼,如果鄙生有理解錯的地方,還望各位大牛指點。

首先是初始化函式

bit init_ds18b20(void)
{
  bit initflag = 0;
  DQ = 1;      //首先將資料線置高
  Delay_OneWire(12);  //短暫延時
  DQ = 0;      //將資料線拉到低電平
  Delay_OneWire(80);    //延時在480~960US之間
  DQ = 1;                     //資料線拉回高電平
  Delay_OneWire(10);  // 延時等待
  initflag = DQ;     // initflag等於1初始化失敗
  Delay_OneWire(5);     //最後一個延時
  return initflag;

}

其中的Delay_OneWire()函式如下所示:注意這是一段延時,但是延時t值需要根據你微控制器的一個機器週期時長來確定,否則時序會出錯,即無法讀出溫度值!!!

void Delay_OneWire(unsigned int t)
{
int i;
        while(t--)
{
      for(i=0;i<12;i++);
}
}

//向DS18B20寫一個位元組

void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)    //重複直到傳送完整個位元組
{
DQ = 0;  //資料線首先拉低
DQ = dat&0x01;
Delay_OneWire(5);  //延時45us
DQ = 1;    //將資料線拉回高電平1
dat >>= 1;
}
Delay_OneWire(5);

}

//從DS18B20讀取一個位元組

unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat; 
for(i=0;i<8;i++)    //重複接收直到讀完整個位元組
{
DQ = 0;   //資料線拉低
dat >>= 1;
DQ = 1;   //資料線拉高
if(DQ)
{
dat |= 0x80;
}    
Delay_OneWire(5);
}
return dat;
}

以上就是藍橋杯官方給出的程式碼,下面我給出我根據單匯流排庫寫出的溫度讀取函式:

void Read_tem(void)
{
  unsigned char low,high;
        char temp;
  Init_DS18B20();       
  Write_DS18B20(0xCC);  //忽略64位ROM地址,直接向DS18B20傳送溫度變換命令,適用於一個從機工作
  Write_DS18B20(0x44);   //溫度轉換
  Delay_OneWire(200);


  Init_DS18B20();
  Write_DS18B20(0xCC);   
  Write_DS18B20(0xBE);   //讀取溫度資料


  low = Read_DS18B20();    //低八位
  high = Read_DS18B20();   //高八位
  
  temp = high<<4;           //整合成一個位元組
  temp |= (low>>4);
  
  return temp;
}

至此,DS18B20部分就全部介紹完了,如果有錯誤,希望各位大牛指正。