12.1 DS18B20 簡介
DS18B20 數(shù)字溫度傳感器提供 9-Bit 到 12-Bit 的攝氏溫度測量精度和一個(gè)用戶可編程的非易失性且具有過溫和低溫觸發(fā)報(bào)警的報(bào)警功能。DS18B20 采用的 1-Wire 通信即僅采用一個(gè)數(shù)據(jù)線(以及地)與微控制器進(jìn)行通信。該傳感器的溫度檢測范圍為-55℃ 至 +125℃,并且在溫度范圍超過-10℃ 至 85℃ 之外時(shí)還具有 +-0.5℃ 的精度。此外,DS18B20 可以直接由數(shù)據(jù)線供電而不需要外部電源供電。
每片 DS18B20 都有一個(gè)獨(dú)一無二的 64 位序列號,所以一個(gè) 1-Wire 總線上可連接多個(gè) DS18B20 設(shè)備。因此,在一個(gè)分布式的大環(huán)境里用一個(gè)微控制器控制多個(gè) DS18B20 是非常簡單的。這些特征使得其在 HVAC 環(huán)境控制,在建筑、設(shè)備及機(jī)械的溫度監(jiān)控系統(tǒng),以及溫度過程控制系統(tǒng)中有著很大的優(yōu)勢。DS18B20 數(shù)字溫度傳感器的 3 種封裝圖如下圖所示:
獨(dú)特的 1-Wire 總線接口僅需要一個(gè)管腳來通信,應(yīng)用于溫度控制系統(tǒng),工業(yè)系統(tǒng),民用產(chǎn)品,溫度傳感器,或者任何溫度檢測系統(tǒng)中。RY-51 開發(fā)板根據(jù)數(shù)據(jù)手冊要求,溫度采集模塊電路設(shè)計(jì)如下所示:
其中,Temp 與單片機(jī)的 P2.2 引腳相連接。
DS18B20 是一款直接式數(shù)字溫度傳感器,溫度數(shù)據(jù)格式可設(shè)置為 9、10、11、12 位模式,出廠初始值為 12 為格式。對應(yīng)的最小溫度精度可達(dá)到 0.5℃、0.25℃、0.125℃ 或者 0.0625℃。當(dāng)向 DS18B20 寫入溫度轉(zhuǎn)換字 44H 之后,傳感器內(nèi)部會完成溫度數(shù)據(jù)的采集,并將溫度值以一個(gè) 16 位的有符號數(shù)存儲在 2 個(gè) 8 位的存儲單元中,如下圖所示。
如上圖所示,由兩個(gè)字節(jié)的存儲單元存儲了溫度數(shù)據(jù),高 5 位的 s 表示符號,當(dāng) s=0 時(shí),表示溫度為正。當(dāng) s=1 時(shí),表示溫度為負(fù)值, 并以補(bǔ)碼形式存儲溫度值,溫度值與存儲值轉(zhuǎn)換關(guān)系如圖 12-3 所示。當(dāng)向傳感器寫入讀溫度指令 BEH 后,傳感器會將上面兩個(gè) 8 位存儲單元的內(nèi)容從最低位開始依次輸出。上電后,溫度存儲單元中存儲的初始溫度為 85℃。
12.2 DS18B20 操作指令
我們使用數(shù)字溫度傳感器的最終目的是通過它采集到溫度值,單片機(jī)獲得 DS18B20 溫度值的過程一般遵循以下協(xié)議:傳感器初始化——>ROM 操作命令——> 存儲器操作命令——> 處理數(shù)據(jù)。下面逐一進(jìn)行介紹。
12.2.1 傳感器初始化
單總線上的所有處理均從初始化序列開始。初始化序列由總線主機(jī)發(fā)出一復(fù)位脈沖,當(dāng)傳感器收到復(fù)位脈沖后,會返回存在脈沖,表示總線上存在傳感器并準(zhǔn)備好可以接收由主機(jī)發(fā)來的操作指令。初始化指令如下圖所示,下面我們講解如何來理解這個(gè)圖的時(shí)序,圖中包括四種線型,第一種為粗的實(shí)線表示總線由主機(jī)拉低,第二種為粗的虛線表示總線由 DS18B20 拉低,第三種為粗的實(shí)線虛線交叉表示主機(jī)和 DS18B20 同時(shí)拉低總線,第四種為細(xì)實(shí)線由阻抗拉高,即釋放總線。
下面我們來分析一下初始化的時(shí)序步驟:
- 由主機(jī)也就是單片機(jī)拉低總線引腳,持續(xù)時(shí)間為 480us 到 960us;
- 主機(jī)釋放總線,即單片機(jī)拉高總線引腳,等待 15us 到 60us;
- DS18B20 拉低總線 60us 到 240us,即返回存在脈沖,表示傳感器存在總線上并可接受操作指令了;
- DS18B20 主動釋放總線,總線引腳自動被電阻拉高;
DS18B20 復(fù)位脈沖時(shí)序如下圖:
DS18B20 初始化函數(shù)如下所示:
#include< reg52.h >
#include < intrins.h >
#define uchar unsigned char
#define uint unsigned int
sbit DS18B20 = P2^2; //DS18B20傳感器I/O口定義
void DelayT_10us(uchar count)
{
while(count--)
{ //模擬10us延時(shí)
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void Init_DS18B20(void)
{
//單片機(jī)拉低總線并延時(shí)600us
DS18B20 = 0;
DelayT_10us(50);
//單片機(jī)釋放總線并延時(shí)60us
DS18B20 = 1;
DelayT_10us(6);
//當(dāng)DS18B20返回低電平時(shí),表示總線上存在傳感器
while(!DS18B20);
DelayT_10us(50);
}
如上代碼所示,Init_DS18B20()為初始化函數(shù),DelayT_10us()為 10us 延時(shí)函數(shù)。DS18B20 為自定義的傳感器 I/O 口名稱。首先由單片機(jī)將 I/O 口拉低 500us,滿足 480us 到 960us 持續(xù)時(shí)間要求。然后由單片機(jī)將 I/O 口拉高,即釋放總線,持續(xù)時(shí)間為 60us,而時(shí)序要求里面表示在 15us 到 60us 之內(nèi)傳感器會給出存在信號,為了保證一定能收到存在信號,我們這里延時(shí)最大的 60us。最后一直檢測傳感器是否給出了低電平的存在信號,當(dāng)檢測到存在信號后繼續(xù)延時(shí) 500us。
12.2.2 DS18B20 單 bit 數(shù)據(jù)讀寫操作
對 DS18B20 溫度傳感器而言,需要通過對它寫字節(jié)命令或讀字節(jié)命令來實(shí)現(xiàn)溫度值的傳輸。而作為單總線傳感器,字節(jié)命令都是通過連續(xù)的 8 次單 bit 命令來實(shí)現(xiàn)的,這節(jié)的主要內(nèi)容為,單 bit 數(shù)據(jù)讀寫操作時(shí)序講解。主機(jī)向 DS18B20 寫“0”或“1”時(shí)序如下:
如上所示,圖中左半邊為寫“0”時(shí)序,右邊為寫“1”時(shí)序。如左邊所示,首先將總線拉低持續(xù)時(shí)間最低 60us 最高 120us。傳感器 DS18B20 最快在第 15us 采集總線上的低電平,最典型的時(shí)間為第 30us,最慢也在第 60us 能采集完畢 ,也就是說只要我們保持低電平至少 60us,就能將“0”寫入到傳感器中。與寫“0”類似,當(dāng)要向傳感器寫入“1”的時(shí)候,首先由主機(jī)將總線拉低,持續(xù)時(shí)間大于 1us,隨后立馬將總線拉高,同樣傳感器最快在第 15us 采集總線上的高電平,最典型的時(shí)間為第 30us,最慢也在第 60us 能采集完畢。因此我們將寫“0”和寫“1”整合到一個(gè)函數(shù)中。主機(jī)向 DS18B20 傳感器寫數(shù)據(jù)函數(shù):
void WrByte_18B20(uchar dat)
{
uchar j;
bit flag;
for(j=1;j<=8;j++)
{ //從低到高一次將1Byte數(shù)據(jù)寫入DS18B20
flag = dat&0x01;
dat=dat >>1;
DS18B20 = 0;//拉低總線并延時(shí)2us
_nop_();
_nop_();
DS18B20 = flag;//將要寫的位放到總線
DelayT_10us(6);//延時(shí)60us
DS18B20 = 1;//拉高釋放總線
}
}
單片機(jī)讀 DS18B20 傳感器時(shí)序如下圖所示:
如上圖所示,當(dāng)主機(jī)需要讀取傳感器的“0”時(shí),首先將主機(jī)拉低,并在 15us 之內(nèi)讀取總線值,隨后釋放總線。當(dāng)主機(jī)需要讀取“1”時(shí),首先將主機(jī)拉低,并延時(shí)超過 1us,并在 15us 之內(nèi)讀取總線值,隨后釋放總線。因此我們將讀“0”和寫“1”整合到一個(gè)函數(shù)中,如下主機(jī)讀 DS18B20 函數(shù):
uchar RdByte_18B20(void)
{
uchar dat,flag,j;
for(j=1;j<=8;j++)
{
DS18B20 = 0;//拉低總線并延時(shí)2us
_nop_();
_nop_();
DS18B20 = 1;//拉高釋放總線并延時(shí)2us
_nop_();
_nop_();
flag = DS18B20;//采集
DelayT_10us(6);//延時(shí)60us
//讀出的值最低位在前面
dat=(dat >>1)|(flag< 7);
}
return dat;
}
12.2.3 ROM 操作命令
下面介紹兩個(gè)采集溫度用到的寫入不同的字節(jié)實(shí)現(xiàn)的功能,其他請參考 DS18B20 數(shù)據(jù)手冊。
a) 寫入字節(jié)[CCh]
功能:Skip ROM( 跳過 ROM ),在單點(diǎn)總線系統(tǒng)中,此命令通過允許總線。不給主機(jī)提供 64 位 ROM 編碼而訪問存儲器操作來節(jié)省時(shí)間。如果在總線上存在多于一個(gè)的從屬器件而且在 Skip ROM 命令之后發(fā)出讀命令,那么由于多個(gè)從片同時(shí)發(fā)送數(shù)據(jù),會在總線上發(fā)生數(shù)據(jù)沖突(漏極開路下拉會產(chǎn)生線與的效果)。
b) 寫入字節(jié)[44h]
功能:Convert T(溫度變換),這條命令啟動一次溫度轉(zhuǎn)換而無需其他數(shù)據(jù)。溫度轉(zhuǎn)換命令被執(zhí)行,而后 DS18B20 保持等待狀態(tài)。如果總線控制器在這條命令之后跟著發(fā)出讀時(shí)間隙,而 DS18B20 又忙于做時(shí)間轉(zhuǎn)換的話,DS18B20 將在總線上輸出“0”,若溫度轉(zhuǎn)換完成,則輸出“1”。如果使用寄生電源,總線控制器必須在發(fā)出這條命令后立即起動強(qiáng)上拉,并保持 500ms。
12.2.4 存儲器操作命令
單片機(jī)通過向 DS18B20 寫入相應(yīng)的字節(jié)命令完成對 DS18B20 存儲器中數(shù)據(jù)的讀寫功能。本系統(tǒng)用到的功能為讀取存儲器中的溫度值,寫入字節(jié)[BEh]。
功能為:Read Scratchpad(讀暫存存儲器),這個(gè)命令讀取暫存器的內(nèi)容。讀取將從字節(jié) 0 開始,一直進(jìn)行下去,直到第 9(字節(jié) 8,CRC)字節(jié)讀完。如果不想讀完所有字節(jié),控制器可以在任何時(shí)間發(fā)出復(fù)位命令來中止讀取。讀取的前兩個(gè)字節(jié)為存儲了溫度值。
12.2.5 處理數(shù)據(jù)
溫度存儲于上述的前兩個(gè)字節(jié)中,通過讀取前兩個(gè)字節(jié)便可獲得溫度,兩個(gè)字節(jié)內(nèi)容與實(shí)際溫度值對應(yīng)所示,按照下關(guān)系如圖 12-3 所示,按圖進(jìn)行相應(yīng)的轉(zhuǎn)換即可,另外在上電時(shí)溫度的初始值為 85℃。
根據(jù)前面介紹,溫度采集的步驟總結(jié)如下:
a) 溫度傳感器初始化;
b) 寫入字節(jié)[CCh],跳過 ROM;
c) 寫入字節(jié)[44h],啟動一次溫度轉(zhuǎn)換;
d) 溫度傳感器初始化;
e) 寫入字節(jié)[CCh],跳過 ROM;
f) 寫入字節(jié)[BEh],發(fā)送讀溫度命令;
g) 讀取返回的前兩個(gè)字節(jié),并轉(zhuǎn)化為溫度值。
溫度采集函數(shù)代碼如下:
uint GetT_18B20(void)
{
uchar Temp_L,Temp_H;
uint Temp;
Init_DS18B20(); //初始化
WrByte_18B20(0xCC);//跳過ROM
WrByte_18B20(0x44);//啟動溫度轉(zhuǎn)換
Init_DS18B20(); //初始化
WrByte_18B20(0xCC);//跳過ROM
WrByte_18B20(0xBE);//發(fā)送讀溫度命令
//讀取兩個(gè)字節(jié)的溫度值
Temp_L = RdByte_18B20();
Temp_H = RdByte_18B20();
Temp = ((uint)Temp_H< 8) + Temp_L;//將溫度組合成16變量
return Temp;
}
為了方便后續(xù)使用,我們將與 DS18B20 有關(guān)的函數(shù)都放到“Drive_DS18B20.h”、 “Drive_DS18B20.c”文件中。
“Drive_DS18B20.h”文件代碼如下所示:
#ifndef __18b20_H__
#define __18b20_H__
extern unsigned int GetT_18B20(void);
#endif
“Drive_DS18B20.h”文件代碼如下所示:
#include< reg52.h >
#include < intrins.h >
#define uchar unsigned char
#define uint unsigned int
sbit DS18B20 = P2^2; //DS18B20傳感器I/O口定義
void DelayT_10us(uchar count)
{
while(count--)
{ //模擬10us延時(shí)
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void Init_DS18B20(void)
{
//單片機(jī)拉低總線并延時(shí)600us
DS18B20 = 0;
DelayT_10us(50);
//單片機(jī)釋放總線并延時(shí)60us
DS18B20 = 1;
DelayT_10us(6);
//當(dāng)DS18B20返回低電平時(shí),表示總線上存在傳感器
while(!DS18B20);
DelayT_10us(50);
}
void WrByte_18B20(uchar dat)
{
uchar j;
bit flag;
for(j=1;j<=8;j++)
{ //從低到高一次將1Byte數(shù)據(jù)寫入DS18B20
flag = dat&0x01;
dat=dat >>1;
DS18B20 = 0;//拉低總線并延時(shí)2us
_nop_();
_nop_();
DS18B20 = flag;//將要寫的位放到總線
DelayT_10us(6);//延時(shí)60us
DS18B20 = 1;//拉高釋放總線
}
}
uchar RdByte_18B20(void)
{
uchar dat,flag,j;
for(j=1;j<=8;j++)
{
DS18B20 = 0;//拉低總線并延時(shí)2us
_nop_();
_nop_();
DS18B20 = 1;//拉高釋放總線并延時(shí)2us
_nop_();
_nop_();
flag = DS18B20;//采集
DelayT_10us(6);//延時(shí)60us
//讀出的值最低位在前面
dat=(dat >>1)|(flag< 7);
}
return dat;
}
uint GetT_18B20(void)
{
uchar Temp_L,Temp_H;
uint Temp;
Init_DS18B20(); //初始化
WrByte_18B20(0xCC);//跳過ROM
WrByte_18B20(0x44);//啟動溫度轉(zhuǎn)換
Init_DS18B20(); //初始化
WrByte_18B20(0xCC);//跳過ROM
WrByte_18B20(0xBE);//發(fā)送讀溫度命令
//讀取兩個(gè)字節(jié)的溫度值
Temp_L = RdByte_18B20();
Temp_H = RdByte_18B20();
Temp = ((uint)Temp_H< 8) + Temp_L;//將溫度組合成16變量
return Temp;
}
將上述兩個(gè)文件添加到工程中,主程序文件中調(diào)用函數(shù)便可實(shí)現(xiàn)溫度采集了。
12.3 DS18B20 的應(yīng)用
下面我們講解 DS18B20 的應(yīng)用,要實(shí)現(xiàn)的功能為:單片機(jī)每秒采集一次溫度值,并將溫度值顯示到液晶顯示模塊上。用定時(shí)器中斷來時(shí)實(shí)現(xiàn) 1s 的定時(shí),建立工程,將 1602、18B20 的文件添加到工程中,在主程序中調(diào)用相關(guān)大函數(shù)來實(shí)現(xiàn)顯示和溫度的采集,主程序代碼如下所示:
#include< reg52.h >
#include"Drive_DS18B20.h"
#include"Drive_1602.h"
#define uchar unsigned char
#define uint unsigned int
uint Temp;
uchar str[10]=0;
#define FOSC 11059200 //單片機(jī)晶振頻率
#define T_1ms (65536 - FOSC/12/1000) //定時(shí)器初始值計(jì)算
uint flag = 0;
uint T_count = 0;
uint Sec = 0;
sbit DU = P2^7;//數(shù)碼管段選、位選引腳定義
sbit WE = P2^6;
void main(void)
{
Init_1602();//1602初始化
P0 = 0xff;//關(guān)閉所有數(shù)碼管
WE = 1;
WE = 0;
TMOD = 0x01; //定時(shí)器工作模式配置
TL0 = T_1ms; //裝載初始值
TH0 = T_1ms >>8;
TR0 = 1; //啟動定時(shí)器
ET0 = 1; //允許定時(shí)器中斷
EA = 1; //開總中斷
Disp_1602_str(1,3,"RongYi RY-51");//第1行第3列開始顯示"RongYi RY-51"
while(1)
{
if(T_count >=1000)//1s進(jìn)行一次溫度的采集以及顯示
{
EA=0;//關(guān)閉中斷,防止定時(shí)器中斷影響溫度傳感器的讀寫
T_count =0;
Sec++;
Temp = GetT_18B20(); //采集溫度
str[0] = (Temp >>4)/10 + '0';//左移4位獲得溫度整數(shù)部分
str[1] = (Temp >>4)%10 + '0';
str[2] = '.';
if((Temp >>3)%10)
str[3] = '5';
else
str[3] = '0';
str[4] = '?';
Disp_1602_str(2,3,str);//第2行第3列開始顯示溫度值
EA = 1;//顯示完成后,開總中斷
}
}
}
void timer0() interrupt 1
{
TL0 = T_1ms;//重裝初始值
TH0 = T_1ms >>8;
T_count++;
}
12.4 本章小結(jié)
本章詳細(xì)介紹了DS18B20的工作原理,通信時(shí)序,以及函數(shù)的編寫,后面使用時(shí)只需調(diào)用函數(shù)即可了,無需重復(fù)造輪子咯。
-
傳感器
+關(guān)注
關(guān)注
2551文章
51106瀏覽量
753662 -
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44558瀏覽量
635407 -
DS18B20
+關(guān)注
關(guān)注
10文章
779瀏覽量
80873 -
數(shù)字溫度傳感器
+關(guān)注
關(guān)注
0文章
188瀏覽量
15454
發(fā)布評論請先 登錄
相關(guān)推薦
評論