新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > 初步認識51單片機-2.3單片機控制DS18B20溫度傳感器模塊

初步認識51單片機-2.3單片機控制DS18B20溫度傳感器模塊

作者: 時間:2016-11-21 來源:網絡 收藏
通過前面LCD1602的例子我相信對IO口的控制和延時基本有所了解,下面再來一個例子溫度傳感器,同樣只需要IO口操作和延時。先來個DS18B20溫度傳感器的簡介。既然是溫度傳感器,那么一定有個感知溫度的感應器。這個感應器能把它周圍的溫度直接轉成數字并存儲在scratchpad存儲器中。這個感知溫度和轉換成數字信號的過程我們可以不用理解。我們要做的事情就是讀存儲器的內容及其他一些配置。其原理圖如下:
圖1 DS18B20溫度傳感器概述?

在DS18B20中有一個溫度傳感器(如上圖所示),它能感知周圍環(huán)境溫度,并能將溫度的結果直接轉成數字信號存儲起來。溫度信號轉成數字信號的過程我們可以不用關心。那么數字信號存在哪里了?DS18B20中有一個叫做ScratchPad的存儲器,一共9個字節(jié)(Byte0-Byte8),數字信號就存儲在Byte0_LSM和Byte1_MSB中。其中Byte0為低位,Byte1為高位。事實上,我們的目的就是讀出Byte0和Byte1中存儲的數字信號而已。由此可見,雖然名字是溫度傳感器模塊,但是在我們的思考過程中絲毫不用關心傳感的過程,這一點與前面講到的LCD1602其實是一樣,我們要做的事情只是去讀或者寫。這就是模塊的作用,我們可以把它當作黑盒子,按照它的規(guī)則,只要掌握往里面輸入,它會產出什么就行了,不需要關注中間的過程。我們把Byte0_LSM和Byte1_MSB組合成一個16bit的數字信號,Byte0_LSB為低位,Byte1_MSB為高位,并給它取個名字叫”T-16bit”,如上圖所示。那么如何把這個”T-16bit”的數字信號轉換成溫度呢?從圖中看出,bit11-bit15為S,表示溫度的正負,如果S=0,那么溫度為正,如果S=1那么溫度為負。后面的bit10-bit0,數值每增加一就表示溫度增加0.0625°C,舉個例子: 假如LSB中讀出來的是1100 0011,MSB讀出來的是0000 0110,那么LSB和MSB結合起來”T-16bit”就是0000 0110 1100 0011,高5位為0,表示溫度為正,余下11位bit10-bit0(110 1100 0011=1731),把1731×0.0625=108.1875,那么測量的溫度為+108.1875°C. 如果LSB和MSB結合起來”T-16bit”為1111 1110 1100 0011,那么測量的溫度為-108.1875°C. 在”T-16bit”中,我們也可以這樣理解,bit0位每加1,表示20×0.0625°C,bit1位每變化1表示21×0.0625°C, 依此類推, bit4位每變化1為24×0.0625°C=1°C.

本文引用地址:http://m.butianyuan.cn/article/201611/319544.htm

接著就是Byte2_TH和Byte3_TL報警的功能了,圖中Byte2_TH表示設置的最高溫度,Byte3_TL表示設置的最低溫度。同樣S表示溫度的正負,如果S=0,那么表示正,如果S=1,那么溫度為負。Byte2_TH和Byte3_TL就表示設定溫度的范圍了。注意這里的Byte2_TH與Byte3_TL與”T-16bit”中的bit11到bit4是對應的,如圖中藍色部分所示。前面講了,在”T-16bit”中,bit4每變化1為1°C,因此在Byte2_TH與Byte3_TL中的最低位每變化1,表示溫度變化1°C. 比如Byte2_TH設定為,01111001(十進制為121),首位為0,表示+121°C, Byte3_TL為01001001(十進制為73),首位為0,表示+73°C .因此溫度的設定范圍為:73-121°C. 當”T-16bit”中的溫度高于/等于+121°C,或者低于/等于73°C時,將觸發(fā)報警。

接下來就是溫度采集的精度設置了,如圖中的Byte4_Config所示。bit5和bit6分別為R0和R1,其他幾位是固定的。R0和R1分別可以取0或者1,因此可以組合成4種情況,00/01/10/11,分別對應不同的精度,如下表所示:

Byte5-Byte7未給出,Byte8為CRC用與通信錯誤檢測,我們暫且不用管它,我們先考慮簡單的部分

通過上面的講解,相信對DS18B20有了初步的認識,現在再來談談它與單片機如何溝通的。DS18B20一共三個引腳,兩個電源引腳(電源正負極),一個數據引腳DQ.其結構圖如下所示。黑色殼體朝上,引腳朝下,平面對著自己,左手邊第一個引腳為GND. DS18B20的正負極如果接反,可能會燒掉。

可見單片機與DS18B20的溝通只能靠這一根線了,另外這一根線上可以同時接很多個DS18B20. 那么單片機是如何通過這一根線準確的與多個DS18B20溝通的呢?單片機是不知道DQ線上有沒有DS18B20的,或者有多個,或者有但是壞了。與人的溝通方式一樣,當你不知道屋里情況的時候,會先打個招呼,問下有人沒。同樣,單片機也一樣,先來個初始化,打個招呼,看看DQ線上有沒有18B20。怎么樣打招呼呢,與前面講LCD1602一樣,當然按照DS18B20的規(guī)則。單片機先要把DQ拉低至少480μS, 然后釋放DQ,大約在15-60μS后,如果線上有DS18B20并能正常工作,那么DS18B20將DQ拉低并維持60-240μS. 單片機通過檢查這個信號,從而判斷線上是否有能正常工作的DS18B20,有多少個信號就掛著多少個DS18B20,這個就是DS18B20的規(guī)則,具體如下,

初始化后之后就可以與DS18B20溝通了?線上如果有多個DS18B20,你到底是要與哪個溝通呢?因此溝通之前要先來個確定對象。這里我們取最簡單一個DS18B20,搞懂了一個,自然會做控制多個DS18B20了。我們來看看初始化代碼如何寫,

step1:首先DQ拉低,要維持至少480Us,這里我們取500Us保險一點

step2:釋放總線(DQ=1),大約等待15-60Us后,DS18B20會把DQ拉低。那么這里到底是選15Us,還是60Us?

step3:此時DS18B20把DQ拉低信號(L_DQ)能持續(xù)60-240Us.那么到底選60Us還是240Us?

注意我們這里的目的是要檢測出DS18B20是否拉低DQ的信號(L_DQ)。那么在step2中,釋放總線(DQ=1)后,我們到底要延時多長時間(Tdelay),去讀DQ是否等于0的信號?

我們來個極端假設,最小值和最大值

(1)在step2中, 單片機釋放總線(DQ=1),等待15Us(最小值)后,DS18B20把DQ拉低,在step3中,DQ拉低持續(xù)了60Us(最小值)

在這種情況下,如果Tdelay>75Us,你就不能檢測到L_DQ信號了。因此Tdelay要小于75Us.

(2)在step2中, 單片機釋放總線(DQ=1),等待60Us(最大值)后,DS18B20把DQ拉低,在step3中,DQ拉低持續(xù)了60/240Us(兩種情況)

在這種情況下,如果Tdelay<60Us,你就檢測不到L_DQ信號了。比如你設置Tdelay=50Us然后去讀DQ,此時DQ仍然為1,為什么?因為60Us后

DS18B20才把DQ拉低。因此Tdelay>60Us.

綜上所述,保險時間為:75Us>Tdelay>60Us,代碼如下:

void ds18b20_init(void)

{

DQ=0;//總線拉低

delayUs(240); //延時526Us

DQ=1;//釋放總線

delayUs(28);//延時66Us(60-75Us之間)

if(DQ==0)

{

LED1=0;//(設置一個LED,如果檢測到DQ=0,就把LED1點亮)

}

else

{

LED2=0;

}

delayUs(240);//注意讀完DQ后要繼續(xù)延時480Us

}

DS18B20的ID信號在ROM中,因此這里我們可以跳過讀ROM(Skip ROM[CCh]).

接下來就到了與DS18B20溝通的部分了。DS18B20一上電的時候是鈍態(tài)的,就是說它是被動的,沒有指令它就不干活。所以,單片機給DS18B20的第一個指令就是讓它開始測量溫度(Convert T [44h]). 當DS18B20收到這條指令后干什么呢?這里就要回到前面的我們講的圖1,DS18B20開始感知周圍溫度并把溫度高低轉成數字信號存儲在ScratchPad中的Byte0和Byte1中。從這里我們知道,我們僅僅通過一條指令Convert T,就讓DS18B20開始溫度測量并存儲,至于這個過程怎么發(fā)生的我們并不關心。從這里我們看到,其實控制DS18B20模塊與LCD1602模塊沒有本質上區(qū)別,我們要做的事情僅僅是去讀懂規(guī)則,這些規(guī)則來源與它們的芯片手冊,那么簡單的講就是閱讀理解芯片手冊。這一點其實被很多初學者忽略了,不愿意或者不習慣查看芯片手冊。DS18B20把溫度信號轉成數字信號需要一定的時間,因此在發(fā)布下一條指令前,我們這里需要檢測DS18B20是否仍處于工作之中,如果你想簡化,來個延時也行。轉換完成后,DS18B20又處于鈍態(tài)了,這個轉換過程不是持續(xù)的,因此你想讓它再轉換,那么就必須再發(fā)一次Convert T指令。

那么怎么發(fā)指令呢?這個就涉及到‘DS18B20寫’的部分了。參考數據手冊,找到‘寫時序

首先看單片機如何往DS18B20中寫0和1,

(1)寫0:DQ拉低,維持至少60Us,在大約15-60Us的時候,DS18B20開始接受數據

(2)寫1: DQ拉低,延時2Us,然后釋放DQ,此時,上拉電阻會把DQ拉高,延時至少60Us,在15-60Us的時候,DS18B20開始接受數據

因此寫指令的代碼如下

void ds18b20_com(unsigned char mycom)

{

unsigned char temp;

unsigned char i;

for (i=0;i<8;i++)

{

temp=mycom & 0x01;

if (temp==1)

{

DQ=0;

_nop_();

_nop_();

DQ=1;

delayUs(35);

}

else

{

DQ=0;

delayUs(35);

DQ=1;

}

mycom>>=1;

}

}

所以,如果你要發(fā)指令 ds18b20_com(0xcch)//skip rom,DS18B20就知道了要跳過讀ROM,如果要發(fā)指令Convert T, ds18b20_com(0x44h),DS18B20就開始溫度轉換,并存儲在ScratchPad中的前兩個字節(jié)。

當轉換完成后,數據存儲在Byte0和Byte1中,下面的任務就是去讀Byte0和Byte1了。這里需要注意的是,再單片機每發(fā)一次指令之前都要: 初始化->ROM指令->功能指令。這個是芯片手冊上規(guī)定的。因此在讀Byte0和Byte1之前要再初始化一次,Skip ROM([CCh]), 就可以讀Byte0和Byte1了。之后將Byte0和Byte1合并,然后轉換成溫度就可以了。

現在我們來看看如何讀DS18B20,同樣查看芯片手冊,找到讀的時序圖

DS18B20要把數據發(fā)送給單片機,那么DS18B20怎么知道單片機什么時候開始要數據呢?這里同樣有個規(guī)則,當單片機將DQ拉低,延時1Us,然后釋放DQ。此時,DS18B20就知道了,哦,單片機開始要數據了。如果此時DS18B20要給0,就把DQ拉低,相反,如果要寫1就讓DQ維持高的狀態(tài)。從單片機發(fā)出讀數據信息,DS18B20給數據,單片機采集數據,這個過程要在15Us完成,之后需要延時45Us,為保險,我們這里取65Us。兩個讀之間,至少要有1Us的間隔。因此很容易得出單片機讀DS18B20的代碼:

unsigned int ds18b20_read(void)

{

unsigned char temp1=0;

unsigned int temp2=0;

unsigned int temp=0;

unsigned char i;

for (i=0;i<8;i++)

{

temp1>>=1;

DQ=0;

_nop_();

_nop_();

DQ=1;

if(DQ==1)

temp1 |=0x80;

delayUs(35);

}

for (i=0;i<8;i++)

{

temp2>>=1;

DQ=0;

_nop_();

_nop_();

DQ=1;

if(DQ==1)

temp2 |=0x80;

delayUs(35);

}

temp2 <<=8;

temp=temp1+temp2;

return temp;

}

通過LCD1602和DS18B20兩個例子可以看出,對這兩個模塊的控制,其實只用了單片機的引腳控制和延時程序。重點和難點其實在理解各模塊的控制規(guī)則。其實這些只需要通過仔細閱讀對應的芯片手冊就能找到。而單片機引腳的控制和延時部分與LED的操作并無區(qū)別,難怪有人說,如果你把操作LED的過程真正搞懂了,單片機你就學會了一半。后面我們會反復的使用LED作為例子,講解單片機其它相關內容。



評論


技術專區(qū)

關閉