DS18B20是一種單總線數字溫度傳感器,測試溫度范圍-55℃-125℃,具有體積小,硬件開銷低,抗干擾能力強,精度高的特點。單總線,意味著沒有時鐘線,只有一根通信線。單總線讀寫數據是靠控制起始時間和采樣時間來完成,所以時序要求很嚴格,這也是DS18B20驅動編程的難點。
一.DS18B20溫度傳感器
1.引腳圖
2.DS18B20內部結構圖
主要由2部分組成:64位ROM、9字節暫存器,如圖所示。
(1) 64 位ROM。它的內容是64 位序列號,它可以被看作是該DS18B20 的地址序列碼,其作用是使每個DS18B20 都各不相同,這樣就可以實現一根總線上掛接多個DS18B20 的目的。
(2) 9字節暫存器包含:溫度傳感器、上限觸發TH高溫報警器、下限觸發TL低溫報警器、高速暫存器、8位CRC產生器。
3.64位ROM結構圖
8位CRC:是單總線系列器件的編碼,DS18B20定義為28H。
48位序列號:是一個唯一的序列號。
8位系列碼:由CRC產生器生產,作為ROM中的前56位編碼的校驗碼。
4.9字節暫存器結構圖
以上是內部9 個字節的暫存單元(包括EEPROM)。
字節0~1 是溫度存儲器,用來存儲轉換好的溫度。
字節2~3 是用戶用來設置最高報警和最低報警值。這個可以用軟件來實現。
字節4 是配置寄存器,用來配置轉換精度,讓它工作在9~12 位。
字節5~7 保留位。
字節8 CRC校驗位。是64位ROM中的前56位編碼的校驗碼。由CRC發生器產生。
5.溫度寄存器結構圖
溫度寄存器由兩個字節組成,分為低8位和高8位。一共16位。
其中,第0位到第3位,存儲的是溫度值的小數部分。
第4位到第10位存儲的是溫度值的整數部分。
第11位到第15位為符號位。全0表示是正溫度,全1表示是負溫度。
表格中的數值,如果相應的位為1,表示存在。如果相應的位為0,表示不存在。
6.配置寄存器
精度值:
9-bit 0.5℃
10-bit 0.25℃
11-bit 0.125℃
12-bit 0.0625℃
7.溫度/數據關系
注意:如果溫度是一個負溫度,要將讀到的數據減一再取反
二.單總線協議
1.單總線通信初始化
初始化時序包括:主機發出的復位脈沖和從機發出的應答脈沖。主機通過拉低單總線480-960μs產生復位脈沖;然后由主機釋放總線,并進入接收模式。主機釋放總線時,會產生一由低電平跳變為高電平的上升沿,單總線器件檢測到該上升沿后,延時15~60μs,接著單總線器件通過拉低總線60~240μsμ來產生應答脈沖。主機接收到從機的以應答脈沖后,說明有單總線器件在線,到此初始化完成。然后主機就可以開始對從機進行ROM命令和功能命令操作。
2.位寫入時序
寫時隙:當主機把數據線從邏輯高電平拉到邏輯低電平的時候,寫時間隙開始。有兩種寫時間隙:寫1的時間隙和寫0時間隙。所有寫時間隙必須最少持續60us,包括兩個寫周期間至少1us的恢復時間。DQ引腳上的電平變低后,DS18B20在一個15us到60us的時間窗口內對DQ引腳采樣。如果DQ引腳是高電平,就是寫1,如果DQ引腳是低電平,就是寫0。主機要生成一個寫1時間隙,必須把數據線拉到低電平然后釋放,在寫時間隙開始后的15us內允許數據線拉到高電平。主機要生成一個寫0時間隙,必須把數據線拉到低電平并保持60us。
3.位讀取時序
當主機把總線從高電平拉低,并保持至少1us后釋放總線;并在15us內讀取從DS18B20輸出的數據。
4.DS18B20的ROM操作命令
用途:主要是用于選定在單總線上的DS18B20,分為5個命令
(1).讀出ROM,代碼為33H,用于讀出DS18B20的序列號,即64位激光ROM代碼。
(2).匹配ROM,代碼為55H,用于識別(或選中)某一特定的DS18B20進行操作。
(3).搜索ROM,代碼為F0H,用于確定總線上的節點數以及所有節點的序列號。
(4).跳過ROM,代碼為CCH,當總線僅有一個DS18B20時,不需要匹配 。
(5).報警搜索,代碼為ECH,主要用于鑒別和定位系統中超出程序設定的報警溫度界限的節點。
三.驅動程序
測試平臺:
單片機:STC89C52RC,晶振12MHZ
#include
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^7; //定義數據線
void delay_us(uchar n) //延時約16微妙
{
while(n--);
}
1.初始化
void DS18B20_init()
{
DQ=1;
delay_us(1); //稍作延時
DQ=0;
delay_us(80); //延時480到960us
DQ=1;
i = 0;
while(DQ) //等待DS18B20拉低總線
{
delay_us(100);
i++;
if(i>5)//約等待>5MS
{
return 0;//初始化失敗
}
}
}
2.寫字節
void write_byte(uchar dat) //寫一個字節
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0; //每寫入一位數據之前先把總線拉低1us
_nop_();
DQ=dat&0x01; //取最低位寫入
delay_us(10); //延時68us,持續時間最少60us
DQ=1; //然后釋放總線
dat=dat>>1; //從低位開始寫
}
delay_us(10);
}
3.讀字節
uchar read_byte() //讀一個字節
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
DQ=0; //先將總線拉低1us
_nop_();
DQ=1; //然后釋放總線
_nop_();_nop_();
_nop_();_nop_();
if(DQ) dat=dat|0x80; //每次讀一位
dat=dat>>1; //從最低位開始讀
delay_us(10); //讀取完之后等待48us再接著讀取下一個數
}
return dat;
}
4.讀溫度
uint read_temper ()
{
uchar a,b;
uint t=0;
DS18B20_init();
delay_us(15);
write_byte(0xcc); //跳過ROM操作命令
write_byte(0x44); //發送啟動溫度轉換命令
DS18B20_init();
delay_us(15);
write_byte(0xcc); //跳過ROM操作命令
write_byte(0xbe); //發送讀溫度寄存器命令
a=read_byte(); //先讀低八位
b=read_byte(); //再讀高八位
t=b;
t<<=8; //左移八位
t=t|a; //t為16位的數,使高八位為b的值,低八位為a的值
return t; //返回溫度值
}
5.溫度轉換
uint temper_change()
{
uint temper;
float tp;
temper=read_temper();
if(temper<0) //考慮負溫度的情況
{
temper=temper-1;
temper=~temper;
tp=temper*0.0625; //16位溫度轉換成10進制的溫度
temper=tp*100+0.5; //留兩個小數點,并四舍五入
}
else
{
tp=temper*0.0625; //16位溫度轉換成10進制的溫度
temper=tp*100+0.5; //留兩個小數點,并四舍五入
}
return temper;
}
注意:在主函數中調用temper_change()函數返回的temper即為溫度值。由于單總線對時序要求嚴格,我們的延時函數可能并不適用于你的單片機,所以請根據需要自行進行修改
上一篇:DS18B20溫度傳感器+12864液晶串口顯示
下一篇:最后一頁
推薦閱讀
史海拾趣