DS18B20****介绍
DS18B20 是由 DALLAS 半导体公司推出的一种的"一线总线(单总线)"接 口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、 适用电压宽、与微处理器接口简单的数字化温度传感器。
DS18B20 温度传感器具有如下特点:
- 适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据 线供电。
- 独特的单线接口方式,DS18B20 在与微处理器连接时仅需要一条口线即 可实现微处理器与 DS18B20 的双向通讯。
- DS18B20 支持多点组网功能,多个 DS18B20 可以并联在唯一的三线上, 实现组网多点测温。
- DS18B20 在使用中不需要任何外围元件,全部传感元件及转换电路集成 在形如一只三极管的集成电路内。
- 温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃
- 可编程的分辨率为 9~12 位,对应的可分辨温度分别为 0.5℃、0.25℃、0.125℃、0.0625℃,可实现高精度测温。
- 在 9 位分辨率时最多在 93.75ms 内把温度转换为数字,12 位分辨率时 最多在 750ms 内把温度值转换为数字,速度更快。
- 测量结果直接输出数字温度信号,以"一根总线"串行传送给 CPU,同时 可传送 CRC 校验码,具有极强的抗干扰纠错能力。
- 负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
DS18B20 管脚

- 管脚 1 为 GND
- 管脚 2 为 DQ(数据)
- 管脚 3 为 VDD
如果把传感器插反,那么电源将短路,传感器就会发烫, 很容易损坏,所以一定要注意传感器方向。
DS18B20 序列号
ROM 中的 64 位序列号是出厂前被光刻好的,它可以看作是该 DS18B20 的 地址序列号。64 位光刻 ROM 的排列是:开始 8 位(28H)是产品类型标号,接 着的 48 位是该 DS18B20 自身的序列号,最后 8 位是前面 56 位的循环冗余校 验码。光刻 ROM 的作用是使每一个 DS18B20 都各不相同,这样就可以实现一根 总线上挂接多个 DS18B20 的目的。
示例代码
smg.h
#ifndef _smg_H
#define _smg_H
#include "public.h"
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
extern u8 gsmg_code[17];
void smg_display(u8 dat[],u8 pos);
#endif
smg.c
#include "smg.h"
//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]=
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};
/*******************************************************************************
* 函 数 名 : smg_display
* 函数功能 : 动态数码管显示
* 输 入 : dat:要显示的数据
pos:从左开始第几个位置开始显示,范围1-8
* 输 出 : 无
*******************************************************************************/
void smg_display(u8 dat[],u8 pos)
{
u8 i=0;
u8 pos_temp=pos-1;
for(i=pos_temp;i<8;i++)
{
switch(i)//位选
{
case 0: LSC=1;LSB=1;LSA=1;break;
case 1: LSC=1;LSB=1;LSA=0;break;
case 2: LSC=1;LSB=0;LSA=1;break;
case 3: LSC=1;LSB=0;LSA=0;break;
case 4: LSC=0;LSB=1;LSA=1;break;
case 5: LSC=0;LSB=1;LSA=0;break;
case 6: LSC=0;LSB=0;LSA=1;break;
case 7: LSC=0;LSB=0;LSA=0;break;
}
SMG_A_DP_PORT=dat[i-pos_temp];//传送段选数据
delay_10us(100);//延时一段时间,等待显示稳定
SMG_A_DP_PORT=0x00;//消影
}
}
ds18b20.h
#ifndef _ds18b20_H
#define _ds18b20_H
#include "public.h"
//管脚定义
sbit DS18B20_PORT=P3^7; //DS18B20数据口定义
//函数声明
u8 ds18b20_init(void);
float ds18b20_read_temperture(void);
#endif
ds18b20.c
#include "ds18b20.h"
#include "intrins.h"
/*******************************************************************************
* 函 数 名 : ds18b20_reset
* 函数功能 : 复位DS18B20
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds18b20_reset(void)
{
DS18B20_PORT=0; //拉低DQ
delay_10us(75); //拉低750us
DS18B20_PORT=1; //DQ=1
delay_10us(2); //20US
}
/*******************************************************************************
* 函 数 名 : ds18b20_check
* 函数功能 : 检测DS18B20是否存在
* 输 入 : 无
* 输 出 : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 ds18b20_check(void)
{
u8 time_temp=0;
while(DS18B20_PORT&&time_temp<20) //等待DQ为低电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
else time_temp=0;
while((!DS18B20_PORT)&&time_temp<20) //等待DQ为高电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
return 0;
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_bit
* 函数功能 : 从DS18B20读取一个位
* 输 入 : 无
* 输 出 : 1/0
*******************************************************************************/
u8 ds18b20_read_bit(void)
{
u8 dat=0;
DS18B20_PORT=0;
_nop_();_nop_();
DS18B20_PORT=1;
_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
if(DS18B20_PORT)dat=1; //如果总线上为1则数据dat为1,否则为0
else dat=0;
delay_10us(5);
return dat;
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_byte
* 函数功能 : 从DS18B20读取一个字节
* 输 入 : 无
* 输 出 : 一个字节数据
*******************************************************************************/
u8 ds18b20_read_byte(void)
{
u8 i=0;
u8 dat=0;
u8 temp=0;
for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
{
temp=ds18b20_read_bit();
dat=(temp<<7)|(dat>>1);
}
return dat;
}
/*******************************************************************************
* 函 数 名 : ds18b20_write_byte
* 函数功能 : 写一个字节到DS18B20
* 输 入 : dat:要写入的字节
* 输 出 : 无
*******************************************************************************/
void ds18b20_write_byte(u8 dat)
{
u8 i=0;
u8 temp=0;
for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
{
temp=dat&0x01;//选择低位准备写入
dat>>=1;//将次高位移到低位
if(temp)
{
DS18B20_PORT=0;
_nop_();_nop_();
DS18B20_PORT=1;
delay_10us(6);
}
else
{
DS18B20_PORT=0;
delay_10us(6);
DS18B20_PORT=1;
_nop_();_nop_();
}
}
}
/*******************************************************************************
* 函 数 名 : ds18b20_start
* 函数功能 : 开始温度转换
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds18b20_start(void)
{
ds18b20_reset();//复位
ds18b20_check();//检查DS18B20
ds18b20_write_byte(0xcc);//SKIP ROM
ds18b20_write_byte(0x44);//转换命令
}
/*******************************************************************************
* 函 数 名 : ds18b20_init
* 函数功能 : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输 入 : 无
* 输 出 : 1:不存在,0:存在
*******************************************************************************/
u8 ds18b20_init(void)
{
ds18b20_reset();
return ds18b20_check();
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_temperture
* 函数功能 : 从ds18b20得到温度值
* 输 入 : 无
* 输 出 : 温度数据
*******************************************************************************/
float ds18b20_read_temperture(void)
{
float temp;
u8 dath=0;
u8 datl=0;
u16 value=0;
ds18b20_start();//开始转换
ds18b20_reset();//复位
ds18b20_check();
ds18b20_write_byte(0xcc);//SKIP ROM
ds18b20_write_byte(0xbe);//读存储器
datl=ds18b20_read_byte();//低字节
dath=ds18b20_read_byte();//高字节
value=(dath<<8)+datl;//合并为16位数据
if((value&0xf800)==0xf800)//判断符号位,负温度
{
value=(~value)+1; //数据取反再加1
temp=value*(-0.0625);//乘以精度
}
else //正温度
{
temp=value*0.0625;
}
return temp;
}
public.h
#ifndef _public_H
#define _public_H
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
void delay_10us(u16 ten_us);
void delay_ms(u16 ms);
#endif
public.c
#include "public.h"
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
DS18B20 内部寄存器
DS18B20内部寄存器地址和功能,核心都集中在其 9字节高速暂存器(Scratchpad) 中。它没有像单片机SFR那样的固定物理地址,而是通过单总线协议进行顺序读写。
📋 DS18B20内部寄存器地址与功能列表
| 字节序号 (逻辑地址) | 寄存器名称 | 功能描述 | 读写 属性 | 备注 |
|---|---|---|---|---|
| Byte 0 | 温度低字节 (Temp LSB) | 存储温度值的低8位。 | 只读 | 与Byte 1共同组成16位补码格式的温度数据。 |
| Byte 1 | 温度高字节 (Temp MSB) | 存储温度值的高8位。 | 只读 | 高5位为符号位,后3位为温度整数部分。 |
| Byte 2 | 高温报警上限 (TH) | 用户可设置的报警温度上限值。 | 读写 | 断电后可通过EEPROM保存。 |
| Byte 3 | 低温报警下限 (TL) | 用户可设置的报警温度下限值。 | 读写 | 断电后可通过EEPROM保存。 |
| Byte 4 | 配置寄存器 | 控制温度转换的分辨率。 | 读写 | 具体位定义见下方详解。断电后可保存。 |
| Byte 5 | 保留 | 供内部使用, 读取值通常为0xFF。 |
只读 | - |
| Byte 6 | 保留 | 供内部使用, 读取值通常为0xFF。 |
只读 | - |
| Byte 7 | 保留 | 供内部使用, 读取值通常为0xFF。 |
只读 | - |
| Byte 8 | CRC校验字节 | 前8个字节(Byte 0-7)的循环冗余校验码。 | 只读 | 用于验证数据传输的正确性。 |
⚙️ 关键寄存器详解与操作要点
1. 配置寄存器 (Byte 4)
| bit7 | bit6 (R1) | bit5 (R0) | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|
| TM | R1 | R0 | 1 | 1 | 1 | 1 | 1 |
-
TM (bit7) :测试模式位。出厂固定为
0,切勿改动。 -
R1, R0 (bit6-5):分辨率设置位。决定了测量的精度和转换所需时间。关系如下:
-
R1R0 = 00: 9位分辨率,转换时间 93.75 ms。 -
R1R0 = 01: 10位分辨率,转换时间 187.5 ms。 -
R1R0 = 10: 11位分辨率,转换时间 375 ms。 -
R1R0 = 11: 12位分辨率,转换时间 750 ms(默认值)。
-
2. 温度读取与换算
温度数据(Byte 0, 1)以16位二进制补码格式存储。
在实际使用中,最简便的计算公式是:实际温度 = 读取的16位有符号整数 × 0.0625
3. 非易失性存储器(EEPROM)与暂存器的关系
TH、TL和配置寄存器(Byte 2-4),除了在暂存器中有"易失性"的拷贝外,在芯片内部还有一份非易失性EEPROM(断电不丢失)用于永久存储。它们之间的数据转移通过专用命令完成:
-
写入流程: 通过
Write Scratchpad (0x4E)命令将数据写入暂存器(Byte 2-4),然后使用Copy Scratchpad (0x48)命令将数据从暂存器复制到EEPROM进行保存。 -
读取/恢复流程: 上电时,EEPROM中的值会自动恢复到暂存器的对应位置。也可以通过
Recall EEPROM (0xB8)命令手动恢复。
完结,撒花~~~