普中51单片机学习笔记-DS18B20温度传感器

DS18B20****介绍

DS18B20 是由 DALLAS 半导体公司推出的一种的"一线总线(单总线)"接 口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、 适用电压宽、与微处理器接口简单的数字化温度传感器。

DS18B20 温度传感器具有如下特点:

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

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) 命令手动恢复。

完结,撒花~~~

相关推荐
知识分享小能手18 小时前
CentOS Stream 9入门学习教程,从入门到精通,CentOS Stream 9 配置网络功能 —语法详解与实战案例(10)
网络·学习·centos
瑶光守护者19 小时前
【学习笔记】5G RedCap:智能回落5G NR驻留的接入策略
笔记·学习·5g
你想知道什么?19 小时前
Python基础篇(上) 学习笔记
笔记·python·学习
SHOJYS19 小时前
学习离线处理 [CSP-J 2022 山东] 部署
数据结构·c++·学习·算法
weixin_4093831219 小时前
简单四方向a*学习记录4 能初步实现从角色到目的地寻路
学习·a星
xian_wwq20 小时前
【学习笔记】可信数据空间的工程实现
笔记·学习
浩瀚地学20 小时前
【Arcpy】入门学习笔记(五)-矢量数据
经验分享·笔记·python·arcgis·arcpy
Li.CQ20 小时前
SQL学习笔记
笔记·sql·学习
jtymyxmz20 小时前
《Maya 2024 超级学习手册》3.4.8 实例:制作垃圾桶模型
学习·maya
jtymyxmz20 小时前
《Maya 2024 超级学习手册》3.4.6 实例:制作小筐模型
学习·maya