51单片机---DS1802温度传感器(含源码,小白可入)

写在前面:

        在单片机的学习中,传感器作为一种最基本的外设,是初学者必须掌握的。特别是在后面做相关项目“智慧农业、智能家居等”,都会用到相关的传感器;而温度传感器是所有传感器中运用的最多的一种传感器,因此,学好温度传感器也是为后面其他的学习打好基础。

        温度传感器相关内容,包括单总线的学习,相关时序的理解以及代码的实现,成功的在LCD1602液晶屏幕上显示了温度数据,并进行了相关操作,包括:阈值的判断、阈值的调节、将其DS18B20同LCD1602、独立按键、I2C总线、EEPROM进行来联合使用,做出相应的操作;

        如果需要查看实验现象,或使用源码直接放在文末,百度网盘中!!!

        本次我们学习如何使用精度较高的外设DS18B20温度传感器,由于此传感器是单总线接口,因此我们会先介绍单总线的使用;利用51单片机的一个IO口模拟单总线时序与DS18B20通信,将检测的环境温度读取出来;

        本节要实现的功能为:

1、系统运行时,LCD1602液晶显示屏显示检测的温度值;

2、系统运行时,判断检测的温度值与设置阈值范围的比较,手动调节阈值范围,并且将设置的阈值同AT24C02联系起来,做到断电保存。 

目录

一、DS18B20介绍

1、寄生电路(电源)

2、64位ROM(身份证号)

3、暂存器

二、单总线介绍

1、初始化

2、写时序

3、读时序 

4、发送一个字节 

5、接收一个字节

三、DS18B20的使用

四、硬件电路

五、软件设计

5.1 LCD1602液晶显示屏显示检测的温度值

5.2温度传感器相关操作


一、DS18B20介绍

            DS18B20是一种常见的数字温度传感器,与传统的热敏电阻等测温元器件相比,它的优点是:体积小,适用电压宽、功能强大、硬件简单,抗干扰性强。

DS18B20特点

1、适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电。

2、独特的单线接口方式,DS18B20 在与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通信。

3、DS18B20 在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内。

4、温范围-55℃~+125℃;

下图为DS18B20的引脚图:

         其中,三根接线分别为VDD电源线、GND接地线以及DQ数据线;当使用寄生电源时,将GND与VDD相连,数据线提供电压,此时只需要两个数据线即可满足传感器要求;寄生电源的优点有:1、利用此引脚,远程温度检测无需本地电源;2、缺少电源的情况也可以读ROM;

        上图为DS18B20传感器内部框图,下面将逐块介绍:

1、寄生电路(电源)

        在上图的左侧为内部供电电路,供电方式共有两种:

        1、直接采用5V电源供电:通过VPU与上拉电阻作用,直接同寄生电源电路相连;

        2、通信线供电:器件从单总线上取得电源,在信号线为高电平器件,把能量存储在内部电容中,在信号线为低电平时断开此电源,直到信号重信接上寄生电源为止;

2、64位ROM(身份证号)

        ROM中64位序列号时出厂前被光刻好的,它可以看作是DS18B20的地址序列。64位中,前8位是产品的类型标号,中间的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(如同身份证最后一位),光刻ROM的作用是使买到的DS18B20各不相同,这样一根总线上可以挂接多个DS18B20。

3、暂存器

        暂存器的主要作用为:保证单线通信时数据的完整性,当温度传感器完成温度检测后将该测量的结果暂存于存储器中,通过发现出读暂存器内容的存储器操作命令可以获取到测量的结果。

寄存器内容地址
温度值低位0
温度值高位1
高温限值(TH)2
低温限值(TL)3
配置寄存器4
保留5
保留6
保留7
CRC校验值8

后面是对暂存器中的内容做出说明: 

  温度传感器(读取温度值)

  高低温限值

        在DS18B20完成温度转化后,温度值与存储在TH和TL的触发值进行比较,TH与TL的最高位直接对应16为数据的最高位,如果温度测试的值高于TH或低于TL,那么器件内告警标志位将置位。

  配置寄存器(确定精度)

        配置寄存器是配置不同的位数来确定温度和数字的转化,其结构为:

TMR1R011111

        低5位一直都是“1”,TM为出厂设置。R1 和 R0 用来设置 DS18B20 的精度(分辨率),可设置为 9,10,11 或 12 位,(00.01.10.11)对应的分辨率温度是 0.5℃,0.25℃,0.125℃和 0.0625℃.

        CRC

        用于产生校验码,同主机进行确认数据字节的传送。

二、单总线介绍

         单总线通信,顾名思义即只需要一根通信线即可实现数据的双向传输,采用实时供电时,还可以省去VDD。如何通过一根通信线实现双方通信,这就对时序的要求十分严格,同I2C相同。

电路规范:

1、设备DQ均要配置成开漏输出模式(达到各个设备的相互干扰最小);

2、DQ添加一个上拉电阻;当所有的设备都不工作时,总线被上拉置高电平;

3、若此总线的从机采用寄生供电,则主机还应该配备一个强上拉的输出电路(增强IO口的驱动能力);

电路相关部分,建议参考之前的I2C部分,两者有异曲同工之妙;

CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/134191210单总线时序:

1、初始化

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

unsigned char OneWire_Init()//初始化DS1802
{
            unsigned char i;//定义延时函数需要的参数;
            unsigned char  ACK;//定义从机产生的答应脉冲
                OneWire_IO=1;//先将总线拉高;
                OneWire_IO=0;//主机输出低电平
                i = 227;while (--i);//延时500us
                OneWire_IO=1;//主机释放总线,外部上拉电阻将总线拉高;
                i = 20;while (--i);//延时50us;
                ACK=OneWire_IO;//从机对主机进行应答;
                i = 227;while (--i);//延时500us;
    return ACK;//返回从机对主机的应答;
}       

2、写时序

        写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次 独立的写时序之间至少需要 1us 的恢复时间,两种写时序均起始于主机拉低总线

写 1 时序:主机输出低电平,延时 2us,然后释放总线,延时 60us。

写 0 时序:主机输出低电平,延时 60us,然后释放总线,延时 2us。

void OneWire_Sendbit(unsigned char Bit)//写一个位数据;
{
                unsigned char i;//定义延时函数需要的参数
                OneWire_IO=0;   //起始主机拉低总线; 
                i = 3;while (--i);//  延时10us;
                OneWire_IO= Bit;//主机输出低电平或高电平;
                i = 22;while (--i);//  延时50us; 
                OneWire_IO=1;//主机释放总线;
}

 

3、读时序 

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

unsigned char OneWire_ReceiveBit()//读取一位数据
{
                unsigned char Bit;//定义读取的返回值;
                unsigned char i;//定义延时所需要的变量;
                OneWire_IO=0;    //主机发起拉低总线信号;
                i = 2;while (--i);//延迟5us
                OneWire_IO=1;//主机释放总线;
                i = 2;while (--i);//延迟5us;
                Bit=OneWire_IO;//主机读取总线的值;
                i = 22;while (--i);//  延时50us;
                return Bit;//返回主机读取的值;
}

 

4、发送一个字节 

        连续调用8次发送一位的时序,依次发送一个字节(低位在前,高位在后);

void OneWire_SendByte(unsigned char Byte)
{
            unsigned char i;
            for(i=0;i<8;i++)
                { 
                    OneWire_Sendbit(Byte&(0x01<<i));//依次发送一个字节的每一位,低位在前;
                }

5、接收一个字节

        连续调用8次接收一位的时序,依次接收一个字节(低位在前,后位在后);

unsigned char OneWire_ReceiveByte()
{
            unsigned char Byte=0x00;
            unsigned char i;
            for(i=0;i<8;i++)
                { 
                if(OneWire_ReceiveBit()) {Byte|=(0x01<<i);}//依次接收一个字节的每一位,低位在前;
                }
                return  Byte;
}

三、DS18B20的使用

 一般通过初始化+ROM指令+功能指令来实现;

初始化:从机复位,主机判断,从机是否响应;

ROM操作:ROM指令+本指令需要的读写操作;

功能操作:功能指令+本指令需要的读写操作;

其中: 

SKIP ROM [CCh] 

允许总线控制器不用提供 64 位 ROM 编码就使用功能指令;

CONVERT T [44h] (温度转换指令)

用于启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以 2 个字节的形式被存储在高速暂存器中。

READ SCRATCHPAD [BEh] (读暂存器指令)

这条命令读取暂存器的内容。

温度变化:初始化——跳过ROM——开始温度变化;

void DS18B20_ConverT()//温度转化;
{
         OneWire_Init();//初始化
         OneWire_SendByte(0xcc);//跳过ROM;
         OneWire_SendByte(0x44);//温度变化;
}

温度读取: 初始化——跳过ROM——读暂存器——连续的读操作;

float  DS18B20_ReadT()//温度读取
{
            unsigned char TLSB,TMSB;//定义相关变量
            int Temp;  float T;
            OneWire_Init();//初始化;
            OneWire_SendByte(0xcc);//跳过ROM;
            OneWire_SendByte(0xBE);//读暂存器
            TLSB=OneWire_ReceiveByte();//读取温度第一个字节;
            TMSB=OneWire_ReceiveByte();//读取温度第二个字节;
            Temp=(TMSB<<8)|TLSB;//整和温度值;
            T=Temp/16.0;//温度换算;
            return T;//返回温度值;
}

四、硬件电路

 本次实验用到的硬件电路如下:

1、LCD1602液晶显示屏(实验1)

2、DS18B20(实验1)

3、独立按键(实验1、2)

4、EEPROM(实验1、2)

        其他电路在之前的博客中都有介绍,大家可以去学习使用: 

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

五、软件设计

5.1 LCD1602液晶显示屏显示检测的温度值

实验要求:利用DS18B20进行温度检测,并将检测的值进行显示;

源码:

main.c

#include <REGX52.H>//包含51头文件
#include "LCD1602.h"//包含LCD1602头文件
#include "DS18B20.h"//包含DS18B20头文件
float T;//定义浮点数温度
void main()
{
	LCD_Init();	//LCD1602初始化
	LCD_ShowString(1,1,"Temperature: ");//显示格式
		while(1)
		{
							DS18B20_ConverT();//DS18B20温度转变函数
							T= DS18B20_ReadT();//DS18B20温度读取函数
			if(T<0)//判断温度的正负(-55至125℃)
			{			
						LCD_ShowString(2,1,"-");
						T=-T;
						LCD_ShowNumber(2,2,T,3);//进行数据显示整数部分
						LCD_ShowString(2,5,".");
						LCD_ShowNumber(2,6,(unsigned long)(T*10000)%10000,4);//进行数据显示,小数部分,先乘再取余
	   	}
			else
			{
					LCD_ShowString(2,1,"+");
					LCD_ShowNumber(2,2,T,3);/进行数据显示整数部分
					LCD_ShowString(2,5,".");
					LCD_ShowNumber(2,6,(unsigned long)(T*10000)%10000,4);//进行数据显示,小数部分,先乘再取余
			}
		}
}

DS18B20.c

#include <REGX52.H>//包含51头文件
#include "one_wire.h"//包含单总线头文件
/**
   *@breaf 
   *@param 无
   *@retval 无
   */
void DS18B20_ConverT()
{
		OneWire_Init();
	    OneWire_SendByte(0xcc);
	    OneWire_SendByte(0x44);
}
/**
   *@breaf 
   *@param 无
   *@retval T 返回测量的温度
   */
float  DS18B20_ReadT()
{
			unsigned char TLSB,TMSB;
			int Temp;
			float T;
			OneWire_Init();
			OneWire_SendByte(0xcc);
			OneWire_SendByte(0xBE);
			TLSB	=OneWire_ReceiveByte();
			TMSB=OneWire_ReceiveByte();
			Temp=(TMSB<<8)|TLSB;
			T=Temp/16.0;
			return T;
}

one_wire.c

#include <REGX52.H>
//定义端口
sbit  OneWire_IO=P3^7;
/**
   *@breaf 单总线初始化函数
   *@param 无
   *@retval  ACK  从机响应主机
   */
unsigned char OneWire_Init()
{
			unsigned char i;
			unsigned char  ACK;	
				OneWire_IO=1;
				OneWire_IO=0;//主机将总线拉低:至少480us;用来产生复位脉冲;
				i = 227;while (--i);//延时500us;
				OneWire_IO=1;//主机释放总线;外部上拉电阻将单总线拉高;
				i = 20;while (--i);//延时50us;
				ACK=OneWire_IO;//从机对主机的响应;
				i = 227;while (--i);//延时500us;
	return ACK;
}

/**
   *@breaf 单总线发送一位数据
   *@param  Bit发送的数据
   *@retval 无
   */
void OneWire_Sendbit(unsigned char Bit)
{
				unsigned char i;
				OneWire_IO=0;	
				i = 3;while (--i);//	延迟10us;
				OneWire_IO= Bit;
				i = 22;while (--i);//	延迟50us;
				OneWire_IO=1;
}

/**
   *@breaf  单总线接收一位数据
   *@param 无
   *@retval Bit总线接受到的数据
   */
unsigned char OneWire_ReceiveBit()
{
				unsigned char Bit;
				unsigned char i;
				OneWire_IO=0;	//主机拉低总线;
				i = 2;while (--i);//延迟5us;
				OneWire_IO=1;//主机释放总线;
				i = 2;while (--i);//延迟5us;
				Bit=OneWire_IO;//主机读取总线的值;
				i = 22;while (--i);//	延迟50us;
				return Bit;
}
/**
   *@breaf 单总线发送一个字节数据
   *@param  Byte发送的数据
   *@retval 无
   */
void OneWire_SendByte(unsigned char Byte)
{
			unsigned char i;
			for(i=0;i<8;i++)
				{ 
					OneWire_Sendbit(Byte&(0x01<<i));//依次将一个字节的每一位发送给内部;低位在前,高位在后;
				}
}
/**
   *@breaf 单总线接收一个字节的数据 
   *@param 无
   *@retval Byte接收到的数据
   */
unsigned char OneWire_ReceiveByte()
{
			unsigned char Byte=0x00;
			unsigned char i;
			for(i=0;i<8;i++)
				{ 
				if(OneWire_ReceiveBit()) {Byte|=(0x01<<i);}
				}
				return  Byte;
}

实验现象:

温度显示

实验代码:

链接:https://pan.baidu.com/s/1akFSmSJllPG90rdqdka9oQ 
提取码:1022

5.2温度传感器相关操作

 实验要求:

1、显示温度;

2、显示阈值(高阈值、低阈值);

3、判断温度与阈值的关系,并将判断结果显示;

4、按键控制阈值(K1:高阈值+1;K2:高阈值-1;K3:低阈值+1;K4:低阈值-1);

5、将阈值存于EEPROM,做到断电不丢失;

实验源码:

main.c

#include <REGX52.H>//包含对应头文件
#include "DS18B20.h"
#include "LCD1602.h"
#include "I2C.h"
#include "key.h"
#include "delay.h"
#include  "AT24C02.h"

char THigh,Tlow;
unsigned char keynumber;
float Temp,T;
void main()
{
	THigh=AT24C02_ReadByte(0);
	Tlow=AT24C02_ReadByte(1);
	if(THigh>125||	Tlow<-55||THigh<=Tlow)
	{THigh=25;Tlow=10;}
		 LCD_Init();	
		 LCD_ShowString(1,1,"T:");
		LCD_ShowString(2,1,"TH:");
		LCD_ShowString(2,9,"TL:");
		LCD_ShowNumber(2,4,THigh,4);
		LCD_ShowNumber(2,12,Tlow,4);
			
while(1)
		{
			keynumber=key_scan();
			//温度读取及显示;
				DS18B20_ConverT();
			T=DS18B20_ReadT();
			if(T<0)
			{
				LCD_ShowString(1,3,"-");
			 T=-T;
				LCD_ShowNumber(1,4,T,3);
				LCD_ShowString(1,7,".");
				LCD_ShowNumber(1,8,(unsigned long)(T*100)%100,3);
			}
			else 
			{
				LCD_ShowString(1,3,"+");
				LCD_ShowNumber(1,4,T,3);
				LCD_ShowString(1,7,".");
				LCD_ShowNumber(1,8,(unsigned long)(T*100)%100,3);
			}
			//阈值判断及显示;
			if(keynumber)
			{
						if(keynumber==1)
							{
								THigh++;
								if(THigh>125)
								{THigh=125;}
							}
							
						if(keynumber==2)
						{
							THigh--;
							if(THigh<Tlow)
							{THigh++;}
						}
						
						if(keynumber==3)
							{
							Tlow++;
							if(Tlow>THigh)
							{Tlow--;}
						}
							
						if(keynumber==4)
						{
							Tlow--;
							if(Tlow<-55)
								{Tlow=-55;}
						}
				 LCD_ShowSignedNum(2,4,THigh,3);
				 LCD_ShowSignedNum(2,12,Tlow,3);
							AT24C02_WriteByte(0,THigh);
						Delay1ms(5);
							AT24C02_WriteByte(1,Tlow);
						Delay1ms(5);
							
			}		
			//阈值判断;
			Temp=DS18B20_ReadT();
			if(Temp>THigh)
				LCD_ShowString(1,13,"H ");
			else if(Temp<Tlow)
				LCD_ShowString(1,13,"L ");
			else
				LCD_ShowString(1,13,"OK");
		}
}

此处,仅有main.c文件同之前不同,其余文件均与前方相同,故不在此进行讲解,源码如下方网盘;

实验现象:

温度传感器相关操作


实验源码:

链接:https://pan.baidu.com/s/1g2cty1YVV3cndDq9Ifm8BA 
提取码:1022

总结: 本节我们学习了温度传感器相关内容,包括单总线的学习,相关时序的理解以及代码的实现,成功的在LCD1602液晶屏幕上显示了温度数据,并进行了相关操作,包括:阈值的判断、阈值的调节、将其DS18B20同LCD1602、独立按键、I2C总线、EEPROM进行来联合使用,做出相应的操作;大家看完之后,一定需要自己练习练习,这样才能更好的接收;

最后,创作不易,还请大家多多点赞支持!!!

能力有限,如有错误,欢迎留言讨论!!!

  • 24
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
#include #define uchar unsigned char #define uint unsigned int sbit led=P2^5; sbit wei=P2^7; sbit duan=P2^6; sbit DQ=P2^2; uchar mazhi_duan[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; uchar mazhi_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xff}; void delayl(uint n) { uint i,j; for(i=n;i>0;i--) for(j=114;j>0;j--); } void delays(uchar i) { while(i--); } bit init_DS18B20() //DS8B20初始化 { bit x; DQ=1; //DQ复位 delays(8); DQ=0; //单片机将DQ拉低 delays(75); DQ=1; //拉高总线 delays(15); x=DQ; //延时过后 若x=0则初始化成功 若x=1则初始化失败 delays(5); return x; } void write_data(uchar dat) { uchar i,temp; temp=dat; DQ=1; for(i=0;i>=1; } } uchar read_data() { uchar i,dat; DQ=1; for(i=0;i>=1; DQ=1;//配置为输入 if(DQ) dat|=0x80; delays(4); } return dat; } uint readtemp() { uchar temph,templ; uint temp; float wendu; init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0x44);//启动温度转换 //delayl(100); init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0xBE);//读温度 //以下读温度,低八位在前 //高8位在后 templ=read_data(); temph=read_data(); temp = (temph<<8)|templ; wendu = temp*0.625+0.5;//温度扩大10倍,四舍五入 temp = wendu;//10倍温度 return temp; } void STC_init() { P1=0x00;//关闭led led=0; //锁存 wei=0; duan=0; } void display(uchar weil,uchar duanl,bit dp) { wei=1; P0=mazhi_wei[weil-1]; wei=0; duan=1; if(dp==1) P0=(mazhi_duan[duanl]|0x80); else P0=mazhi_duan[duanl]; duan=0; } void main() { uchar i; uint wendu; STC_init(); wendu=readtemp(); delayl(500); wendu=readtemp(); delayl(500); while(1) { wendu=readtemp(); for(i=0;i<80;i++) { display(1,wendu/100,0); delayl(3); display(2,wendu0/10,1); delayl(3); display(3,wendu,0); delayl(3); } } }
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值