———————————————————————————————————————————— 1-Wire匯流排 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...
————————————————————————————————————————————
1-Wire匯流排
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 只使用一根導線(地址線、數據線、控制線合一)
- 可以傳輸時鐘和數據
- 雙向傳輸
- 信號線上可掛許多測控對象,電源也由這根信號線提供
-
適用於單Master,多個Slave。
- 當只有一個Slave時,系統按照單節點系統操作
- 當有多個Slave時,系統按照多節點系統操作
-
優點:
-
綜合性:
- 感測器、控制器、輸入/輸出設備均可按1-Wire協議接入網路
-
簡捷性:
- 1-Wire單匯流排的設置和安裝只需一條普通三芯電線連接至各從機接入點
- 當系統需要增加Slave時,只需要從該匯流排拉出延長線即可
-
可靠性:
- 每個從機均有絕對唯一的地址碼
- 數據傳輸均採用CRC校驗碼
- 1-Wire單匯流排上傳輸的是數字信號
-
綜合性:
- 缺點:傳輸速率較低
————————————————————————————————————————————
DS18B20
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 改進型智能數字溫度感測器
- 只需要一根導線就能讀出被測溫度,並實現雙向通信
- 根據需求實現9-12位數字值的讀數方式,精度分別為0.5,0.25,0.125,0.0625
- 適應電壓範圍寬,電壓範圍為3.0-5.5V,寄生電源方式下可由數據線供電
- 支持多點組網功能,多個DS18B20通過並聯方式,實現多點組網測溫
- 不需要任何外圍元件,感測元件及轉換電路已經集成了
- 溫度範圍-55~+125℃,在-10~+85℃時,精度為±0.5℃
- 轉換速度較快。在9位解析度時,最多在93.75ms內把溫度轉換為數字,12位解析度時最多在750ms內把溫度值轉換為數字
- 測試結果直接輸出數字溫度信號,以一條匯流排串列傳送給CPU,同時可傳送CRC校驗碼,具有極強的抗干擾糾錯能力
- 負壓特性,當電源極性接反時,晶元不會因發熱而燒毀,但也無法正常工作
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
三種封裝形式及引腳說明
- 當信號線DQ為高電平時,DQ為晶元供電,並且內部電容器儲存電能
- 當信號線DQ為低電平時,內部電容器為晶元供電,直至下一個高電平到來重新充電
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
內部結構:
-
64位ROM
- 廠家激光刻錄的一個64位二進位ROM代碼,是該晶元的標號
8位迴圈冗餘檢驗 |
48位序列號 |
8位分類編號(10H) |
MSB ... LSB |
MSB ... LSB |
MSB ... LSB |
- 8位分類編號:10H,是DS18B20的分類號
-
溫度感測器
- 溫度範圍-55~+125℃。9-12位解析度,轉換精度分別為0.5,0.25,0.125,0.0625
- 出廠時預設為16位轉換精度
-
當接收到溫度轉換命令(44H)後開始轉換,轉換完成後的溫度以16位帶符號擴展的二進位補碼形式表示。存儲在高速緩存器RAM的第0、1位元組中,二進位數的前5位為符號位。
- 如果溫度>0,則該5位為0,只要將測到的數值乘上0.0625即可得到實際溫度。
- 如果溫度<0,則該5位為1,測到的數值需要取反+1再乘上0.0625。
-
高速緩存器:包含以下兩個組件
-
高速暫存器RAM:連續8位元組的存儲器
- 前2位元組是測得的溫度信息,第1位元組存放溫度的低8位,第2位元組存放溫度的高8位
- 第3/4/5位元組分別是高溫觸發器、低溫觸發器、配置寄存器的易失性複製
- 前5位元組的內容在每次上電覆位時被刷新
- 第6/7/8位元組用於暫時保留為1
-
非易失性可電擦除EEPROM
-
高速暫存器RAM:連續8位元組的存儲器
-
配置寄存器
- 用於確定溫度值的數字轉換解析度,按此寄存器的解析度將溫度轉換為相應精度的數值,是高速緩存器的第5個位元組
- 該位元組定義:
TM |
R0 |
R1 |
1 |
1 |
1 |
1 |
1 |
- TM是測試模式位,用於設置DS18B20在工作模式還是測試模式。工作模式時該位為0,用戶不必改動。R1和R0用來設置解析度,其餘5位均固定為1。
- 解析度設置:
R1 |
R0 |
解析度 |
最大轉換時間/ms |
0 |
0 |
9位 |
93.75 |
0 |
1 |
10位 |
187.5 |
1 |
0 |
11位 |
375 |
1 |
1 |
12位 |
750 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
測溫工作原理:由以下部分組成
-
斜率累加器:
- 用於補償和修正測溫過程中的非線性
- 其輸出用於修正減法計數器的預置值
-
溫度繫數振蕩器:
- 用於產生減法計數器脈衝信號
- 低溫度繫數振蕩器受溫度的影響很小,用於產生固定頻率的脈衝信號送給減法計數器1
- 高溫度繫數振蕩器受溫度的影響較大,隨溫度的變化,其振蕩頻率明顯改變,產生的信號作為減少計數器2的輸入脈衝
-
減法計數器
- 減法計數器1對低溫度繫數振蕩器產生的脈衝信號進行減法計數,當減法計數器1的預置值減到0時,溫度寄存器的值將+1。
- 之後,減法計數器1的預置將重新被裝入。減法計數器1重新開始對低溫度繫數振蕩器產生的脈衝信號進行計數,迴圈操作直到減法計數器2計數減到0,才會停止溫度寄存器的值的累加。此時,溫度寄存器中的數值即為所測溫度。
- 只要計數門未關閉就重覆上述過程,直至溫度寄存器的值達到被測溫度值。
-
溫度寄存器
- 暫存溫度數值
-
計數門
- 當計數門打開時,DS18B20就對低溫繫數震蕩器產生的時鐘脈衝進行計數,從而完成溫度測量。
- 開啟時間由高溫度繫數振蕩器決定。
- 每次測量前,首先將-55℃所對應的基數分別置入減法計數器1和高溫寄存器中,減法計數器1和溫度寄存器被預置在-55℃所對應的一個基數值。
p.s. 每個晶元的信息交換是分時完成的,均有嚴格的讀/寫是時序要求,系統對DS18B20的操作協議為:
初始化DS18B20(發複位脈衝)→ 發ROM功能命令 → 發存儲器操作命令 → 處理數據
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ROM命令
操作 |
命令代碼 |
詳細說明 |
讀ROM |
33H |
允許主設備讀出64位二進位ROM代碼 只適用於匯流排上存在單隻DS18B20 |
匹配ROM |
55H |
若匯流排上有多個Slave,使用該命令可以選中某一指定的DS18B20,即只有與64位二進位ROM代碼完成匹配的DS18B20才能響應其操作 |
跳過ROM |
CCH |
啟動所有DS18B20轉換之前或系統只有一個DS18B20時,該命令允許Master不提供64位二進位ROM代碼就使用存儲器操作命令 |
搜索ROM |
F0H |
確定系統中的Slave個數及其ROM代碼 |
報警搜索ROM |
ECH |
鑒別和定位系統中超出程式設定的報警溫度值 |
寫暫存器 |
4EH |
允許Master向DS18B20的暫存器寫入2個位元組的數據 可以在任何時刻發出複位命令中止數據寫入 |
讀暫存器 |
BEH |
允許主設備讀取暫存器的內容,從第1個位元組開始,直到CRC讀完第9個位元組。也可以在任何時刻發出複位命令中止數據的讀取操作 |
複製暫存器 |
48H |
將高溫觸發器和低溫觸發器中的位元組複製到非易失性EEPROM 若主機在該命令之後又發出讀操作,而DS18B20正忙於複製過程時,DS18B20會輸出一個0,複製結束時DS18B20會發出一個1。 如果使用寄生電源,則主設備發出該命令之後,立即發出強上拉並至少保持10ms以上時間。 |
溫度轉換 |
44H |
啟動一次溫度轉換 若主機在該命令之後又發出其他操作,DS18B20正忙於溫度轉換,則輸出一個0,轉換結束則輸出一個1,。 若使用寄生電源,則Master發出該命令之後,立即發出強上拉並至少保持500ms以上的時間。 |
複製回暫存器 |
B8H |
將高溫觸發器和低溫觸發器的位元組從EEPROM複製回暫存器中。 若忙,同上 |
讀電源使用模式 |
B4H |
Master將該命令發給DS18B20後發出讀操作,DS18B20會返回它的電源使用模式:0為寄生電源,1為外部電源 |
————————————————————————————————————————————
基於1-Wire的DS18B20測量溫度的實例
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
實現效果:
實現代碼:
1 #include <reg52.h> 2 typedef unsigned char uchar; 3 typedef unsigned int uint; 4 uchar code table[] = 5 { 6 0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6, 0xee, 0x3e, 0x9c 7 }; 8 uchar code address[] = 9 { 10 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f 11 }; 12 sbit DQ = P3 ^ 0; //DQ控制位 13 sbit dot = P1 ^ 0; //小數點 14 uchar temp1, temp2; //通過temp1和temp2存儲溫度低位和高位 15 16 void Delay(uint m) 17 { 18 while(m--); 19 } 20 uchar ReadByte() 21 { 22 uchar byte = 0; 23 uchar i; 24 for (i = 0; i < 8; ++i) 25 { 26 DQ = 0; 27 byte >>= 1; 28 DQ = 1; 29 if (DQ) 30 byte = byte | 0x80; 31 Delay(4); 32 } 33 return byte; 34 } 35 void WriteByte(uchar byte) 36 { 37 uchar i; 38 for (i = 0; i < 8; ++i) 39 { 40 DQ = 0; 41 byte >>= 1; //數據左移 42 DQ = CY; 43 Delay(5); 44 DQ = 1; 45 } 46 } 47 void Init() 48 { 49 DQ = 1; 50 Delay(8); 51 DQ = 0; 52 Delay(80); 53 DQ = 1; 54 Delay(20); 55 } 56 void ReadTemp() 57 { 58 /* 初始化DS18B20 */ 59 Init(); 60 WriteByte(0xcc); //跳過ROM,當前只有一個Slave 61 WriteByte(0x44); //啟動溫度轉換 62 Delay(10); 63 Init(); 64 WriteByte(0xcc); //跳過ROM 65 WriteByte(0xbe); //讀取暫存器內容 66 temp1 = ReadByte(); //低位存放在temp1中 67 temp2 = ReadByte(); //高位存放在temp2中 68 } 69 void main() 70 { 71 bit flag; 72 uint temp; 73 uchar i; 74 while(1) 75 { 76 /* 讀取溫度 */ 77 ReadTemp(); 78 79 /* 溫度轉化 */ 80 temp = temp1 & 0x0f; //temp存入溫度低8位並保留低4位 81 if (temp2 > 127) //temp2 > 01111111時,溫度為負 82 { 83 flag = 1; 84 temp1 = ~temp1; 85 temp2 = ~temp2; //高低各取反 86 temp = temp1 & 0x0f; 87 temp += 0x01; //取反後+1,得到負數值 88 } 89 temp = temp * 625; 90 temp1 = temp1 & 0xf0; 91 temp1 = temp1 / 16; 92 temp2 = temp2 * 16; 93 temp1 += temp2; 94 if (flag) 95 temp1 += 0x01; 96 97 /* 溫度顯示 */ 98 for (i = 0; i < 4; ++i) 99 { 100 P2 = address[i]; 101 P1 = table[temp % 10]; 102 Delay(750); 103 temp = temp / 10; 104 } 105 P2 = 0xef; 106 P1 = table[temp1 % 10]; 107 dot = 1; 108 Delay(750); 109 if (temp1 / 100 || temp1 / 10) 110 { 111 P2 = 0xdf; 112 P1 = table[temp1 / 10 % 10]; 113 Delay(750); 114 } 115 if (temp1 / 100) 116 { 117 P2 = 0xbf; 118 P1 = table[temp1 / 100 % 10]; 119 Delay(800); 120 } 121 if (flag) 122 { 123 P2 = 0x7f; 124 P1 = 0x02; 125 Delay(750); 126 flag = 0; 127 } 128 } 129 }