DS18B20的核心功能是它的直接讀數(shù)字的溫度傳感器。溫度傳感器的精度為用戶(hù)可編程的9,10,11或12位,分別以0.5℃,0.25℃,0.125℃和0.0625℃增量遞增。在上電狀態(tài)下默認(rèn)的精度為12位(所以最后獲取的數(shù)據(jù)要乘以0.0625得到實(shí)際溫度)。DS18B20啟動(dòng)后保持低功耗等待狀態(tài);當(dāng)需要執(zhí)行溫度測(cè)量(和AD轉(zhuǎn)換)時(shí),總線(xiàn)控制器必須發(fā)出[44h]命令。
在那之后,產(chǎn)生的溫度數(shù)據(jù)以?xún)蓚€(gè)字節(jié)的形式被存儲(chǔ)到高速暫存器的溫度寄存器中(所以后期獲取數(shù)據(jù)時(shí),必須連續(xù)讀取兩次數(shù)據(jù)),下面介紹時(shí)序及相應(yīng)代碼(以12MHz的晶振為例,數(shù)據(jù)線(xiàn)定義為DQ),其中DS18B20的所有通信都是以由復(fù)位脈沖組成的初始化序列開(kāi)始的,并采用的是單總線(xiàn)協(xié)議。
操作順序:初始化——》寫(xiě)相應(yīng)的控制指令(用寫(xiě)數(shù)據(jù)函數(shù)完成)——》讀取DS18B20所采集到的數(shù)據(jù)(用讀數(shù)據(jù)函數(shù)完成)———》把采集的數(shù)據(jù)轉(zhuǎn)化成實(shí)際的溫度。
時(shí)序圖及代碼分析如下
一、初始化
在初始化序列期間,總線(xiàn)控制器拉低總線(xiàn)并保持480us(改延時(shí)可以在480~960us之間,但需要在480us以?xún)?nèi)釋放總線(xiàn))以發(fā)出一個(gè)復(fù)位脈
沖,然后釋放總線(xiàn),進(jìn)入接收狀態(tài)(等待DS18B20應(yīng)答)。總線(xiàn)釋放后,單總線(xiàn)由上拉電阻拉到高電平。當(dāng)DS18B20探測(cè)到I/O引腳上的上升沿后,等待15-60us,然后其以拉低總線(xiàn)60-240us的方式發(fā)出存在脈沖。至此,初始化時(shí)序完畢。
初始化代碼,初始化代碼寫(xiě)至此,其實(shí)我們便可以用數(shù)碼管顯示來(lái)檢驗(yàn)初始化是否成功(即DS18B20有應(yīng)答),數(shù)碼管顯示”0“,初始化失敗,顯示”1“,則初始化成功。
bit DS18B20_init()
{
bit ack = 1;
DQ = 0; //主機(jī)拉低總線(xiàn)
delay_us(32); //延時(shí)495us
DQ = 1; //釋放總線(xiàn),同時(shí)IO口產(chǎn)生的上升沿能被DS18B20所檢測(cè)到
delay_us(4); //延時(shí)大于60us,確保接下來(lái)DS18B20能發(fā)出60~240us的存在脈沖應(yīng)答
ack = DQ; //在此60~240us之內(nèi)DQ被DS18B20所占用,若存在,則其會(huì)發(fā)送一個(gè)低電平信號(hào),DQ被DS18B20拉低,則ack為0,反之為1
delay_us(15); //延時(shí)達(dá)240us,讓DS18B20釋放總線(xiàn)
DQ = 1;
return(ack);
}
二、DS18B20的寫(xiě)時(shí)序
主機(jī)在寫(xiě)時(shí)隙向DS18B20寫(xiě)入數(shù)據(jù),其中分為寫(xiě)”0”時(shí)隙,和寫(xiě)”1”時(shí)隙??偩€(xiàn)主機(jī)使用寫(xiě)“1”時(shí)間隙向DS18B20寫(xiě)入邏輯1,使用寫(xiě)“0”時(shí)間隙向DS18B20寫(xiě)入邏輯0.所有的寫(xiě)時(shí)隙必須有最少60us的持續(xù)時(shí)間,相鄰兩個(gè)寫(xiě)時(shí)隙必須要有最少1us的恢復(fù)時(shí)間。兩種寫(xiě)時(shí)隙都通過(guò)主機(jī)拉低總線(xiàn)產(chǎn)生(見(jiàn)下圖)為了產(chǎn)生寫(xiě)1時(shí)隙。
在拉低總線(xiàn)后主機(jī)必須在15μs內(nèi)釋放總線(xiàn)。在總線(xiàn)被釋放后,由于上拉電阻將總線(xiàn)恢復(fù)為高電平。為了產(chǎn)生寫(xiě)”0”時(shí)隙,在拉低總線(xiàn)后主機(jī)必須繼續(xù)拉低總線(xiàn)以滿(mǎn)足時(shí)隙持續(xù)時(shí)間的要求(至少60μs)。
在主機(jī)產(chǎn)生寫(xiě)時(shí)隙后,DS18B20會(huì)在其后的15~60us的一個(gè)時(shí)間段內(nèi)采樣單總線(xiàn)(DQ)。在采樣的時(shí)間窗口內(nèi),如果總線(xiàn)為高電平,主機(jī)會(huì)向DS18B20寫(xiě)入1;如果總線(xiàn)為低電平,主機(jī)會(huì)向DS18B20寫(xiě)入0。
綜上所述,所有的寫(xiě)時(shí)隙必須至少有60us的持續(xù)時(shí)間。相鄰兩個(gè)寫(xiě)時(shí)隙必須要有最少1us的恢復(fù)時(shí)間。所有的寫(xiě)時(shí)隙(寫(xiě)0和寫(xiě)1)都由拉低總線(xiàn)產(chǎn)生。
DS18B20的寫(xiě)時(shí)序代碼 :寫(xiě)字節(jié)函數(shù)、由低位至高位,向DS18B20寫(xiě)入一個(gè)字節(jié)的數(shù)據(jù)。無(wú)返回值,形參byte是待寫(xiě)入的字節(jié)數(shù)據(jù),讀取8次,移位8次,保證每位都傳輸至DQ。
void DS18B20_write_byte(uchar byte)
{
uchar i;
for(i=0 ; i《8 ; i++)
{
DQ = 0; //拉低總線(xiàn),產(chǎn)生寫(xiě)時(shí)隙
_nop_();
_nop_(); //大于1us的延時(shí)
DQ = 1; //15us之內(nèi)釋放總線(xiàn)
_nop_();
_nop_(); //適當(dāng)延時(shí)
DQ = byte & 0x01; //將字節(jié)低位寫(xiě)入單總線(xiàn)
delay_us(3); //在15~60us內(nèi)等待DS18B20來(lái)采集信號(hào)
DQ = 1; //釋放總線(xiàn)
byte 》》= 1; //每次講要讀取的數(shù)據(jù)位移至最低位,
}
}
三、DS18B20的讀時(shí)序
主機(jī)發(fā)起讀時(shí)序時(shí),DS18B20僅被用來(lái)傳輸數(shù)據(jù)給控制器。因此,總線(xiàn)控制器在發(fā)出讀暫存器指令[0xBE]或讀電源模式指令[0xB4]后必須立刻開(kāi)始讀時(shí)序,DS18B20可以提供請(qǐng)求信息。除此之外,總線(xiàn)控制器在發(fā)出發(fā)送溫度轉(zhuǎn)換指令[0x44] (或召回EEPROM指令[0xB8])之后讀時(shí)序,詳見(jiàn)DS18B20 的芯片手冊(cè)上的功能指令。
所有讀時(shí)序必須最少60us,包括兩個(gè)讀周期間至少1us的恢復(fù)時(shí)間。當(dāng)總線(xiàn)控制器把數(shù)據(jù)線(xiàn)從高電平拉到低電平時(shí),讀時(shí)序開(kāi)始,數(shù)據(jù)線(xiàn)必須至少保持1us,然后總線(xiàn)被釋放。DS18B20 通過(guò)拉高或拉低總線(xiàn)上來(lái)傳輸”1”或”0”。當(dāng)傳輸邏輯”0”結(jié)束后,總線(xiàn)將被釋放,通過(guò)上拉電阻回到上升沿狀態(tài)。從DS18B20輸出的數(shù)據(jù)在讀時(shí)序的下降沿出現(xiàn)后15us 內(nèi)有效。因此,總線(xiàn)控制器在讀時(shí)序開(kāi)始后必須停止把I/O口驅(qū)動(dòng)為低電15us,以讀取I/O口狀態(tài)。
DS18B20的讀時(shí)序的代碼 :讀字節(jié)函數(shù)、由低位至高位,讀取DS18B20所采集到的數(shù)據(jù)。帶返回值,可結(jié)合前面的寫(xiě)時(shí)序,對(duì)寫(xiě)、讀數(shù)據(jù)函數(shù)進(jìn)行檢驗(yàn)(后面會(huì)提到檢驗(yàn)過(guò)程及效果)byte 是讀取到的字節(jié)數(shù)據(jù)。其中,此函數(shù)讀取8次,移位7次(實(shí)際移位8次)。
uchar DS18B20_read_write()
{
uchar i;
uchar byte; //byte為要接收到的數(shù)據(jù)
for(i=0 ; i《8 ; i++)
{
DQ = 0; //產(chǎn)生讀時(shí)序
_nop_();
_nop_(); //簡(jiǎn)單延時(shí)
DQ = 1; //釋放總線(xiàn),有從機(jī)DS18B20占用
byte 》》= 1; //先進(jìn)行移位
if(DQ) //讓DS18B20占用總線(xiàn),發(fā)出采集到的信號(hào)
byte |= 0x80; //若DQ=1,則讓當(dāng)前byte最高位為1,在下次循環(huán)中移位至次高位,最后達(dá)到從低位到高位接收的目的;若DQ=0,則可跳過(guò)此語(yǔ)句,直接在下次循環(huán)對(duì)byte進(jìn)行移位補(bǔ)0。以上操作15us以?xún)?nèi)完成
delay_us(3); //延時(shí)60us
DQ = 1; //釋放總線(xiàn)
_nop_();
}
}