2017年12月26日 星期二

DS18B20-Read-讀個位元

跨入淺水區的第三步


二話不說,在上一步,我們知道如何寫入一個位元值到DS18B20,此篇是告訴你如何讀取DS18B20的位元值,重點仍是時間,特別是位元值"1"的取樣時間,底下將作細部說明!

從DS18B20讀取位元值

 要謮取DS18B20的位元值,最主要的關鍵是對於位元值"1"的取樣時間點的掌握,底下會先說明官方資料的內容,再作區段說明及程式碼步驟分析。

官方資料

讀取位元值的文字說明於DS18B20的Datasheet的第16頁下方(Read Time Slots),有興趣的可參考一下!

Read的時序圖


 上圖為官方文件中的第16頁中,有關讀位元的時序圖,可分為三部份,第三部份是線條示意,就不必特別介紹。

第一部分是DS18B20的時序輸出(左為位元"0"值輸出時序,右為位元"1"值的輸出時序)

第二部份中的長條狀Master(此為Arduino)讀取點。

關鍵是DS18B20給予的位元值的時間點,是在電位拉低後,1~15μs的時間點中,如果位元值為"0"時,問題不大,主要麻煩的是當位元值為"1"時,如何準確的掌握讀取的時間點,才是重點。

官方建議的讀取位元圖

  可能是讀取位元值"1"的時序很重要,當然也可能是上圖畫的不清楚,所以又給了一張[建議主機讀取時序圖],簡單的說啟始時間(Tint)及電位回復高電位(Trc)越短越好,而主機取樣點靠近信號尾端為佳。


讀取位元時序整合及關鍵

 底下將上述兩圖整合,再拆解成七個步驟來解析其讀取位元的順序及重點說明!

時序對照圖

 重點仍是放在當DS18B20給予的位元值為"1"時,如何正確的讀取其值。上圖為整體圖,而下圖為讀取位元值"1"的步驟及時序圖,其中紫色長條為Arduino的取樣時點(意謂著,當Arduino於此時點取樣時,1就是1,0就是0,不會搞錯)

區段概念分析

 在步驟分析之前,先看一下訊息區段,其實可分為四段

1-啟始訊號段:電位由高轉為低電位,等於通知DS18B20準備將位元值作輸出動作)

2-DS18B20接手段:主機放手:主機端放開電位控制,由DS18B20接手控制

3-訊息混亂段:
   位元值為"0"時,DS18B20會讓電位維持在低電位
   位元值為"1"時,DS18B20會放手讓上拉電阻將電位拉至高電位,這段時間(Trc)為混亂段,
   如果Arduino於此段(灰色段)讀取資料會出現問題

4-正確訊息段:上圖綠色的部份就是最好的取樣時段,在此區段取樣可獲得正確的位元值

關鍵步驟說明

程式碼中有附上詳細的說明,在此只提重點

1-確保讀取時序間,要有至少1μs的間隔

2-整個的讀取時序,最好是60μs

3- 步驟3/5/7的時間,可自行調整,如one wire中的設定是3/10/53,而官方建議是4/8/55,都可行,不妨都試試。

程式碼

ReadSlot()副程式中,分為7個步驟,其中fp為取樣值的變數名稱,讀取位元值並傳回。
uint8_t ReadSlot() {
 //步驟01:確保與上一個讀時序有1us的間隔
 delayMicroseconds(1);

 //步驟02:啟始信號--拉低電位
 pinMode(g_dq_pin, OUTPUT);       //轉為輸出,可達到高電位
 digitalWrite(g_dq_pin, LOW);   //將電位拉低告訴DS18B20,主機已準備好了

 //步驟03:保持低電位最少1us
 delayMicroseconds(3);

 //步驟04:釋放線路電位
 pinMode(g_dq_pin, INPUT);    //轉為輸入狀態,同時釋放線路

 //步驟05:等待時間,
 delayMicroseconds(9);     //加前面的延時,於2+9<=11us時取樣為保險值

 //步驟06:讀取slot的電位值
 uint8_t fp=digitalRead(g_dq_pin);

 //Step07:延時動作達到讀時序時段全長為60us
 delayMicroseconds(48);    //1+2+9+48=60us
 return fp;
}

基本功過關了

恭禧!到此,你已掌握了Arduino控制DS18B20的三個最基本工具:重啟、寫入一個位元值、讀取一個位元值。

下一步,我們就可以讀取溫度值了!


沒有留言:

張貼留言