DS18B20溫度傳感器
- DS18B20相關介紹
- DS18B20特性
- 封裝形式與引腳說明
- 供電方式(外部電源供電、寄生電源供電、寄生電源強上拉)
- 內部結構
- 溫度存盤格式及配置暫存器(模式和解析度)
- DS18B20指令(ROM指令操作)
- 指令的使用
- 注意事項
- 時序圖
- 初始化
- 寫時序(寫0或1)
- 讀時序(讀0或1)
- 程式代碼
- LCD1602顯示溫度
- main.c(主函式)
- delay.c
- delay.h
- lcd1602.c
- lcd1602.h
- 專案展示
DS18B20相關介紹
DS18B20特性
1.獨特的單總線介面,就需一條線則可實作雙向通信(測溫)
2.測溫范圍:-55℃~+125℃,可通過編程設定9—12位解析度,對應分辨溫度分別為0.5、0.25、0.125、0.0625℃,
3.支持多點組網(可連接多個DS18B20溫度傳感器),多個DS18B20可以并聯(3或2線)實作多個組網測溫,但注意超過8個要解決好供電問題,否則電壓過低會導致傳輸不穩定,從而資料不準確,
4.作業電壓:3.0~5.5V (寄生電源方式下可由資料線供電)
5.在使用程序中不需要外圍電路,全部傳感元件及轉換電路都在芯片內了,(上拉電阻)
6.測溫結果直接是數字量輸出,單總線串行傳送方式,同時可傳送CRC校驗碼(校驗資料采集是否正確),具有極強的抗干擾和糾錯能力,
7.在9位解析度時最多在93.75ms內把溫度轉換為數字,12位解析度時最多在750ms內把溫度值轉換為數字,
8.負壓特性:電源極性接反時,芯片不會因發熱而啥訓, 但不能正常作業,
封裝形式與引腳說明

供電方式(外部電源供電、寄生電源供電、寄生電源強上拉)



內部結構
DS18B20內部結構如圖所示,其中與操作有關的是:64位光刻ROM、溫度傳感器、9個位元組的RAM存盤器、EEPROM(溫度報警暫存器TH和TL、配置暫存器),

光刻ROM中64位序列號是出廠前就光刻好的,相當地址序列號,排列是低位開始,低8位(產品型別標號),接著48位(自身序列號,)相當于身份證號、最高8位(前面56位的回圈亢余校驗碼),
如果一條總線掛接多個DS18B20需要MCU(微控制器)通過單總線對多個DS18B20進行尋址,


溫度存盤格式及配置暫存器(模式和解析度)
DS18B20溫度傳感器進行測溫,測溫是以16位的二進制形式提供,
存放格式:

16位中 低4位是溫度的小數部分、最高5位是溫度的正負(全為0為正,全為1為負),中間的7位則是溫度的整數部分,小數部分十進制等于16進制乘0.0625,
例子:

注意:如果是負數溫度,那么得按位取反+1,
比如資料為 1111 1100 1001 0000
首先低4位都為0.所以溫度小數部分為0,最高5位為1,所以溫度是負數,所以我們得按位取反才是正確的數, 溫度的整數部分為 100 1001——>按位取反得:011 0110 再+1 則結果是 011 0111 ——>0x37(16進制)——>55℃(十進制)
配置暫存器
| TM | R1 | R0 | 1 | 1 | 1 | 1 | 1 |
|---|
TM:測驗模式位,用于設定是在作業方式還是測驗模式,在DS18B20出廠時該位設為0,用戶不要改動,
R1 R0:解析度設定
| R1 | R0 | 解析度/位 | 溫度最大轉向時間/ms |
|---|---|---|---|
| 0 | 0 | 9 | 93.75 |
| 0 | 1 | 10 | 187.5 |
| 1 | 0 | 11 | 375 |
| 1 | 1 | 12 | 750 |
DS18B20指令(ROM指令操作)
| 序號 | 指令 | 代碼 | 說明 |
|---|---|---|---|
| 1 | 讀取ROM | 33H | 讀DS18B20的64位序列號(只能適用于總線上只有一個DS18B20) |
| 2 | 符合 ROM | 55H | 匹配指令,發出64位ROM編碼,與總線上一個或多個DS18B20匹配,完全對應則回應,(單個或多個均可) |
| 3 | 跳過 ROM | CCH | 忽略64位ROM地址,直接向DS18B20發溫度變換指令,適用于單片機作業,(適用于單個DS18B20), |
| 4 | 搜索 ROM | F0H | 用于確定掛接在總線上DS18B20個數和 識別64位ROM地址(一般用于多個DS18B20), |
| 5 | 報警搜索命令 | ECH | 執行后搜索溫度超過設定值上限或下限才做出回應, |
| 6 | 寫暫存器 | 4EH | 在該寫暫存器指令后向DS18B20的暫存器TH.TL以及配置暫存器中寫入資料, |
| 7 | 讀暫存器 | BEH | 發送該指令后DS18B20將從一個位元組開始,依次送出9個位元組的內容,如果不想讀完所有位元組,控制器可以在任何時間發出復位指令中止讀取或直接不讀取, |
| 8 | 復制暫存器 | 48H | 將TH.TL和配置暫存器的內容拷貝到EEPROM中,如果使用寄生電源,總線控制器必須在這條指令發出后10us內啟動強上拉并保持至少10ms時間, |
| 9 | 啟動溫度轉換指令 | 44H | 溫度轉換完成后存放在第1個和第2個位元組中,如果是寄生電源,總線必須在發出這條指令后的10us內啟動強上拉, |
| 10 | 復制EEPROM指令 | B8H | 把TH.TL和配置暫存器的值拷貝回暫存器,這種拷貝操作在DS18B20上電時自動執行,上電后,暫存器里就存了有效資料, |
| 11 | 讀供電方式指令 | B4H | 發給DS18B20后,再發出讀時間間隙,后回傳電源模式:0為寄生電源、1為外部電源, |
注:每個指令在寫都是 低位在前 高位在后 DS18B20發送也是先發低位,再發高位,
比如發送跳過ROM指令(CCH) 二進制位:1100 1100 ,發送順序為
0、0 、1、1、 0、 0、 1、 1 ,
指令的使用
多個DS18B20情況: 對某一個操作時,主機先逐個與DS18B20掛接-搜索ROM——(F0H),發出匹配ROM指令(55H),緊接著提供64位序列號,之后操作就是針對DS18B20的了,
單個DS18B20情況: 不需要搜索ROM指令,讀ROM指令以及匹配ROM等操作,直接跳過ROM指令(CCH),溫度轉換(44H),讀溫度操作(8EH),
注意事項
一、 DS18B20硬體是簡單,但軟體就比較復雜,特別是時序要求,
二、 連接DS18B20線長限制:部分資料顯示:
采用普通信號電纜傳輸超50m時,測溫資料不穩定,
采用帶屏蔽層雙絞線電纜,正常通訊距離可達到150m,
采用每米絞合次數更多的帶屏蔽層雙絞線電纜時,通訊距離進一步加長,
三、 距離長了測溫要考慮總線分布電容和阻抗匹配問題,
在測溫程式設計中,一般如果硬體沒什么問題,可以采用延時來跳過檢測,但是如果要檢測是否有應答要注意不要進入了死回圈,
時序圖
初始化

/*DS18B20初始化函式*/
void initDs18b20()
{
DS18B20 = 1;
delay20us();
DS18B20 = 0; //拉低電平
delay480us(); //480us-960us之間均可
DS18B20 = 1; //拉高電平
delay50us(); //等待15us-60us
if(DS18B20 == 1) //如果未回應
{
ds18b20Flag = 1; //DS18B20未回應 標志位置1
}
delay240us();
}
寫時序(寫0或1)

/*DS18B20寫命令函式*/
void ds18b20WriteData(unsigned char com)
{
unsigned char i;
for(i=0;i<8;i++)
{
DS18B20 = 0; //拉低電平
//延時至少1us
DS18B20 = com&0x01;
delay60us(); //至少60us直到周期結束
DS18B20 = 1;
com = com>>1; //右移一位
}
}
讀時序(讀0或1)

/*DS18B20讀資料函式*/
unsigned char ds18b20ReadData()
{
unsigned char i;
unsigned char dat = 0; //接收資料
for(i=0;i<8;i++)
{
DS18B20 = 0; //拉低電平至少1us
dat=dat>>1; //右移一位
DS18B20 = 1; //釋放總線
if(DS18B20 == 1) //如果是1
{
dat = dat|0x80;
}
delay45us(); //保持45us
DS18B20 = 1; //釋放總線
}
return dat;
}
程式代碼
每一次進行寫命令都記得初始化,
對于單個DS18B20我們可以直接跳過ROM指令 直接溫度轉換,讀取溫度
步驟:
1.初始化
2.跳過ROM指令
3.啟動溫度轉換(需要時間)
4.延時(等待溫度轉換)
5.初始化 (記得每寫命令記得需要從初始化開始)
6.讀取溫度
7.顯示溫度
LCD1602顯示溫度
main.c(主函式)
#include <reg52.h>
#include "delay.h"
#include "lcd1602.h"
sbit DS18B20 = P3^7; //DS18B20引腳
unsigned char ds18b20Flag; //DS18B20是否回應標志位
unsigned char temperature[2] = {'\0'}; //存放溫度整數和小數
unsigned char code array[14] = {"DS18B20 error!"};
unsigned char code array1[5] = {"Temp:"};
/*DS18B20初始化函式*/
void initDs18b20()
{
DS18B20 = 1;
delay20us();
DS18B20 = 0; //拉低電平
delay480us(); //480us-960us之間均可
DS18B20 = 1; //拉高電平
delay50us(); //等待15us-60us
if(DS18B20 == 1) //如果未回應
{
ds18b20Flag = 1; //DS18B20未回應 標志位置1
}
delay240us();
}
/*DS18B20寫命令函式*/
void ds18b20WriteData(unsigned char com)
{
unsigned char i;
for(i=0;i<8;i++)
{
DS18B20 = 0; //拉低電平
//延時至少1us
DS18B20 = com&0x01;
delay60us();
DS18B20 = 1;
com = com>>1;
}
}
/*DS18B20讀資料函式*/
unsigned char ds18b20ReadData()
{
unsigned char i;
unsigned char dat = 0; //接收資料
for(i=0;i<8;i++)
{
DS18B20 = 0; //拉低電平至少1us
dat=dat>>1; //右移一位
DS18B20 = 1; //釋放總線
if(DS18B20 == 1)
{
dat = dat|0x80;
}
delay45us(); //保持45us
DS18B20 = 1; //釋放總線
}
return dat;
}
/*讀取溫度函式*/
void readTemperature()
{
unsigned char temperatureLow; //溫度低位元組
unsigned char temperatureHigh; //溫度高位元組
unsigned char tempFlag = 0; //溫度正負標志位
unsigned char disposeValue; //處理值
initDs18b20(); //初始化DS18B20
ds18b20WriteData(0xcc); //跳過ROM
ds18b20WriteData(0x44); //啟動溫度轉換指令
//延時一段時間
delay800ms();
initDs18b20(); //每一次寫命令都需要初始化
ds18b20WriteData(0xcc); //跳過ROM
ds18b20WriteData(0xbe); //讀暫存器內容
temperatureLow = ds18b20ReadData(); //獲取溫度的第一個位元組
temperatureHigh = ds18b20ReadData(); //獲取溫度的第二個位元組
disposeValue = (temperatureHigh<<4)|(temperatureLow>>4); //獲取溫度整數部分
if(disposeValue>=128) //溫度是負數
{
disposeValue = ~disposeValue+1;
tempFlag = 1;
}
temperature[0] = disposeValue; //溫度整數
temperature[1] = temperatureLow & 0x0f; //溫度小數
}
void displayTemperature()
{
write_com(0x85);
write_data((temperature[0]/100) + 0x30); //溫度百位
write_com(0x86);
write_data((temperature[0]/10%10) + 0x30); //溫度十位
write_com(0x87);
write_data((temperature[0]%10) + 0x30); //溫度個位
write_com(0x88);
write_data('.');
write_com(0x89);
write_data((temperature[1]*10/16) + 0x30); //小數第一位
// write_data((tempterature[1]*625/1000));
write_com(0x8a);
write_data((temperature[1]*100/16%10) + 0x30); //小數第二位
// write_data((tempterature[1]*625/100%10));
/* 顯示 ℃ */
write_com(0x8b);
write_data(0xdf);
write_com(0x8c);
write_data('C');
}
void main()
{
unsigned char i;
init_lcd(); //初始化1602
write_com(0x80);
for(i=0;i<5;i++)
{
write_data(array1[i]);
}
while(1)
{
readTemperature(); //讀取溫度
if(ds18b20Flag == 1) //如果初始化錯誤
{
for(i=0;i<14;i++)
{
write_com(0x80);
write_data(array[i]); //顯示DS18B20 error!
}
}
else
{
displayTemperature(); //溫度顯示
}
}
}
delay.c
/*延時20us函式*/
void delay20us() //誤差 -0.46875us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=5;a>0;a--);
}
/*延時45us函式*/
void delay45us() //誤差 -0.512152777778us
{
unsigned char a;
for(a=18;a>0;a--);
}
/*延時60us函式*/
void delay60us() //誤差 -0.321180555556us
{
unsigned char a;
for(a=25;a>0;a--);
}
/*延時480us函式*/
void delay480us() //誤差 -0.399305555556us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=218;a>0;a--);
}
/*延時50us函式*/
void delay50us() //誤差 -0.086805555556us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=19;a>0;a--);
}
/*延時240us函式*/
void delay240us() //誤差 -0.199652777778us
{
unsigned char a;
for(a=108;a>0;a--);
}
/*延時800ms函式*/
void delay800ms() //誤差 -0.000000000195us
{
unsigned char a,b,c;
for(c=175;c>0;c--)
for(b=10;b>0;b--)
for(a=209;a>0;a--);
}
delay.h
void delay15us(); //15us
void delay20us(); //20us
void delay480us(); //480us
void delay50us(); //50us
void delay240us(); //240us
void delay45us();//45us
void delay60us(); //60us
void delay800ms(); //800ms
lcd1602.c
#include <reg52.h>
#include "lcd1602.h"
#define LCD P0
sbit E = P2^7;
sbit RS = P2^6;
sbit RW = P2^5;
/******延遲5毫秒函式********/
void delay5ms() //誤差 -0.000000000001us
{
unsigned char a,b;
for(b=15;b>0;b--)
for(a=152;a>0;a--);
}
/******LCD1602寫命令函式********/
void write_com(unsigned char command)
{
RS = 0;
RW = 0; //高讀低寫
LCD = command;
delay5ms(); //這里延時最低要30納秒 我們直接給5ms
E = 1; //使能拉高
delay5ms(); //最低要求延遲150納秒 我們直接給5ms
E = 0;
}
/******LCD1602寫資料函式********/
void write_data(unsigned char dat)
{
RS = 1;
RW = 0;
LCD = dat;
delay5ms(); //這里延時最低要30納秒 我們直接給5ms
E = 1; //使能拉高
delay5ms(); //最低要求延遲150納秒 我們直接給5ms
E = 0;
}
/******初始化LCD1602********/
void init_lcd()
{
write_com(0x06); //寫入資料后游標自動右移 整屏不移動, 0x40(游標左移 整屏不移動)0x05(左移 整屏右移)0x07(右移 整屏右移)
write_com(0x0c); //開顯示功能 無游標 不閃爍
write_com(0x38); //資料總線8位 16X2顯示 5*7點陣
write_com(0x01); //清屏 0000 0001
}
lcd1602.h
void write_com(unsigned char command); //寫命令函式
void write_data(unsigned char dat); //寫資料函式
void init_lcd(); //初始化LCD1602函式
void delay5ms(); //延時5ms函式
專案展示

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/264220.html
標籤:其他
上一篇:STM32 最小系統電路簡析
