ds18b20數(shù)據(jù)手冊(cè)
DS18B20內(nèi)部構(gòu)成
主要由以下3部分組成:
64 位ROM
高速暫存器
存儲(chǔ)器
64位ROM存儲(chǔ)獨(dú)有的序列號(hào),ROM中的64位序列號(hào)是出廠前被光刻好的,它可以看作是該DS18B20的地址序列碼,每個(gè)DS18B20的64位序列號(hào)均不相同。這樣就可以實(shí)現(xiàn)一根總線上掛接多個(gè)DS18B20的目的。
高速暫存器包含:
溫度傳感器
一個(gè)字節(jié)的溫度上限和溫度下限報(bào)警觸發(fā)器(TH和TL)
配置寄存器允許用戶設(shè)定9位,10位,11位和12位的溫度分辨率,分別對(duì)應(yīng)著溫度的分辨率為:0.5°C,0.25°C,0.125°C,0.0625°C,默認(rèn)為12位分辨率
存儲(chǔ)器:由一個(gè)高速的RAM和一個(gè)可擦除的EEPROM組成,EEPROM存儲(chǔ)高溫和低溫觸發(fā)器(TH和TL)以及配置寄存器的值,(就是存儲(chǔ)低溫和高溫報(bào)警值以及溫度分辨率)
DS18B20溫度讀取與計(jì)算
DS18B20采用16位補(bǔ)碼的形式來(lái)存儲(chǔ)溫度數(shù)據(jù),溫度是攝氏度。當(dāng)溫度轉(zhuǎn)換命令發(fā)布后,經(jīng)轉(zhuǎn)換所得的溫度值以二字節(jié)補(bǔ)碼形式存放在高速暫存存儲(chǔ)器的第0和第1個(gè)字節(jié)。
高字節(jié)的五個(gè)S為符號(hào)位,溫度為正值時(shí)S=1,溫度為負(fù)值時(shí)S=0。
剩下的11位為溫度數(shù)據(jù)位,對(duì)于12位分辨率,所有位全部有效,對(duì)于11位分辨率,位0(bit0)無(wú)定義,對(duì)于10位分辨率,位0和位1無(wú)定義,對(duì)于9位分辨率,位0,位1,和位2無(wú)定義。
對(duì)應(yīng)的溫度計(jì)算:
當(dāng)五個(gè)符號(hào)位S=0時(shí),溫度為正值,直接將后面的11位二進(jìn)制轉(zhuǎn)換為十進(jìn)制,再乘以0.0625(12位分辨率),就可以得到溫度值。
當(dāng)五個(gè)符號(hào)位S=1時(shí),溫度為負(fù)值,先將后面的11位二進(jìn)制補(bǔ)碼變?yōu)樵a(符號(hào)位不變,數(shù)值位取反后加1),再計(jì)算十進(jìn)制值。再乘以0.0625(12位分辨率),就可以得到溫度值。
舉兩個(gè)例子:
數(shù)字輸出07D0(00000111 11010000),轉(zhuǎn)換成10進(jìn)制是2000,對(duì)應(yīng)攝氏度:0.0625x2000=125°C
數(shù)字輸出為 FC90,首先取反,然后+1,轉(zhuǎn)換成原碼為:11111011 01101111,數(shù)值位轉(zhuǎn)換成10進(jìn)制是870,對(duì)應(yīng)攝氏度:-0.0625x870=-55°C
溫度對(duì)應(yīng)表如下:
上述例子,用C語(yǔ)言來(lái)實(shí)現(xiàn)的代碼,如下:
unsigned int Temp1,Temp2,Temperature; //Temp1低八位,Temp2高八位
unsigned char Minus Flag=0; //負(fù)溫度標(biāo)志位
if(Temp2&0xFC)//判斷符號(hào)位是否為1
{
Minus Flag=l; //負(fù)溫度標(biāo)志位置1
Temperature=((Temp2<<8)|Temp1); //高八位第八位進(jìn)行整合
Temperature=((Temperature)+1); //講補(bǔ)碼轉(zhuǎn)換為原碼,求反,補(bǔ)1
Temperature*=0.0625;//求出十進(jìn)制
}
else //溫度為正值
{
Minus Flag=0; //負(fù)溫度標(biāo)志位置0
Temperature =((Temp2<<8) |Temp1)*0.0625;
}
DS18B20工作步驟
DS18B20的工作步驟可以分為三步:
初始化DS18B20
執(zhí)行ROM指令
執(zhí)行DS18B20功能指令
其中第二步執(zhí)行ROM指令,也就是訪問(wèn)每個(gè)DS18B20,搜索64位序列號(hào),讀取匹配的序列號(hào)值,然后匹配對(duì)應(yīng)的DS18B20,如果我們僅僅使用單個(gè)DS18B20,可以直接跳過(guò)ROM指令。而跳過(guò)ROM指令的字節(jié)是0xCC。
初始化DS18B20
任何器件想要使用,首先就是需要初始化,對(duì)于DS18B20單總線設(shè)備,首先初始化單總線為高電平,然后總線開(kāi)始也需要檢測(cè)這條總線上是否存在DS18B20這個(gè)器件。如果這條總線上存在DS18B20,總線會(huì)根據(jù)時(shí)序要求返回一個(gè)低電平脈沖,如果不存在的話,也就不會(huì)返回脈沖,即總線保持為高電平。
初始化具體時(shí)序步驟如下:
單片機(jī)拉低總線至少480us,產(chǎn)生復(fù)位脈沖,然后釋放總線(拉高電平)
這時(shí)DS8B20檢測(cè)到請(qǐng)求之后,會(huì)拉低信號(hào),大約60~240us表示應(yīng)答
DS8B20拉低電平的60~240us之間,單片機(jī)讀取總線的電平,如果是低電平,那么表示初始化成功
DS18B20拉低電平60~240us之后,會(huì)釋放總線
DS18B20的初始化代碼如下:
/*****初始化DS18B20*****/
unsigned int Init_DS18B20(void)
{
unsigned int x=0;
DQ = 1; //DQ復(fù)位
delay(4); //稍做延時(shí)
DQ = 0; //單片機(jī)將DQ拉低
delay(60); //精確延時(shí),大于480us
DQ = 1; //拉高總線
delay(8);
x = DQ; //稍做延時(shí)后,如果x=0則初始化成功,x=1則初始化失敗
delay(4);
return x;
}
寫(xiě)時(shí)序
總線控制器通過(guò)控制單總線高低電平持續(xù)時(shí)間從而把邏輯1或0寫(xiě)DS18B20中。每次只傳輸1位數(shù)據(jù)。
單片機(jī)想要給DS18B20寫(xiě)入一個(gè)0時(shí),需要將單片機(jī)引腳拉低,保持低電平時(shí)間要在60~120us之間,然后釋放總線。
單片機(jī)想要給DS18B20寫(xiě)入一個(gè)1時(shí),需要將單片機(jī)引腳拉低,拉低時(shí)間需要大于1us,然后在15us內(nèi)拉高總線。
在寫(xiě)時(shí)序起始后15μs到60μs期間,DS18B20處于采樣單總線電平狀態(tài)。如果在此期間總線為高電平,則向DS18B20寫(xiě)入1;如果總線為低電平,則向DSl8B20寫(xiě)入0。
注意:2次寫(xiě)周期之間至少間隔1us。
DS18B20寫(xiě)時(shí)序的代碼如下:
/*****寫(xiě)一個(gè)字節(jié)*****/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01; //與1按位與運(yùn)算,dat最低位為1時(shí)DQ總線為1,dat最低位為0時(shí)DQ總線為0
delay(4);
DQ = 1;
dat>>=1;
}
delay(4);
}
采用多個(gè)DS18B20時(shí),需要寫(xiě)ROM指令來(lái)控制總線上的某個(gè)DS18B20。如果是單個(gè)DS18B20,直接寫(xiě)跳過(guò)ROM指令0xCC即可。DS18B20寫(xiě)入ROM功能指令如下表:
DS18B20的一些RAM功能指令如下表。其中常用的是溫度轉(zhuǎn)換指令,開(kāi)啟溫度讀取轉(zhuǎn)換,讀取好的溫度會(huì)存儲(chǔ)在高速暫存器的第0個(gè)和第一個(gè)字節(jié)中。另一個(gè)常用的是讀取溫度指令,讀取高速暫存器存儲(chǔ)的數(shù)據(jù)。
讀時(shí)序
讀時(shí)隙由主機(jī)拉低總線電平至少1μs然后再釋放總線,讀取DS18B20發(fā)送過(guò)來(lái)的1或者0。
DS18B20在檢測(cè)到總線被拉低1微秒后,便開(kāi)始送出數(shù)據(jù),若是要送出0就把總線拉為低電平直到讀周期結(jié)束。若要送出1則釋放總線為高電平。
注意:所有讀時(shí)隙必須至少需要60us,且在兩次獨(dú)立的時(shí)隙之間至少需要1ps的恢復(fù)時(shí)間。
同時(shí)注意:主機(jī)只有在發(fā)送讀暫存器命令(0xBE)或讀電源類型命令(0xB4)后,立即生成讀時(shí)隙指令,DS18B20才能向主機(jī)傳送數(shù)據(jù)。也就是先發(fā)讀取指令,再發(fā)送讀時(shí)隙。
最后一點(diǎn):寫(xiě)時(shí)序注意是先寫(xiě)命令的低字節(jié),比如寫(xiě)入跳過(guò)ROM指令0xCC(11001100),寫(xiě)的順序是“零、零、壹、壹、零、零、壹、壹”。
讀時(shí)序時(shí)是先讀低字節(jié),在讀高字節(jié),也就是先讀取高速暫存器的第0個(gè)字節(jié)(溫度的低8位),在讀取高速暫存器的第1個(gè)字節(jié)(溫度的高8位) 我們正常使用DS18B20讀取溫度讀取兩個(gè)溫度字節(jié)即可。
STM32例程
DS18B20.c代碼:
#include "ds18b20.h"
#include "delay.h"
//復(fù)位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT(); //SET PG11 OUTPUT
DS18B20_DQ_OUT=0; //拉低DQ
delay_us(750); //拉低750us
DS18B20_DQ_OUT=1; //DQ=1
delay_us(15); //15US
}
//等待DS18B20的回應(yīng)
//返回1:未檢測(cè)到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN(); //SET PG11 INPUT
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
//從DS18B20讀取一個(gè)位
//返回值:1/0
u8 DS18B20_Read_Bit(void)
{
u8 data;
DS18B20_IO_OUT(); //SET PG11 OUTPUT
DS18B20_DQ_OUT=0;
delay_us(2);
DS18B20_DQ_OUT=1;
DS18B20_IO_IN(); //SET PG11 INPUT
delay_us(12);
if(DS18B20_DQ_IN)data=1;
else data=0;
delay_us(50);
return data;
}
//從DS18B20讀取一個(gè)字節(jié)
//返回值:讀到的數(shù)據(jù)
u8 DS18B20_Read_Byte(void)
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
//寫(xiě)一個(gè)字節(jié)到DS18B20
//dat:要寫(xiě)入的字節(jié)
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT(); //SET PG11 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DS18B20_DQ_OUT=0; // Write 1
delay_us(2);
DS18B20_DQ_OUT=1;
delay_us(60);
}
else
{
DS18B20_DQ_OUT=0; // Write 0
delay_us(60);
DS18B20_DQ_OUT=1;
delay_us(2);
}
}
}
//開(kāi)始溫度轉(zhuǎn)換
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0x44); // convert
}
//初始化DS18B20的IO口 DQ 同時(shí)檢測(cè)DS的存在
//返回1:不存在
//返回0:存在
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PORTG口時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTG.11 推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_11); //輸出1
DS18B20_Rst();
return DS18B20_Check();
}
//從ds18b20得到溫度值
//精度:0.1C
//返回值:溫度值 (-550~1250)
short DS18B20_Get_Temp(void)
{
u8 temp;
u8 TL,TH;
short tem;
DS18B20_Start (); // ds1820 start convert
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0xbe); // convert
TL=DS18B20_Read_Byte(); // LSB
TH=DS18B20_Read_Byte(); // MSB
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0; //溫度為負(fù)
}else temp=1; //溫度為正
tem=TH; //獲得高八位
tem<<=8;
tem+=TL; //獲得底八位
tem=(float)tem*0.625; //轉(zhuǎn)換
if(temp)return tem; //返回溫度值
else return -tem;
}
DS18B20.h代碼:
#ifndef __DS18B20_H
#define __DS18B20_H
#include "sys.h"
//IO方向設(shè)置
#define DS18B20_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
//IO操作函數(shù)
#define DS18B20_DQ_OUT PGout(11) //數(shù)據(jù)端口 PA0
#define DS18B20_DQ_IN PGin(11) //數(shù)據(jù)端口 PA0
u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//獲取溫度
void DS18B20_Start(void);//開(kāi)始溫度轉(zhuǎn)換
void DS18B20_Write_Byte(u8 dat);//寫(xiě)入一個(gè)字節(jié)
u8 DS18B20_Read_Byte(void);//讀出一個(gè)字節(jié)
u8 DS18B20_Read_Bit(void);//讀出一個(gè)位
u8 DS18B20_Check(void);//檢測(cè)是否存在DS18B20
void DS18B20_Rst(void);//復(fù)位DS18B20
#endif