DS18B20 (by 51微控制器)
依舊是接著藍橋杯的機會來學習一下DS18B20和單匯流排技術,平臺依舊是IAP15F2K61S2微控制器
DS18B20單線數字溫度計以9位數字量的形式反映器件的溫度值,DS18B20通過一個單線介面傳送或者接受資訊,因此在中央微處理器和DS18B20之間只需要一根連線。下圖為其引腳功能說明:
器件框圖如下所示:
從圖中可以看出,DS18B20主要由三個數字部件構成,分別是64位鐳射ROM,溫度感測器,非易失性溫度報警觸發器TH和TL。
DS18B20所使用的匯流排技術為單匯流排技術,目前微控制器與外設之間進行資料傳輸的序列匯流排主要由SCI,I2C和SPI匯流排,其中SCI匯流排總是以非同步方式進行通訊(一條資料輸入線,一條資料輸出線),而I2C匯流排以同步序列二線方式進行通訊(一條時鐘線,一條資料線),SPI匯流排則以同步序列三線方式進行通訊(一條資料輸入線,一條資料輸出線)。這些匯流排都需要至少兩條或兩條以上的訊號線,而DS18B20使用的單匯流排技術與上述匯流排不同,它採用單條訊號線,既可傳輸時鐘,有可傳輸資料,而且資料傳輸是雙向的,因而這種單匯流排技術具有線路簡單,硬體開銷少,成本低廉,便於匯流排擴充套件和維護等優點。單匯流排適用於單主機系統,能夠控制一個或多個從機裝置。
還是老方法,先對DS18B20進行初始化,然後對DS18B20進行讀寫操作。
首先我們來看看控制DS18B20的指令。
33H-----讀ROM:讀DS18B20溫度感測器ROM中的編碼。
55H-----匹配ROM。發出此命令之後,接著發出64位ROM的編碼,訪問單總線上與該編碼相對應的DS18B20並使之做出響應,為下一步對該DS18B20的讀/寫做準備。
F0H-----搜尋ROM。用於確定掛接在同一總線上DS18B20的個數,識別64位ROM地址,為操作各器件做好準備。
CCH-----跳過ROM。忽略64位ROM地址,直接向DS18B20發溫度變換命令,適用於一個從機工作。
ECH-----告警搜尋命令。執行後只有溫度超過設定值上限或下限晶片才會做出反應。
以上指令是針對總線上掛接多個DS18B20的情況,但如果總線上只掛接了一個DS18B20,就不需要以上ROM指令,直接進行如下的溫度轉換和讀取操作。
44H----溫度轉換。啟動DS18B20進行溫度轉換,12位轉換時長最長為750ms,9位為93.75ms,結果存入內部9位元組的RAM中。
BEH----讀暫存器。讀內部ROM中9位元組的溫度資料。
4EH----寫暫存器。發出向內部RAM的第二三位元組寫上下線溫度資料的命令,緊跟該命令之後,是傳送兩位元組的資料。
48H----複製暫存器。將RAM中第2,3位元組的內容複製到EEPROM中。
B8H----重調EEPROM。將EEPROM中內容恢復到RAM中的第三四位元組。
B4H----讀供電方式。讀DS18B20的供電模式。寄生供電時,DS18B20傳送0;外接電源供電時,DS18B20傳送1。
和DS18B20的任何通訊都需要以初始化序列開始,初始化序列見下圖:
上圖含義如下:
1.先將資料線置高電平1
2.延時(時間要求不嚴格,但儘可能短些)
3.資料線拉到低電平0
4.延時750us(該時間範圍可以在480~960us)
5.資料線拉到高電平1
6.延時等待。如果初始化成功,則在15~60us內產生一個由DS18B20返回的低電平0,據該狀態可以確定它的存在,但是應注意,不能無限地等待,不然會使程式進入死迴圈,所以要進行超時判斷。
7.若CPU讀到資料線上的低電平0後,還有進行延時,其延時的時間從發出高電平算起至少要480us。
8.將資料線再次拉到高電平1後結束。
DS18B20寫資料,時序如下圖所示:
其含義如下:
1.資料線先置低電平0
2.延時確定的時間為15us
3.按從低位到高位的順序傳送資料(一次只發送一位)
4.延時時間為45us
5.將資料線拉到高電平1
6.重複1~5步驟,直到傳送完整個位元組
7.最後將資料線拉高到1
DS18B20讀資料,時序圖如下:
含義如下:
1.將資料線拉高到1
2.延時2us
3.將資料線拉低到0
4.延時6us
5.將資料線拉高到1
6.延時4us
7.讀資料線的狀態得到一個狀態位,並進行資料處理
8.延時30us
9.重複1~7步驟,直到讀取完一個位元組
下面我們一起分析一下藍橋杯官方給出的程式碼,如果鄙生有理解錯的地方,還望各位大牛指點。
首先是初始化函式
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1; //首先將資料線置高
Delay_OneWire(12); //短暫延時
DQ = 0; //將資料線拉到低電平
Delay_OneWire(80); //延時在480~960US之間
DQ = 1; //資料線拉回高電平
Delay_OneWire(10); // 延時等待
initflag = DQ; // initflag等於1初始化失敗
Delay_OneWire(5); //最後一個延時
return initflag;
}
其中的Delay_OneWire()函式如下所示:注意這是一段延時,但是延時t值需要根據你微控制器的一個機器週期時長來確定,否則時序會出錯,即無法讀出溫度值!!!
void Delay_OneWire(unsigned int t)
{
int i;
while(t--)
{
for(i=0;i<12;i++);
}
}
//向DS18B20寫一個位元組
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++) //重複直到傳送完整個位元組
{
DQ = 0; //資料線首先拉低
DQ = dat&0x01;
Delay_OneWire(5); //延時45us
DQ = 1; //將資料線拉回高電平1
dat >>= 1;
}
Delay_OneWire(5);
}
//從DS18B20讀取一個位元組
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++) //重複接收直到讀完整個位元組
{
DQ = 0; //資料線拉低
dat >>= 1;
DQ = 1; //資料線拉高
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
以上就是藍橋杯官方給出的程式碼,下面我給出我根據單匯流排庫寫出的溫度讀取函式:
void Read_tem(void)
{
unsigned char low,high;
char temp;
Init_DS18B20();
Write_DS18B20(0xCC); //忽略64位ROM地址,直接向DS18B20傳送溫度變換命令,適用於一個從機工作
Write_DS18B20(0x44); //溫度轉換
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE); //讀取溫度資料
low = Read_DS18B20(); //低八位
high = Read_DS18B20(); //高八位
temp = high<<4; //整合成一個位元組
temp |= (low>>4);
return temp;
}
至此,DS18B20部分就全部介紹完了,如果有錯誤,希望各位大牛指正。