基于藍橋杯的單片機模塊練習——DS18B20溫度傳感器
相關知識點
1.概況

特點:
1.單總線通訊
2.每個設備都有一個存盤在板載只讀存盤器中的唯一64位串行代碼,所以一條通訊總線可掛多個DS18B20
3.測量范圍是-55℃至+125℃,從-10℃到+85℃有±0.5℃的精度
4.溫度計解析度可由用戶從9到12位選擇
5.最慢在750毫秒內將溫度轉換為12位數字值
2.測量溫度的操作
溫度傳感器的解析度可由用戶配置為9、10、11或12位,分別對應于0.5℃、0.25℃、0.125℃和0.0625℃的增量,上電時的默認解析度為12位,
要啟動溫度測量和模數轉換,主機必須發出轉換[44h]命令,轉換后,產生的熱資料存盤在暫存存盤器的2位元組溫度暫存器中,DS18B20回傳空閑狀態,
溫度資料在溫度暫存器中存盤為16位符號擴展二進制補碼,如下圖:

符號位表示溫度是正還是負:對于正數,S = 0;對于負數,S = 1,
如果DS18B20配置為12位解析度,溫度暫存器中的所有位都將包含有效資料,對于11位解析度,位0未定義,對于10位解析度,位1和0未定義,對于9位解析度,位2、1和0未定義,
注意:
1)我們從18B20里面讀出的資料全是溫度的補碼形式,所以如果是正溫度則不需要特殊處理,如果是負溫度,那么需要把補碼做一下轉換,
【思考:-10.125 的補碼如何寫呢???】
2)溫度暫存器的上電復位值為+85℃,也就是:0000 0101 0101 0000
3.溫度計解析度配置


將資料寫入暫存位元組2、3(TH、TL和配置暫存器)和4 :【4Eh】
該命令允許主機向DS18B20的暫存區寫入3位元組的資料,第一個資料位元組寫入TH暫存器(暫存區的位元組2),第二個位元組寫入TL暫存器(位元組3),第三個位元組寫入配置暫存器(位元組4),資料必須首先以最低有效位傳輸,主機發出復位之前,必須寫入所有三個位元組,否則資料可能會損壞,
void Config_18B20()
{
init_ds18b20();
Write_DS18B20(0xcc);//跳過ROM
Write_DS18B20(0x4e);//寫暫存器指令4E
Write_DS18B20(0x7d);//寫高速快取器TH高溫限值125度
Write_DS18B20(0x00);//寫高速快取器TL低溫限值0度
Write_DS18B20(0x1f);//寫配置暫存器4
//0x1f : 0.5000°C 轉換時間93.75ms
//0x3f : 0.2000°C 轉換時間187.5ms
//0x5f : 0.1250°C 轉換時間375ms
//0x7f : 0.0625°C 轉換時間750ms
init_ds18b20();
}
note:上電默認值為R0 = 1,R1 = 1 (12位解析度)
4.訪問DS18B20的順序
注意:每次訪問DS18B20時都要遵循這個順序,這一點非常重要,因為如果序列中的任何步驟丟失或順序錯誤,DS18B20將不會回應,
step1.初始化
單線總線上的所有事務都以初始化序列開始,初始化序列由總線主機發送的復位脈沖和從機發送的存在脈沖組成,存在脈沖讓總線主設備知道從設備(如DS18B20)在總線上,并準備運行,
step2.發送ROM指令
總線主控器檢測到存在脈沖后,可以發出只讀存盤器命令,這些命令對每個從設備的唯一64位只讀存盤器代碼進行操作,如果單線總線上有多個從設備,允許主設備選擇一個特定的設備,這些命令還允許主機確定總線上有多少設備和什么型別的設備,或者是否有任何設備出現報警情況,ROM命令有5個,每個命令8位長,在發出DS18B20功能命令之前,主設備必須發出適當的只讀存盤器命令,
step3.跳過ROM【CCh】
主機可以使用該命令同時尋址總線上的所有設備,而無需發送任何只讀存盤器代碼資訊,例如,主機可以通過發出跳過只讀存盤器命令,然后發出轉換T [44h]命令,使總線上的所有DS18B20s同時執行溫度轉換,
step4.開始溫度轉換【44h】
該命令啟動單次溫度轉換,轉換后,產生的熱資料存盤在暫存存盤器的2位元組溫度暫存器中,DS18B20回傳低功耗空閑狀態,
step5.讀取溫度【BEh】
該命令允許主機讀取溫度資料,資料傳輸從位元組0的最低有效位開始,相繼通過暫存區,直到讀取完所有位元組資料,如果只需要部分資料,主機可以隨時發出復位以終止讀取,
注意,只有當總線上只有一個從設備時,讀暫存[BEh]命令才能跟隨跳過只讀存盤器命令,在這種情況下,通過允許主機從從機讀取而不發送設備的64位只讀存盤器代碼,可以節省時間,如果有一個以上的從機,跟隨讀暫存命令的跳過只讀存盤器命令將導致總線上的資料沖突,因為多個設備將試圖同時傳輸資料,
5.單總線通訊相關時序圖及如何用程式模擬
1.初始化

與DS18B20的所有通信都從初始化序列開始,該序列由來自主機的復位脈沖和來自DS18B20的存在脈沖組成,當DS18B20回應復位發送存在脈沖時,它向主機指示它在總線上,準備作業,
在初始化序列期間,總線主設備通過將單線總線拉低至少480秒來發送復位脈沖,然后,總線主設備釋放總線并進入接收模式,當總線釋放時,5k的上拉電阻將單線總線拉高,當DS18B20檢測到該上升沿時,它會等待15秒至60秒,然后通過將單線總線拉低60秒至240秒來發送存在脈沖,
//-----------------------------------------------------
//DS18B20設備初始化
bit init_ds18b20(void)
{
bit initflag = 0;//作為回傳數值
// EA = 0;防止中斷打擾時序
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);//480~960 us
DQ = 1;//釋放總線
Delay_OneWire(10); //15~60 DS18B20會來拉低總線
initflag = DQ; //讀取18B20的復位應答信號
Delay_OneWire(5);//等待60~240us總線釋放
//EA = 1;
return initflag;//應答信號為低電平,表示復位成功
}
2.寫入時序

所有寫入時隙的持續時間必須至少為60us,各個寫入時隙之間的恢復時間至少為1us,兩種型別的寫入時隙都是由主機拉低單線總線來啟動的,為了產生寫1時隙,在將單線總線拉低后,總線主設備必須在15us內釋放單線總線,當總線被釋放時,5k的上拉電阻將把總線拉高,要生成寫0時隙,在將單線總線拉低后,總線主設備必須在時隙期間(至少60us)繼續保持總線低電平,
DS18B20在主機啟動寫入時隙后持續15us至60us的時間內對單線總線進行采樣,如果在采樣視窗期間總線為高電平,則向DS18B20寫入1,如果線路為低電平,則向DS18B20寫入0,
//===============================================
//通過單總線向DS18B20寫一個位元組
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
//EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;//迅速拉低總線10~15us
DQ = dat&0x01;//要寫入的這一位是1,DQ就=1,要寫入的這位是0,DQ就等于0
Delay_OneWire(5);//延時一會20~45us,等待DS18來讀
DQ = 1;//釋放總線
dat >>= 1;//開始準備寫下一位
}
Delay_OneWire(5);
//EA = 1;
}
//===============================================
3.讀出時序

所有讀取時隙的持續時間必須至少為60us,時隙之間的恢復時間至少為1us,通過主設備將單線總線拉低至少1us,然后釋放總線,啟動讀取時隙,在主機啟動讀取時隙后,DS18B20將開始在總線上傳輸1或0,DS18B20通過保持總線高電平傳輸1,通過拉低總線傳輸0,當傳輸0時,DS18B20將在時隙結束時釋放總線,總線將被上拉電阻拉回到其高空閑狀態,
DS18B20的資料在啟動讀取時隙的下降沿后15us內有效,因此,主機必須釋放總線,然后在從插槽開始的15us內對總線狀態進行采樣,
//===============================================
//從DS18B20讀取一個位元組
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;//儲存讀取到的資料
//EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;//迅速拉低
dat >>= 1;//這是從最高位寫的,所以要相佑方移動到第一位
DQ = 1;//把這個置低,才能讓DS18來決定他便成1還是0
if(DQ)//如果讀到1,則把最高位寫1,其他位不變
{
dat |= 0x80;
}
Delay_OneWire(5);//延時45us左右,在讀取下一位
}
// EA = 1;
return dat;
}
//-----------------------------------------------------
6.比賽時需要改寫onewire驅動
/*
程式說明: 單總線驅動程式
軟體環境: Keil uVision 4.10
硬體環境: CT107單片機綜合實訓平臺(外部晶振12MHz) STC89C52RC單片機
日 期: 2011-8-9
*/
#include "onewire.h"
#include <intrins.h>
unsigned int t_data = 0x0000;
//單總線延時函式
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t *= 12;//需要把延時擴大為原來的12倍
while(t--);
}
//===============================================
//通過單總線向DS18B20寫一個位元組
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
//EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;//迅速拉低總線10~15us
DQ = dat&0x01;//要寫入的這一位是1,DQ就=1,要寫入的這位是0,DQ就等于0
Delay_OneWire(5);//延時一會20~45us,等待DS18來讀
DQ = 1;//釋放總線
dat >>= 1;//開始準備寫下一位
}
Delay_OneWire(5);
//EA = 1;
}
//===============================================
//從DS18B20讀取一個位元組
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;//儲存讀取到的資料
//EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;//迅速拉低
//_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
dat >>= 1;//這是從最高位寫的,所以要相佑方移動到第一位
DQ = 1;//把這個置高,才能讓DS18來決定他便成1還是0
if(DQ)//如果讀到1,則把最高位寫1,其他位不變
{
dat |= 0x80;
}
Delay_OneWire(5);//延時45us左右,在讀取下一位
}
// EA = 1;
return dat;
}
//-----------------------------------------------------
//DS18B20設備初始化
bit init_ds18b20(void)
{
bit initflag = 0;//作為回傳數值
// EA = 0;防止中斷打擾時序
// DQ = 1;
// Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);//480~960 us
DQ = 1;//釋放總線
Delay_OneWire(10); //15~60 DS18B20會來拉低總線
initflag = DQ; //讀取18B20的復位應答信號
Delay_OneWire(5);//等待60~240us總線釋放
//EA = 1;
return initflag;//應答信號為低電平,表示復位成功
}
void rd_temperature()
{
//unsigned char i;
unsigned char LSB = 0X00, MSB = 0X00;
init_ds18b20();
Write_DS18B20(0xcc);//跳過ROM
Write_DS18B20(0x44);//開始溫度轉換
// for(i = 125; i > 0; i--)//延時750ms
// {
// Display();
// }
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);//讀取溫度
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
t_data = MSB;
t_data <<= 8;
t_data = t_data | LSB;
if((t_data & 0xf800) == 0x0000)
{
t_data >>= 4;
t_data *= 10;
t_data = t_data + (LSB & 0x0f) * 0.625;
}
}
頭檔案onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "stc15f2k60s2.h"
#include "SEG.h"
sbit DQ = P1^4; //單總線介面
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void rd_temperature();
#endif
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/276267.html
標籤:其他
上一篇:STM32 模擬IIC源代碼 多個I2C減少冗余代碼
下一篇:STM32中斷學習筆記
