DS18B20温度传感器

DS18B20介绍

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

特点

  1. 适应电压范围宽
  2. 单线接口
  3. 支持多点组网功能
  4. 不需要其他外围原件
  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 温度传感器的内部存储器包括一个高速的暂存器 RAM 和一个非易失性的可电擦除的 EEPROM,后者存放高温度和低温度触发器 TH、 TL 和配置寄存器。

配置寄存器是配置不同的位数来确定温度和数字的转化
 

 低五位一直都是"1", TM 是测试模式位, 用于设置 DS18B20 在工作模式还是在测试模式。 在 DS18B20 出厂时该位被设置为 0, 用户不需要去改动。 R1 和R0 用来设置 DS18B20 的精度(分辨率) , 可设置为 9, 10, 11 或 12 位, 对应的分辨率温度是 0.5℃, 0.25℃, 0.125℃和 0.0625℃。

R0 和 R1 配置如下
 

 在初始状态下默认的精度是 12 位, 即 R0=1、 R1=1。 高速暂存存储器由 9 个字节组成, 其分配如下:

 当温度转换命令(44H) 发布后, 经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第 0 和第 1 个字节。 存储的两个字节, 高字节的前 5 位是符号位 S, 单片机可通过单线接口读到该数据, 读取时低位在前, 高位在后。

 如果测得的温度大于 0, 这 5 位为‘ 0’ , 只要将测到的数值乘以 0.0625(默认精度是 12 位) 即可得到实际温度; 如果温度小于 0, 这 5 位为‘ 1’ ,测到的数值需要取反加 1 再乘以 0.0625 即可得到实际温度。 温度与数据对应关系如下:

 比如我们要计算+85 度, 数据输出十六进制是 0X0550, 因为高字节的高 5位为 0, 表明检测的温度是正温度, 0X0550 对应的十进制为 1360, 将这个值乘以 12 位精度 0.0625, 所以可以得到+85 度。

DS18B20 发送所有的命令和数据都是字节的低位在前。

(1)初始化时序

单总线上的所有通信都是以初始化序列开始。 主机输出低电平, 保持低电平时间至少 480us(该时间的时间范围可以从 480 到 960 微妙) , 以产生复位脉冲。 接着主机释放总线, 外部的上拉电阻将单总线拉高, 延时 15~60 us, 并进入接收模式。 接着 DS18B20 拉低总线 60~240 us, 以产生低电平应答脉冲, 若为低电平, 还要做延时, 其延时的时间从外部上拉电阻将单总线拉高算起最少要480 微妙。 初始化时序图如下:

 (2)写时序

写时序包括写 0 时序和写 1 时序。 所有写时序至少需要 60us, 且在 2 次独立的写时序之间至少需要 1us 的恢复时间, 两种写时序均起始于主机拉低总线。 写 1 时序: 主机输出低电平, 延时 2us, 然后释放总线, 延时 60us。 写 0时序: 主机输出低电平, 延时 60us, 然后释放总线, 延时 2us。 写时序图如下:
 

(3)读时序

 单总线器件仅在主机发出读时序时, 才向主机传输数据, 所以, 在主机发出读数据命令后, 必须马上产生读时序, 以便从机能够传输数据。 所有读时序至少需要 60us, 且在 2 次独立的读时序之间至少需要 1us 的恢复时间。 每个读时序都由主机发起, 至少拉低总线 1us。 主机在读时序期间必须释放总线, 并且在时序起始后的 15us 之内采样总线状态。 读时序图如下:

 典型的读时序过程为: 主机输出低电平延时 2us, 然后主机转入输入模式延时 12us, 然后读取单总线当前的电平, 然后延时 50us。

在了解了单总线时序之后, 我们来看看 DS18B20 的典型温度读取过程,DS18B20 的典型温度读取过程为: 复位→发 SKIP ROM 命令(0XCC) →发开始转换命令(0X44) →延时→复位→发送 SKIP ROM 命令(0XCC) →发读存储器命令(0XBE) →连续读出两个字节数据(即温度)→结束。

硬件

开发板上
DS18B20 模块电路

从上图可以看出, 传感器接口的单总线管脚接至单片机 P3.7 IO 口上, 在介
绍单总线的时候我们说过, 为了让单总线默认为高电平, 通常会在单总线上接上
拉电阻, 在图中并没有看到有上拉电阻, 这是因为单片机 IO 都外接了 10K 上拉
电阻, 当单片机 IO 口连接到传感器的总线管脚时即相当于它们外接上拉电阻。

软件设计

//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--);
}
//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;//消音
	}
}

与之前数码管显示驱动程序不同的就是红色加粗标记的那条语句, 可以看到此处没有直接使用数码管段码数据, 而是通过外部提供处理好的数码管段码数据传入进来, 这样可使数码管显示更加灵活, 后面实验我们都将采用这种方式。 因为要让外部提前处理好数码管段码数据, 所以段码数组 gsmg_code 就要定义为全局变量, 需在 smg.h 头文件中声明下即可: extern u8 gsmg_code[17];

//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;
}

 

//main.c
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
PRECHIN
 普中

实验名称:DS18B20温度传感器实验
接线说明:	
实验现象:下载程序后,插上DS18B20温度传感器,数码管显示检测的温度值
注意事项:注意温度传感器的方向,在接口处我们已经用丝印画了一个凸起,
		  所以只需要将温度传感器对应插入即可																				  
***************************************************************************************/
#include "public.h"
#include "smg.h"
#include "ds18b20.h"


/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	u8 i=0;
   	int temp_value;
	u8 temp_buf[5];

	ds18b20_init();//初始化DS18B20

	while(1)
	{				
		i++;
		if(i%50==0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间
			temp_value=ds18b20_read_temperture()*10;//保留温度值小数后一位
		if(temp_value<0)//负温度
		{
			temp_value=-temp_value;
			temp_buf[0]=0x40;//显示负号	
		}
		else
			temp_buf[0]=0x00;//不显示
		temp_buf[1]=gsmg_code[temp_value/1000];//百位
		temp_buf[2]=gsmg_code[temp_value%1000/100];//十位
		temp_buf[3]=gsmg_code[temp_value%1000%100/10]|0x80;//个位+小数点
		temp_buf[4]=gsmg_code[temp_value%1000%100%10];//小数点后一位
		smg_display(temp_buf,4);
	}		
}

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值