一、DS1820的引腳
DS1820單總線數字溫度計:異步串行半雙工
特性:
? ? ? ? 1)獨特的單線接口,只需 1 個接口引腳即可通信
? ? ? ? 2)多點(multidrop)能力使分布式溫度檢測應用得以簡化
? ? ? ? 3)不需要外部元件
? ? ? ? 4)可用數據線供電
? ? ? ? 5)不需備份電源
? ? ? ? 6)測量范圍從 - 55℃至 + 125℃,增量值為 0.5℃。等效的華氏溫度范圍是 - 67°F 至 257°F,增量值為 0.9°F
? ? ? ? 7)以 9 位數字值方式讀出溫度
? ? ? ? 8)在 1 秒(典型值)內把溫度變換為數字
? ? ? ? 9)用戶可定義的,非易失性的溫度告警設置
? ? ? ? 10)告警搜索命令識別和尋址溫度在編定的極限之外的器件(溫度告警情況)
應用范圍包括恒溫控制,工業系統,消費類產品,溫度計或任何熱敏系統
51單片機和DS1820是線與關系,數據接受方需要釋放總線->電平的高低由對方決定
上拉電阻通常在4.7k~10k,雙方在釋放總線時,保證線是高電平
二、ROM操作命令??
Read ROM (讀 ROM) [33h]:允許總線主機讀 DS1820 的 8 位產品系列編碼、唯一的 48 位序列號,以及 8 位的 CRC。僅能在總線上僅有一個 DS1820 時使用;若存在多個從屬器件,所有從片同時發送會發生數據沖突(漏極開路產生 “線與” 結果)。
Match ROM (“符合” ROM) [55h]:命令后緊跟 64 位 ROM 數據序列,允許總線主機對多點總線上特定的 DS1820 尋址。只有與 64 位 ROM 序列嚴格相符的 DS1820,才會對后繼存貯器操作命令響應;不符的從片會等待復位脈沖。總線上有單個或多個器件時都可使用。
Skip ROM (“跳過” ROM) [0Ch]:在單點總線系統中,允許總線主機不提供 64 位 ROM 編碼就訪問存儲器操作,以此節省時間。若總線上有多個從屬器件,且在該命令后發讀命令,多個從片同時發數據會引發總線數據沖突(漏極開路下拉產生 “線與” 效果)。
Search ROM (搜索 ROM) [F0h]:系統剛工作時,總線主機可能不清楚單線總線上的器件個數或 64 位 ROM 編碼。此命令允許主機用 “消去”(elimination) 處理,識別總線上所有從片的 64 位 ROM 編碼。
Alarm Search (告警搜索) [ECh]:流程與 “搜索 ROM” 命令相同,但僅當 DS1820 最近一次溫度測量出現告警(溫度高于 TH 或低于 TL)時,才會對此命令響應。DS1820 上電后,告警條件會保持,直到溫度測量顯示非告警值,或修改 TH/TL 設置使測量值回到允許范圍;EEPROM 內的觸發器值用于告警。
三、DS1820的寄存器
- 讀暫存存儲器(Read Scratchpad)[BEh]:讀取暫存存儲器內容,從字節 0 開始,直到字節 8(CRC);若并非所有位置都可讀,主機可隨時發復位中止讀操作。
- 復制暫存存儲器(Copy Scratchpad)[48h]:將暫存存儲器內容復制到 DS1820 的 E2 存儲器,把溫度觸發器字節存入非易失性存儲器;若總線主機發此命令后讀時間片,DS1820 在復制時總線輸出 “0”,完成后輸出 “1”;若為寄生電源供電,主機發命令后需立即強制上拉至少 10ms。
- 溫度變換(Convert T)[44h]:啟動溫度變換,無需額外數據;若總線主機發此命令后讀時間片,DS1820 變換時總線輸出 “0”,完成后輸出 “1”;若為寄生電源供電,主機發命令后需立即強制上拉至少 2 秒。
- 重新調出 E2(Recall E2)[B8h]:把 E2 中溫度觸發器的值調回暫存存儲器(器件上電時也會自動執行該操作,所以上電后暫存存儲器就有有效數據);發此命令后,第一個讀數據時間片,器件輸出 “0” 表示 “忙”,“1” 表示 “準備就緒”。
- 讀電源(Read Power Supply)[B4h]:發此命令后,第一個讀出數據的時間片,器件會給出電源方式信號:“0” 表示寄生電源供電,“1” 表示外部電源供電。
四、DS1820的時序圖
1.初始化(檢測芯片是否能用)
方法:先給51單片機低電平,如果可以檢測到一個低電平,一個高電平,芯片就是好的
#include <reg52.h>
#include <intrins.h>#define DS18B20_SET (P3 |= (1 << 7)) //拉高
#define DS18B20_CLEAR (P3 &= ~(1 << 7)) //拉低
#define DS18B20_TST ((P3 & (1 << 7)) != 0) //判斷 高電平void Delay10us(unsigned int n) //@12.000MHz
{unsigned char data i;_nop_();_nop_();_nop_();i = 2 * n;while (--i){_nop_();}
}int reset_ds18b20(void)
{int t = 0;DS18B20_CLEAR;Delay10us(50);DS18B20_SET;Delay10us(2);while(DS18B20_TST && t < 25){Delay10us(1);++t;}if(t >= 25){return 0;}t = 0;while(!DS18B20_TST && t < 20){Delay10us(1);++t;}if(t >= 20){return 0;}return 1;
}int main(void)
{int t = reset_ds18b20();if(1 == t){P2 = 0;}else{P2 = 0xFF;}while(1){}return 0;
}
溫度讀取
main.c
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#include <string.h>
#include "uart.h"
#include "delay.h"
#include "ds18b20.h"int main(void)
{ xdata char s[24];init_uart();while(1){float f;f = get_temperatuer();sprintf(s, "%f", f);send_buffer(s, strlen(s));}return 0;
}
delay.c
#include "delay.h"
#include <intrins.h>
void delay(unsigned int n)//0~65526
{while(n--);
}void Delay10us(unsigned int n) //@12.000MHz
{unsigned char data i;_nop_();_nop_();_nop_();i = 2 * n;while (--i){_nop_();}
}void delay_1ms(unsigned int n)
{while(n--){Delay10us(100);}
}
ds18b20.c
#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "ds18b20.h"static int reset_ds18b20(void)
{int t;DS18B20_CLEAR;Delay10us(70);DS18B20_SET;Delay10us(4);t = 0;while(DS18B20_TST && t < 30){Delay10us(1);++t;}if(t >= 30){return 0;}t = 0;while(!DS18B20_TST && t < 30){Delay10us(1);++t;}if(t >= 30){return 0;}return 1;
}void ds18b20_write(unsigned char n) //0x01010 110 & 0000 0001
{int i;for(i = 0;i < 8;++i){if(n & 0x01) // 1{DS18B20_CLEAR;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();DS18B20_SET;Delay10us(5); }else{DS18B20_CLEAR;Delay10us(6);DS18B20_SET;}n >>= 1; }
}unsigned char ds18b20_read(void)
{unsigned char ret = 0;int i;for(i = 0;i < 8;++i){DS18B20_CLEAR;_nop_();_nop_();DS18B20_SET;_nop_();_nop_();_nop_();_nop_();if(DS18B20_TST){ret |= 1 << i; }Delay10us(5); }return ret;
}float get_temperatuer(void)
{unsigned char tl, th;short t;reset_ds18b20();ds18b20_write(0xCC);ds18b20_write(0x44);delay_1ms(750);reset_ds18b20();ds18b20_write(0xCC);ds18b20_write(0xBE);tl = ds18b20_read();th = ds18b20_read();t = tl;t |= th << 8;return t * 0.0625;
}
uart.c
#include "uart.h"
#include <reg52.h>xdata char rcv_buffer[64] = {0};
int pos = 0;void init_uart(void)
{unsigned char t;t = SCON;t &= ~(3 << 6);t |= (1 << 6) | (1 << 4);SCON = t;PCON |= (1 << 7);IE |= (1 << 7) | (1 << 4);t = TMOD;t &= ~(3 << 4);t |= (2 << 4);t &= ~(3 << 6);TMOD = t;TH1 = 204; //12MHzTL1 = 204;TCON |= (1 << 6);
}void uart_handler(void) interrupt 4
{if((SCON & (1 << 0)) != 0){rcv_buffer[pos++] = SBUF;SCON &= ~(1 << 0);}
}void send_char(char ch)
{SBUF = ch;while((SCON & (1 << 1)) == 0);SCON &= ~(1 << 1);
}void send_buffer(const char *p, int len)
{while(len--){send_char(*p++);}
}