一、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 的 E² 存储器,把温度触发器字节存入非易失性存储器;若总线主机发此命令后读时间片,DS1820 在复制时总线输出 "0",完成后输出 "1";若为寄生电源供电,主机发命令后需立即强制上拉至少 10ms。
- 温度变换(Convert T)[44h]:启动温度变换,无需额外数据;若总线主机发此命令后读时间片,DS1820 变换时总线输出 "0",完成后输出 "1";若为寄生电源供电,主机发命令后需立即强制上拉至少 2 秒。
- 重新调出 E2(Recall E2)[B8h]:把 E² 中温度触发器的值调回暂存存储器(器件上电时也会自动执行该操作,所以上电后暂存存储器就有有效数据);发此命令后,第一个读数据时间片,器件输出 "0" 表示 "忙","1" 表示 "准备就绪"。
- 读电源(Read Power Supply)[B4h]:发此命令后,第一个读出数据的时间片,器件会给出电源方式信号:"0" 表示寄生电源供电,"1" 表示外部电源供电。
四、DS1820的时序图
1.初始化(检测芯片是否能用)

方法:先给51单片机低电平,如果可以检测到一个低电平,一个高电平,芯片就是好的
cs
#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
cs
#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
cs
#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
cs
#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
cs
#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; //12MHz
TL1 = 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++);
}
}