1.首先我們知道DS18B20是單總線協(xié)議,只有一根數(shù)據(jù)線。所以Data數(shù)據(jù)線即使發(fā)送端又是接收端,同時(shí)DS18B20內(nèi)部接了弱上拉電阻(如圖一所示),數(shù)據(jù)線默認(rèn)為高電平。有了這些概念,我們就能進(jìn)行下一步。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖一(截取DS18B20芯片手冊)
2.初始化DS18B20
? ? ?看圖二可知,首先我們將總線從高拉低,保持480us左右,然后釋放總線(沒人拉低,默認(rèn)高電平),此時(shí)總線上為高電平。然后等待15-60us,等待DS18B20模塊將總線拉低。(如果拉低則說明DS18B20響應(yīng)成功),DS18B20拉低60-240us后,釋放總線。初始化完成。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖二
?3.向DS18B20寫入數(shù)據(jù)。
? ? ? ? 3.1 向DS18B20寫0。
? ? ? ?首先將總線由高拉低,低電平保持15us到60us,然后釋放總線。寫入0完成。
? ? ? ? 3.2 向DS18B20寫1。
? ? ? ? 將總線由高拉低,低電平保持1-15us(看圖三可知,低電平時(shí)間要低于15us),再釋放總線。
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖三
4.讀取DS18B20寄存器中數(shù)據(jù)
? ? ? ? 4.1 讀數(shù)據(jù)0
將總線由高拉低,保持1-15us。如果DS18B20中數(shù)據(jù)是0,則會(huì)將總線拉低。此時(shí),總線上為低電平。我們要在60us以內(nèi)讀取數(shù)據(jù)(圖四可知,60us以內(nèi)DS18B20會(huì)釋放總線)。否則可能會(huì)讀到錯(cuò)誤數(shù)據(jù)。
? ? ? ? 4.2 讀數(shù)據(jù)1
將總線由高拉低,保持1-15us,如果數(shù)據(jù)是1,DS18B20會(huì)釋放總線,總線上為高電平。然后在15us以后讀取數(shù)據(jù)。
? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??圖四
5.DS18B20一些命令
? 5.1 0xCC→跳過ROM??
?5.2 其他命令
? 0x44→開始溫度轉(zhuǎn)換指令 ,0xBE→讀取數(shù)據(jù)寄存器指令
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖五
6.DS18B20數(shù)據(jù)寄存器
?這里也比較關(guān)鍵,所以拎出來講一下。
首先DS18B20的數(shù)據(jù)寄存器是16位,其中寄存器高字節(jié)的高5位的S表示符號(hào)位,其余3位才是表示數(shù)據(jù)。這里就淺講一下,后面結(jié)合代碼來解析一下。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 圖六?
?7.代碼實(shí)例
? ? 聲明:首先這里面的延時(shí)都是按照經(jīng)驗(yàn)值,就是通過實(shí)踐,得出比較準(zhǔn)確的延時(shí)。
? ? 注:這里使用的是12M頻率的單片機(jī),如果是1M可以把for循環(huán)去掉
延時(shí)函數(shù)如下:
sbit DQ=P1^4;
//我這里是P1^4連接了DS18B20的數(shù)據(jù)線。
//你們根據(jù)自己的單片機(jī)原理圖查詢
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
? ? ? ??7.1 DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0; //拉低總線
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10); //等待DS18B20拉低
initflag = DQ; //獲取總線數(shù)據(jù)
Delay_OneWire(5);
return initflag;
}
? ? ? ? ?7.2 向DS18B20寫入一字節(jié)數(shù)據(jù)
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0; //拉低
DQ = dat&0x01; //獲取dat最后一位數(shù)據(jù)
Delay_OneWire(5);//寫入數(shù)據(jù)
DQ = 1; //釋放總線
dat >>= 1; //dat右移一位
}
Delay_OneWire(5);
}
? ? ? ? 7.3 讀取DS18B20數(shù)據(jù)寄存器的值
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
//循環(huán)8次,讀一個(gè)字節(jié)
for(i=0;i<8;i++)
{
DQ = 0; //拉低
dat >>= 1;
DQ = 1; //釋放總線
if(DQ) // 因?yàn)閐at>>1位默認(rèn)是0 ,如果DQ為0,就不需要賦0了
{
dat |= 0x80; //給dat賦1
}
Delay_OneWire(5);
}
return dat;
}
? ? ? ? 7.4 讀取溫度
unsigned int get_temp()
{
unsigned int result;
float i;
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);//跳過rom
Write_DS18B20(0x44);//開始轉(zhuǎn)換
init_ds18b20();
Write_DS18B20(0xcc);//跳過rom
Write_DS18B20(0xbe);//開始轉(zhuǎn)換
low=Read_DS18B20(); //先讀取低字節(jié)
high=Read_DS18B20();//再讀取高字節(jié)
result =high&0x0f; //獲取高字節(jié)低4位數(shù)據(jù)(1位符號(hào)位,3位數(shù)據(jù)位)
result<<=8; //左移8位
result=result|low; //或上低字節(jié),拼成16位數(shù)據(jù)。
i=result*0.0625; //為什么乘0.0625,下面講
result=i*100; //溫度值擴(kuò)大100倍,方便數(shù)碼管顯示
return result; //返回溫度值
}
這里為什么最后的結(jié)果result需要乘以*0.0625。我們上面講過DS18B20的數(shù)據(jù)寄存器,其實(shí)高字節(jié)的低3位才是數(shù)據(jù)位。?如高字節(jié)的最后一位本來是 2^4,假如有這個(gè)數(shù)據(jù)。則數(shù)據(jù)寄存器這個(gè)位為1,因?yàn)槲覀円呀?jīng)左移了8位,則變成了2^8.則實(shí)際上擴(kuò)大了2^8/2^4=2^4=16,比實(shí)際結(jié)果擴(kuò)大了16倍,所以我們需要乘以0.0625,縮小16倍。這樣才能得到真實(shí)值。
所以整體原因是因?yàn)閞esult左移8位,導(dǎo)致數(shù)據(jù)擴(kuò)大了16倍,所以result需要乘以0.0625縮小16倍!
?文章來源地址http://www.zghlxwxcb.cn/news/detail-482517.html
8.結(jié)語?
?這次也是通過DS18B20的芯片手冊來講解如何讀取DS18B20的數(shù)據(jù),以及最后轉(zhuǎn)化為真實(shí)溫度。? ?最后也是用代碼實(shí)例來鞏固理論,以及驗(yàn)證理論。
????????文章來源:http://www.zghlxwxcb.cn/news/detail-482517.html
?
到了這里,關(guān)于51單片機(jī)讀取DS18B20溫度傳感器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!