關於DS18B20溫度感測器的時序詳解及程式碼分析

KYYK發表於2018-06-17

轉自:https://blog.csdn.net/xiaocheng_sky/article/details/50743176

簡要說明測溫工作**:**DS18B20的核心功能是它的直接讀數字的溫度感測器。溫度感測器的精度為使用者可程式設計的9,10,11或12位,分別以0.5℃,0.25℃,0.125℃和0.0625℃增量 

遞增。在上電狀態下預設的精度為12位(所以最後獲取的資料要乘以0.0625得到實際溫度)。DS18B20啟動後保持低功耗等待狀態; 
當需要執行溫度測量(和AD轉換)時,匯流排控制器必須發出[44h]命令。在那之後, 
產生的溫度資料以兩個位元組的形式被儲存到高速暫存器的溫度暫存器中(所以後期獲取資料時,必須連續讀取兩次資料),下面介紹時序及相應程式碼(以12MHz的晶振為例,資料線定義為DQ) 
,其中DS18B20的所有通訊都是以由復位脈衝組成的初始化序列開始的,並採用的是單匯流排協議。 
操作順序:初始化——>寫相應的控制指令(用寫資料函式完成)——>讀取DS18B20所採集到的資料(用讀資料函式完成)———>把採集的資料轉化成實際的溫度。

延時函式: (15+15*z)us 的延時

void delay_us(uint z)
{
    for(z;z>0 ; z--)
    {
        _nop_();    _nop_();
        _nop_();    _nop_();
    }   
    _nop_();    _nop_();
}

*時序圖及程式碼分析如下:*

一、初始化(見下圖)

在初始化序列期間,匯流排控制器拉低匯流排並保持480us(改延時可以在480~960us之間,但需要在480us以內釋放匯流排)以發出一個復位脈 
衝,然後釋放匯流排,進入接收狀態(等待DS18B20應答)。匯流排釋放後,單匯流排由上拉電阻拉到高電平。當DS18B20探測到I/O引腳上的上升沿後,等待15-60us,然後其以拉低匯流排60-240us的方式發出存在脈衝。至此,初始化時序完畢。 
這裡寫圖片描述

初始化程式碼: 
帶返回值,有利於檢驗。

bit DS18B20_init()
{
    bit ack = 1;
    DQ = 0;         //主機拉低匯流排
    delay_us(32);   //延時495us
    DQ = 1//釋放匯流排,同時IO口產生的上升沿能被DS18B20所檢測到
    delay_us(4);    //延時大於60us,確保接下來DS18B20能發出60~240us的存在脈衝應答
    ack = DQ;      //在此60~240us之內DQ被DS18B20所佔用,若存在,則其會傳送一個低電平訊號,DQ被DS18B20拉低,則ack為0,反之為1
    delay_us(15);  //延時達240us,讓DS18B20釋放匯流排
    DQ = 1return(ack);
}

初始化程式碼寫至此,其實我們便可以用數碼管顯示來檢驗初始化是否成功(即DS18B20有應答),數碼管顯示”0“,初始化失敗,顯示”1“,則初始化成功。

二、DS18B20的寫時序(見下圖): 
主機在寫時隙向DS18B20寫入資料,其中分為寫”0”時隙,和寫”1”時隙。匯流排主機使用寫“1”時間隙向DS18B20寫入邏輯1,使用寫“0”時間隙向DS18B20寫入邏輯0.所有的寫時隙必須有最少60us的持續時間,相鄰兩個寫時隙必須要有最少1us的恢復時間。兩種寫時隙都通過主機拉低匯流排產生(見下圖)為了產生寫1時隙。 
在拉低匯流排後主機必須在15μs內釋放匯流排。在匯流排被釋放後,由於上拉電阻將匯流排恢復為高電平。為了產生寫”0”時隙,在拉低匯流排後主機必須繼續拉低匯流排以滿足時隙持續時間的要求(至少60μs)。 
在主機產生寫時隙後,DS18B20會在其後的15~60us的一個時間段內取樣單匯流排(DQ)。在取樣的時間視窗內,如果匯流排為高電平,主機會向DS18B20寫入1;如果匯流排為低電平,主機會向DS18B20寫入0。 
綜上所述,所有的寫時隙必須至少有60us的持續時間。相鄰兩個寫時隙必須要有最少1us的恢復時間。所有的寫時隙(寫0和寫1)都由拉低匯流排產生。

這裡寫圖片描述

DS18B20的寫時序程式碼 
寫位元組函式、由低位至高位,向DS18B20寫入一個位元組的資料。 
無返回值。 
形參byte是待寫入的位元組資料,讀取8次,移位8次,保證每位都傳輸至DQ

void DS18B20_write_byte(uchar byte)
{
    uchar i;
    for(i=0 ; i<8 ; i++)
    {
        DQ = 0;           //拉低匯流排,產生寫時隙
        _nop_();
        _nop_();          //大於1us的延時
        DQ = 1;           //15us之內釋放匯流排
        _nop_();
        _nop_();          //適當延時
        DQ = byte & 0x01; //將位元組低位寫入單匯流排
        delay_us(3);      //在15~60us內等待DS18B20來採集訊號
        DQ = 1//釋放匯流排
        byte >>= 1;       //每次講要讀取的資料位移至最低位,
    }
}

三、DS18B20的讀時序(見下圖) 
主機發起讀時序時,DS18B20僅被用來傳輸資料給控制器。因此,匯流排控制器在發出讀暫存器指令[0xBE]或讀電源模式指令[0xB4]後必須立刻開始讀時序,DS18B20可以提供請求資訊。除此之外,匯流排控制器在發出傳送溫度轉換指令[0x44] (或召回EEPROM指令[0xB8])之後讀時序,詳見DS18B20 的晶片手冊上的功能指令。 
所有讀時序必須最少60us,包括兩個讀週期間至少1us的恢復時間。當匯流排控制器把資料線從高電平拉到低電平時,讀時序開始,資料線必須至少保持1us,然後匯流排被釋放。DS18B20 通過拉高或拉低匯流排上來傳輸”1”或”0”。當傳輸邏輯”0”結束後,匯流排將被釋放,通過上拉電阻回到上升沿狀態。從DS18B20輸出的資料在讀時序的下降沿出現後15us 內有效。因此,匯流排控制器在讀時序開始後必須停止把I/O口驅動為低電15us,以讀取I/O口狀態。

這裡寫圖片描述

DS18B20的讀時序的程式碼 
讀位元組函式、由低位至高位,讀取DS18B20所採集到的資料。 
帶返回值,可結合前面的寫時序,對寫、讀資料函式進行檢驗(後面會提到檢驗過程及效果) 
byte 是讀取到的位元組資料。其中,此函式讀取8次,移位7次(實際移位8次)

uchar DS18B20_read_write()
{
    uchar i;
    uchar byte;         //byte為要接收到的資料
    for(i=0 ; i<8 ; i++)
    {
        DQ = 0;         //產生讀時序
        _nop_();
        _nop_();        //簡單延時
        DQ = 1//釋放匯流排,有從機DS18B20佔用
        byte >>= 1;     //先進行移位
        if(DQ)          //讓DS18B20佔用匯流排,發出採集到的訊號
            byte |= 0x80;  //若DQ=1,則讓當前byte最高位為1,在下次迴圈中移位至次高位,最後達到從低位到高位接收的目的;若DQ=0,則可跳過此語句,直接在下次迴圈對byte進行移位補0。以上操作15us以內完成
        delay_us(3);    //延時60us
        DQ = 1//釋放匯流排
        _nop_(); 
    }
}

下面簡單說說如何檢驗寫、讀時序的程式: 
檢驗寫、讀的程式,本人採用DS18B20中特有的64位光刻ROM儲存器(其中涉及一些指令,具體請見晶片的資料手冊)。資料手冊上說明,“64位光刻ROM的排列是:開始(最低)8位是產品型別標號,對於DS18B20來說都是(28H),接著的48位是該DS18B20自身的序列號,最後8位是前面56位的迴圈冗餘校驗碼(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一個DS18B20都各不相同,這樣就可以實現一根匯流排上掛接多個DS18B20的目的。

這裡寫圖片描述

因為寫函式剛好是從最低位開始讀,所以我們先: 
呼叫函式:DS18B20_write_byte(0xcc); 
接著再呼叫函式:DS18B20_read_byte(); 
用數碼管,或者液晶,將讀函式的返回值顯示出來,正確的顯示應該為:40。 
這樣,我們便能確定我們的寫,讀函式的正誤了。

相關文章