51單片機溫度傳感器DS18B20
實現(xiàn)功能
插上DS18B20溫度傳感器,數(shù)碼管顯示檢測的溫度值
單片機型號:STC89C52
DS18B20介紹
1、DS18B20簡介
DS18B20 是由 DALLAS 半導(dǎo)體公司推出的一種的“一線總線(單總線)”接口的溫度傳感器。與傳統(tǒng)的熱敏電阻等測溫元件相比,它是一種新型的體積小、 適用電壓寬、與微處理器接口簡單的數(shù)字化溫度傳感器。
2、DS18B20內(nèi)部結(jié)構(gòu)
DS18B20 溫度傳感器的內(nèi)部存儲器包括一個高速的暫存器 RAM 和一個非易 失性的可電擦除的EEPROM,后者存放高溫度和低溫度觸發(fā)器 TH、TL 和配置寄存器。 配置寄存器是配置不同的位數(shù)來確定溫度和數(shù)字的轉(zhuǎn)化,配置寄存器結(jié)構(gòu)如下:
低五位一直都是"1",TM 是測試模式位,用于設(shè)置 DS18B20 在工作模式還 是在測試模式。在 DS18B20 出廠時該位被設(shè)置為 0,用戶不需要去改動。R1 和 R0 用來設(shè)置 DS18B20 的精度(分辨率),可設(shè)置為 9,10,11 或 12 位,對應(yīng)的分辨率溫度是 0.5℃,0.25℃,0.125℃和 0.0625℃。R0 和 R1 配置如下 圖:
當溫度轉(zhuǎn)換命令(44H)發(fā)布后,經(jīng)轉(zhuǎn)換所得的溫度值以二字節(jié)補碼形式存放在高速暫存存儲器的第 0 和第 1 個字節(jié)。存儲的兩個字節(jié),高字節(jié)的前 5 位是符號位 S,單片機可通過單線接口讀到該數(shù)據(jù),讀取時低位在前,高位在后, 數(shù)據(jù)格式如下:
如果測得的溫度大于 0,這 5 位為‘ 0’,只要將測到的數(shù)值乘以 0.0625 (默認精度是 12 位)即可得到實際溫度;如果溫度小于 0,這 5 位為‘ 1’, 測到的數(shù)值需要取反加 1 再乘以 0.0625 即可得到實際溫度。溫度與數(shù)據(jù)對應(yīng)關(guān)系如下:
比如我們要計算+85 度,數(shù)據(jù)輸出十六進制是 0X0550,因為高字節(jié)的高 5 位為 0,表明檢測的溫度是正溫度,0X0550 對應(yīng)的十進制為 1360,將這個值乘以12 位精度 0.0625,所以可以得到+85 度。
3、信號時序
由于 DS18B20 是單總線器件,所有的單總線器件都要求采用嚴格的信號時序,以保證 數(shù)據(jù)的 完整性。DS18B20 時序包括如下幾種:初始化時序、寫(0 和 1)時序、 讀(0 和 1)時序。 DS18B20 發(fā)送所有的命令和數(shù)據(jù)都是字節(jié)的低位在前。這里我們 簡單介紹這幾個信號的時序:
(1)初始化時序
單總線上的所有通信都是以初始化序列開始。主機輸出低電平,保持低電平時間至少 480us(該時間的時間范圍可以從 480 到 960 微妙),以產(chǎn)生復(fù)位脈沖。接著主機釋放總線,外部的上拉電阻將單總線拉高,延時 15~60 us,并進入接收模式。接著 DS18B20 拉低總線 60~240 us,以產(chǎn)生低電平應(yīng)答脈沖,若為低電平,還要做延時,其延時的時間從外部上拉電阻將單總線拉高算起最少要480 微妙。初始化時序圖如下:
(2)寫時序
寫時序包括寫 0 時序和寫 1 時序。所有寫時序至少需要 60us,且在 2 次獨立的寫時序之間至少需要 1us 的恢復(fù)時間,兩種寫時序均起始于主機拉低總線。寫 1 時序:主機輸出低電平,延時 2us,然后釋放總線,延時 60us。寫 0 時序:主機輸出低電平,延時 60us,然后釋放總線,延時 2us。寫時序圖如下:
(3)讀時序
單總線器件僅在主機發(fā)出讀時序時,才向主機傳輸數(shù)據(jù),所以,在主機發(fā)出讀數(shù)據(jù)命令后,必須馬上產(chǎn)生讀時序,以便從機能夠傳輸數(shù)據(jù)。所有讀時序至少需要 60us,且在 2 次獨立的讀時序之間至少需要 1us 的恢復(fù)時間。每個讀時序都由主機發(fā)起,至少拉低總線 1us。主機在讀時序期間必須釋放總線,并且在時序起始后的 15us 之內(nèi)采樣總線狀態(tài)。讀時序圖如下:
典型的讀時序過程為:主機輸出低電平延時 2us,然后主機轉(zhuǎn)入輸入模式延 時 12us,然后讀取單總線當前的電平,然后延時 50us。 296 在了解了單總線時序之后,我們來看看 DS18B20 的典型溫度讀取過程, DS18B20 的典型溫度讀取過程為:復(fù)位→發(fā) SKIP ROM 命令(0XCC)→發(fā)開始轉(zhuǎn) 換命令(0X44)→延時→復(fù)位→發(fā)送 SKIP ROM 命令(0XCC)→發(fā)讀存儲器命令 (0XBE)→連續(xù)讀出兩個字節(jié)數(shù)據(jù)(即溫度)→結(jié)束。
硬件原理
從上圖可以看出,傳感器接口的單總線管腳接至單片機 P3.7 IO 口上,在介紹單總線的時候我們說過,為了讓單總線默認為高電平,通常會在單總線上接上拉電阻,在圖中并沒有看到有上拉電阻,這是因為單片機 IO 都外接了 10K 上拉 電阻,當單片機 IO 口連接到傳感器的總線管腳時即相當于它們外接上拉電阻, 所以此處可以省去。文章來源:http://www.zghlxwxcb.cn/news/detail-428905.html
軟件編寫
程序框架如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-428905.html
- 編寫數(shù)碼管顯示功能
- 編寫 DS18B20 讀取溫度功能
- 編寫主函數(shù)
#include <REGX52.H>
#include <intrins.h>
//數(shù)碼管管腳定義
#define LED P0
//定義數(shù)碼管位選信號控制腳
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//DS18B20管腳定義
sbit DS18B20_PORT=P3^7;
//共陰極數(shù)碼管顯示0~F的段碼數(shù)據(jù)
unsigned char Smg[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//延遲函數(shù)
void Delay(unsigned char x)
{
while(x--);
}
//數(shù)碼管顯示函數(shù)
void Smg_Display(unsigned char Data[],unsigned char Location)
{
unsigned char i=0;
unsigned char temp=Location-1;
for(i=temp;i<8;i++)
{
switch(i) //位選
{
case 0: LSC=1;LSB=1;LSA=1;break;
case 1: LSC=1;LSB=1;LSA=0;break;
case 2: LSC=1;LSB=0;LSA=1;break;
case 3: LSC=1;LSB=0;LSA=0;break;
case 4: LSC=0;LSB=1;LSA=1;break;
case 5: LSC=0;LSB=1;LSA=0;break;
case 6: LSC=0;LSB=0;LSA=1;break;
case 7: LSC=0;LSB=0;LSA=0;break;
}
LED=Data[i-temp]; //傳送段選數(shù)據(jù)
Delay(100); //延時一段時間,等待顯示穩(wěn)定
LED=0x00; //消影
}
}
//初始化時序
unsigned char DS18B20_Init()
{
//復(fù)位DS18B20
DS18B20_PORT=0; //拉低DQ
Delay(75); //拉低 750us
DS18B20_PORT=1; //拉高DQ
Delay(2); //拉高 20us
//檢測DS18B20是否存在
unsigned char time=0;
while((DS18B20_PORT==1)&&(time<20)) //等待 DQ 為低電平
{
time++;
Delay(1);
}
if(time>=20) //如超時則強制返回
return 0;
else
time=0;
while((DS18B20_PORT==0)&&(time<20)) //等待 DQ 為高電平
{
time++;
Delay(1);
}
if(time>=20) //如超時則強制返回
return 0;
else
return 1;
}
//寫時序
void DS18B20_Write_Byte(unsigned char Data)
{
unsigned char i;
unsigned char temp;
for(i=0;i<8;i++) //循環(huán)8次,每次寫一位,且先寫低位再寫高位
{
temp=Data&0x01; //選擇低位準備寫入
Data>>=1; //將次高位移到低位
if(temp==1) //寫 1 時序
{
DS18B20_PORT=0;
_nop_(); //延時 1us
_nop_();
DS18B20_PORT=1;
Delay(6);
}
else //寫 0 時序
{
DS18B20_PORT=0;
Delay(6);
DS18B20_PORT=1;
_nop_();
_nop_();
}
}
}
//讀時序
unsigned char DS18B20_Read_Byte()
{
unsigned char i;
unsigned char dat=0;
unsigned char Data=0;
for(i=0;i<8;i++) //循環(huán)8次,每次讀取一位,且先寫低位再寫高位
{
DS18B20_PORT=0; //先拉低電平
_nop_();
_nop_();
DS18B20_PORT=1; //再釋放總線
_nop_();
_nop_();
//該段時間不能過長,必須在 15us 內(nèi)讀取數(shù)據(jù)
if(DS18B20_PORT==1) //如果總線上為 1 則數(shù)據(jù)為 1,否則為 0
dat=1;
else
dat=0;
Delay(5);
Data=(dat<<7)|(Data>>1); //將讀取的數(shù)字合在一起
}
return Data;
}
//獲取溫度值
float DS18B20_Read_Temperture()
{
float temp; //存儲溫度值
unsigned char DataH=0; //存儲低字節(jié)
unsigned char DataL=0; //存儲高字節(jié)
unsigned int value=0;
DS18B20_Init(); //復(fù)位
DS18B20_Write_Byte(0xcc); //發(fā) SKIP ROM 命令(0XCC)
DS18B20_Write_Byte(0x44); //發(fā)開始轉(zhuǎn)換命令(0x44)
//延時(可有可無)
DS18B20_Init(); //復(fù)位
DS18B20_Write_Byte(0xcc); //發(fā) SKIP ROM 命令(0XCC)
DS18B20_Write_Byte(0xBE); //發(fā)讀存儲器命令(0xBE)
//連續(xù)讀出兩個字節(jié)數(shù)據(jù)(即溫度)
DataL=DS18B20_Read_Byte(); //低字節(jié)
DataH=DS18B20_Read_Byte(); //高字節(jié)
value=(DataH<<8)+DataL; //合并為16位數(shù)據(jù)
if((value&0xf800)==0xf800) //判斷符號位 負溫度
{
value=(~value)+1; //取反加一,因為是以反碼形式存儲
temp=value*(-0.0625); //乘以精度
}
else //正溫度
temp=value*0.0625;
return temp;
}
void main()
{
int value;
unsigned char i=0;
unsigned char buf[5];
DS18B20_Init(); //初始化 DS18B20
while(1)
{
i++;
if(i%50==0) //間隔一段時間讀取溫度值,間隔時間要大于溫度傳感器轉(zhuǎn)換溫度時間
value=DS18B20_Read_Temperture()*10; //保留溫度值小數(shù)后一位
if(value<0) //負溫度
{
value=-value;
buf[0]=0x40; //顯示負號
}
else
buf[0]=0x00; //不顯示
buf[1]=Smg[value/1000]; //百位
buf[2]=Smg[value%1000/100]; //十位
buf[3]=Smg[value%1000%100/10]|0x80; //個位+小數(shù)點
buf[4]=Smg[value%1000%100%10]; //小數(shù)點后一位
Smg_Display(buf,4);
}
}
到了這里,關(guān)于51單片機溫度傳感器DS18B20的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!