具體信息見數據手冊:廠商Dallas Semiconductor DS18B20 數據手冊
一、DS18B20介紹
DALLAS公司的DS18B20數字溫度傳感器是“一線總線”的典型代表,DS18B20的溫度測量范圍為-55℃+125℃,在-10℃+85℃范圍內,精度為±0.5℃。采用“一線總線”方式傳輸,可以大大提高系統的抗干擾能力,所以DS18B20廣泛 用於溫度采集及監控領域。
目前單片機應用系統常用的串行器件有:
- 一線總線器件——DS18B20溫度傳感器
- 二線總線器件——iic總線器件(如采用iic形式的oled顯示屏)
- 三線總線器件——DS1302時鍾芯片(即SPI總線器件)
二、單總線及其擴展
1、DS18B20的引腳
實物模塊圖如下:
(1)VCC:供電電源輸入端
(2)DQ:數字信號輸入輸出端
(3)GND:電源地
2、內部結構
DS18B20溫度傳感器主要由64位ROM、高速緩沖存儲器、CRC生成器、溫度敏感器件、高低溫觸發器及配置寄存器等部件組成。
(1)DS18B20的64位ROM
每個DS18B20都有64位的ROM,出廠之前ROM固化有確定的內容。
低八位(固定為28H)是產品類型標識號,接着的48位是該DS18B20的序列號,高8位是前面56位的循環冗余檢驗碼。由於每個DS18B20都有自己的序列號,這樣就可以實現一根總線上掛接多個DS18B20的目的。
(2)DS18B20的內存映射
在DS18B20的內部有9個字節高速緩沖存儲單元。如下圖所示。
- 第1及第2字節存放轉換完成的溫度值
- 第3及第4字節分別存放上下限報警值TH和TL
- 第5字節為配置寄存器
- 第6、7、8字節為工廠保留字節
- 第9字節是前8字節的CRC檢驗碼(用於提高傳輸的可靠性)
另外在DS18B20的內部還用3個EEPROM單元存放上下限報警值TH、TL和配置寄存器的設定值。數據先寫入高速緩沖存儲器,然后再傳給EEPROM單元。
(3)配置寄存器
配置寄存器字節的最高位D7為測試模式位,出廠時為0,用戶不要改動。D6D5位用於設置DS18B20的轉換分辨率,分辨率有9、10、11和12位四種選擇,對應的轉換時間分別為:93.73ms、187.5ms、275ms和750ms。其余的低5位為保留位(均為1)。
(出廠時默認值為7FH,即分辨率為12位 )
3、DS18B20的溫度值格式
DS18B20中溫度敏感元件完成對溫度的檢測,轉換后的溫度值以帶符號擴展的二進制補碼(16位)形式存儲在高速緩沖存儲器的第1和第2字節中。溫度值以0.0625℃/LSB形式表達。(LSB即Least Significant Bit,意為最低有效位)。采樣值與溫度值的關系:
二進制采樣值 | 十六進制表示 | 十進制溫度/℃ |
---|---|---|
0000 0111 1101 0000 | 07D0 H | +125 |
0000 0001 1001 0001 | 0191 H | +25.0625 |
0000 0000 1010 0010 | 00A2 H | +10.125 |
0000 0000 0000 1000 | 0008 H | +0.5 |
0000 0000 0000 0000 | 0000 H | 0 |
1111 1111 1111 1000 | FFF8 H | -0.5 |
1111 1111 0101 1110 | FF5E H | -10.125 |
1111 1110 0110 1111 | FE6F H | -25.0625 |
1111 1100 1001 0000 | FC90 H | -55 |
12位分辨率時的溫度值格式如下圖:
當符號位S為0時,表示溫度為正,只要將二進制采樣值轉換為十進制數就可以得到十進制表示的溫度值;
當符號位S為1時,表示溫度為負(用補碼表示),這時要對讀取的采樣值取補(取反加1),再轉換為十進制數才能得到十進制表示的溫度值。
三、DS18B20的操作命令
1、ROM操作命令
ROM命令主要用於一線總線上接有多個DS18B20的情況,ROM操作命令與總線上具體DS18B20器件的序列號相關。
ROM操作命令:
指令 | 代碼 | 說明 |
---|---|---|
讀 ROM | 33 H | 讀總線上DS18B20的序列號 |
匹配 ROM | 55 H | 依序列號訪問確定的DS18B20器件 |
跳過 ROM | CC H | 只使用RAM命令,操作在線的DS18B20器件 |
搜索 ROM | F0 H | 對總線上的多個DS18B20進行識別 |
報警搜索 | EC H | 主機搜索越限報警的DS18B20器件 |
2、RAM操作命令
單片機利用ROM操作命令,與總線上指定的DS18B20器間建立起聯系后,就可以對這個指定器件實施RAM操作命令。
這些操作命令允許單片機寫入或讀出DS18B20器件緩沖器的內容。
指令 | 代碼 | 說明 |
---|---|---|
溫度轉換 | 44 H | 啟動DS18B20開始轉換 |
讀緩沖器 | BE H | 讀緩沖器的9個字節數據 |
寫緩沖器 | 4E H | 向DS18B20寫TH、TL及配置寄存器數據 |
復制緩沖器 | 48 H | 將緩沖器的TH、TL和配置寄存器值送EEPROM |
回讀EEPROM | B8 H | 將EEPROM中的TH、TL和配置寄存器值送緩沖器 |
讀供電方式 | B4 H | 檢測供電方式:寄生或外接方式 |
四、操作時序
在一線總線傳輸數據時,邏輯0用一段持續的低電平表示,邏輯1用一段持續的高電平表示。單片機向DS18B20器件傳輸數據時產生寫時隙,單片機從DS18B20器件讀取數據時產生讀間隙。讀間隙和寫間隙均以單片機驅動總線產生低電平開始。
1、初始化時序
單片機與DS18B20器件進行通信是以初始化開始的,初始化序列包括單片機產生復位脈沖和DS18B20器件回應的應答脈沖。當DS18B20發送存在脈沖響應復位時,它指示主機它在總線上並准備好操作。
在初始化序列中,總線主機通過將1線主機拉低至少480us來發送(Tx)復位脈沖。然后單片機釋放總線,進入接收模型(Rx)。當總線釋放時,上拉電阻將1線總線拉高。當DS18B20檢測到上升沿時,它等待15us到60us,DS18B20器件收到單片機發來的復位脈沖后,向總線回應應答脈沖,應答脈沖會使總線拉低60~240us。
2、讀寫時序
總線在寫時隙向DS18B20寫入數據,並在讀時隙從DS18B20讀取數據。每個時隙都有一位數據通過。
1、寫時序
寫時隙有兩種類型:寫1時隙和寫0時隙。這兩種寫時隙都是由主機拉低單線總線發起的。總線使用寫1時隙向DS18B20寫入邏輯1,使用寫0時隙向DS18B20寫入0。
所有寫時隙必須至少有60us的持續時間,並且每個寫時隙之間至少有1us的恢復時間。對於寫0時隙,單片機拉低總線並保持低電平至少60us,然后釋放總線;對於寫1時隙,單片機拉低總線,然后在15us內要釋放總線。
DS18B20在master啟動寫時隙后,在一個持續時間從15us到60us的窗口中對1-WIRE總線進行采樣。如果總線在采樣窗口期間是高,則1被寫入DS18B20。
3、讀時序
DS18B20只能在單片機發出讀取時隙向單片機傳輸數據。因此,單片機必須在發出Read Scratchpad [BE H]或Read Power Supply [B4 H]命令后立即生成讀時隙,以便DS18B20能夠提供所請求的數據。此外單片機可以在發出Convert T [44 H]或Recall E2 [B8 H]命令后生成讀時點,以了解操作狀態。
所有讀時隙的持續時間必須至少為60us,時隙之間的恢復時間必須至少為1us。一個讀時隙是由主設備將1-wire總線拉低一個最小邏輯單元,然后釋放總線發起的。在主機啟動讀取時隙后,DS18B20將開始在總線上發送1或0。DS18B20通過使總線保持高電平來發送1,通過拉低總線來發送0。當發送0時,DS18B20將在時隙結束時釋放總線,總線將被上拉電阻拉回其空閑狀態。
輸出DS18B20的數據在下降沿啟動讀取時隙對15us有效,所以單片機應在15us內采樣總線電平。
五、參考程序(針對51的)
DS18B20.c
#include "reg52.h"
#include "DS18B20.h"
#include "delay.h"
//IO接口定義
sbit DQ = P2^6; //定義DS18B20端口DQ
unsigned char RomCode[8];
int Real_temp; //實際溫度值
/*******************************************************************/
/* */
/*初始化ds1820 */
/* */
/*******************************************************************/
unsigned char Init_DS18B20(void)
{
unsigned char presence = 0;
DQ = 1; //DQ復位
Delay(8); //稍做延時
DQ = 0; //單片機將DQ拉低
Delay(80); //精確延時 大於 480us
DQ = 1; //拉高總線
Delay(8);
presence = DQ; //如果=0則初始化成功 =1則初始化失敗
Delay(4);
DQ = 1;
return(presence); //返回信號,0=presence,1= no presence
}
/*******************************************************************/
/* */
/* 讀一個字節 */
/* */
/*******************************************************************/
unsigned char ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; // 給脈沖信號
dat >>= 1;
DQ = 1; // 給脈沖信號
if(DQ)
dat |= 0x80;
Delay(4);
}
return (dat);
}
/*******************************************************************/
/* */
/* 寫一個字節 */
/* */
/*******************************************************************/
void WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat&0x01;
Delay(4);
DQ = 1;
dat>>=1;
}
Delay(4);
}
/*******************************************************************/
/* */
/* 溫度報警值寫入DS18B20 */
/* */
/*******************************************************************/
void Write_Temperature_alarm(unsigned char Temp_h , unsigned char Temp_l)
{
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0x4e); //將設定的溫度報警值寫入 DS18B20
WriteOneChar(Temp_h); //寫TH
WriteOneChar(Temp_l); //寫TL
WriteOneChar(0x7f); //12位精確度
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0x48); //把暫存器里的溫度報警值拷貝到EEROM
}
/*******************************************************************/
/* */
/* 讀取64位序列碼 */
/* */
/*******************************************************************/
void Read_RomCord(void)
{
unsigned char j;
Init_DS18B20();
WriteOneChar(0x33); // 讀序列碼的操作
for (j = 0; j < 8; j++)
{
RomCode[j] = ReadOneChar() ;
}
}
/*******************************************************************/
/* */
/*DS18B20的CRC8校驗程序 */
/* */
/*******************************************************************/
unsigned char CRC8()
{
unsigned char i,x;
unsigned char crcbuff,crc;
crc=0;
for(x = 0; x <8; x++)
{
crcbuff=RomCode[x];
for(i = 0; i < 8; i++)
{
if(((crc ^ crcbuff)&0x01)==0)
crc >>= 1;
else {
crc ^= 0x18; //CRC=X8+X5+X4+1
crc >>= 1;
crc |= 0x80;
}
crcbuff >>= 1;
}
}
return crc;
}
/*******************************************************************/
/* */
/* 讀取溫度 */
/* */
/*******************************************************************/
unsigned char Read_Temperature(void)
{
unsigned char i;
unsigned char temp_comp;
unsigned char temp_data[2];
unsigned char temp_alarm[2];
unsigned int t;
t = Init_DS18B20();
if(t) return Real_temp;
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0x44); //啟動溫度轉換
t = Init_DS18B20();
if(t) return Real_temp;
// WriteOneChar(0x55); //匹配ROM命令
// for(i=0;i<8;i++)
// WriteOneChar(RomCode[i]);
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器
temp_data[0] = ReadOneChar(); //溫度低8位
temp_data[1] = ReadOneChar(); //溫度高8位
temp_alarm[0] = ReadOneChar(); //溫度報警TH
temp_alarm[1] = ReadOneChar(); //溫度報警TL
temp_comp=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//取溫度整數值
return temp_comp;
}
DS18B20.h
#ifndef _DS18B20_H_
#define _DS18B20_H_
unsigned char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
void Write_Temperature_alarm(unsigned char Temp_h , unsigned char Temp_l);
void Read_RomCord(void);
unsigned char CRC8();
unsigned char Read_Temperature(void);
int ReadTemperature(void);
extern Real_temp;
#endif
delay.c
#include "delay.h"
/*******************************************************************************
* 函 數 名 :Delayms
* 函數功能 :實現 ms級的延時
* 輸 入 :ms
* 輸 出 :無
*******************************************************************************/
void Delayms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
#if FOSC == 11059200L
for(j=0;j<114;j++);
#elif FOSC == 12000000L
for(j=0;j<123;j++);
#elif FOSC == 24000000L
for(j=0;j<249;j++);
#else
for(j=0;j<114;j++);
#endif
}
/*******************************************************************/
/* */
/*us級延時函數 */
/* */
/*******************************************************************/
void Delay(unsigned int num)
{
for(;num>0;num--);
}
delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
#define uint unsigned int
#define uchar unsigned char
//#define FOSC 11059200L //晶振設置,默認使用11.0592M Hz
#define FOSC 12000000L //晶振設置,使用12M Hz
//#define FOSC 24000000L //晶振設置,使用24M Hz
void Delayms(unsigned int ms); // 11.0592MHz
void Delay(unsigned int num);
#endif