一、DS18B20芯片

   DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
   测温范围:-55°C 到 +125°C
   通信接口:1-Wire(单总线)
   其它特征:可形成总线结构、内置温度报警功能、可寄生供电
  在这里插入图片描述

   1、引脚

    在这里插入图片描述

   2、应用电路

    在这里插入图片描述

   3、内部结构

    在这里插入图片描述

     1)、64位激光ROM:

       ROM 中的 64 位序列号是出厂前被光刻好的,它可以看作是该 DS18B20 的地址序列号。
       64 位光刻 ROM 的排列是:
         开始 8 位(28H)是产品类型标号,接着的48 位是该 DS18B20 自身的序列号,最后 8 位是前面 56 位的循环冗余校验码。
        在这里插入图片描述
       光刻 ROM 的作用是使每一个 DS18B20 都各不相同,这样就可以实现一根总线上挂接多个DS18B20 的目的。

     2)、配置寄存器:

       是配置不同的位数来确定温度和数字的转化.
       配置寄存器结构:
        在这里插入图片描述

       低5位:
         低5位一直是“1”
       TM:
         TM是测试模式位,用于设置DS18B20在工作模式还是测试模式。
       R1和R0:
         用来设置DS18B20的精度(分辨率),可以设置为9,10,11,12位,对应的分辨率温度是0.5℃,0.25℃,0.125℃和 0.0625℃。
        在这里插入图片描述

     3)、高速暂存器RAM:

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

       当温度转换命令(44H)发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第 0 和第 1 个字节。
      在这里插入图片描述

       存储的两个字节,高字节的前 5 位是符号位S,单片机可通过单线接口读到该数据,读取时低位在前,高位在后。
         如果SSSSS为“0”,为温度不小于0,将测得数值乘以0.0625即可得到实际温度。
         如果SSSSS为“1”,为温度小于0,将测得数值取反加1再乘以0.0625即可得到实际温度。
        在这里插入图片描述

二、单总线

  参考《通讯协议–OneWire单总线》

三、DS18B20

   1、操作流程

	初始化:从机复位,主机判断从机是否响应。
	ROM操作:ROM指令+本指令需要的读写操作。
	功能操作:功能指令+本指令需要的读写操作。

   2、操作命令

    在这里插入图片描述

     1)、初始化

       单线总线上的所有处理沟从初始化序列开始。
       初始化序列包括总线主机发出一复位脉冲,接着由从属器件送出存在脉冲。

     2)、ROM指令:Read ROM(读ROM)[33h]

       此命令允许总线主机读DS1820的8位产品系列编码,唯一的48位序列号,以及8位的CRC。
       此命令只能在总线上仅有一个DS1820的情况下可以使用。

     3)、ROM指令:Match ROM(“符合”ROM)[55h]

       “符合”ROM命令。
       后继以64位的ROM数据序列,允许总线主机对多点总线上特定的DS1820寻址。
       只有与 64位ROM序列严格相符的DS1820才能对后继的存贮器操作命令作出响应。

     4)、ROM指令:Skip ROM(“跳过”ROM)[CCh]

       在单点总线系统中,此命令通过允许总线主机不提供64位ROM编码而访问存储器操作来节省时间。

     5)、ROM指令:Alarm Search(告警搜索)[ECh]

       此命令的流程与搜索ROM命令相同。
       但是,仅在最近一次温度测量出现告警的情况下,DS1820才对此命令作出响应。
       告警的条件定义为温度高于TH或低于L。
       只要DS1820一上电,告警条件就保持在设置状态,直到另一次温度测量显示出非告警值,或者改变TH或T的设置使得测量值再一次位于允许的范围之内。
       贮存在EEPROM内的触发器值用于告警。

     6)、读暂存存储器(Read Scratchpad) [BEh]

       此命令读暂存存储器的内容。读开始于字节0,并继续经过暂存存储器,直至第九个字节(字节8,CRC)被读出为止。
       如果不是所有位置均可读,那么主机可以在任何时候发出一复位以中止读操作。

     7)、写暂存存储器(Write Scratchpad) [4Eh]

       此命令写至DS1820的暂存存储器,以地址2开始。
       接着写的两个字节将被保存在暂存存储器地址2和3之间中。
       发出一个复位便可在任何处终止写操作。

     8)、复制暂存存储器(Copy Scratchpad) [48h]

       此命令把暂存存储器复制入DS1820的E存储器,把温度触发器字节存贮入非易失性存储器。
       如果总线主机在此命令之后发出读时间片,那么只要DS1820正忙于把暂存存储器复制入E,它就会在总线上输出“0”:当复制过程完成之后,它将反回“1”。
       如果由寄生电源供电,总线主机在发出此命令之后必须能立即强制上拉至少10ms。

     9)、温度变换(Convert T) [44h]

       此命令开始温度变换。不需要另外的数据。
       温度变换将被执行,接着DS1820便保持在空闲状态。
       如果总线主机在此命令之后发出读时间片,那么只要DS1820正忙于进行温度变换,它将在总线上输出“0”;当温度变换完成时,它便返回“1”。
       如果由寄生电源供电,那么总线主机在发出此命令之后必须立即强制上拉至少2秒。

     10)、重新调出E2(Recall E2) [B8h]

       此命令把贮存在E中温度触发器的值重新调至暂存存储器,这种重新调出的操作在对DS1820上电时也自动发生,因此只要器件一接电,暂存存储器内就有有效的数据可供使用。
       在此命令发出之后,对于所发出的第一个读数据时间片,器件都将输出其忙的标志“0”=忙,“1”=准备就绪。

     11)、读电源(Read PowerSupply) [B4h]

       对于在此命令送至DS1820之后所发出的第一读出数据的时间片,器件都会给出其电源方式的信号:“0”=寄生电源供电,“1”=外部电源供电。

   3、数据帧

     温度变换:
       初始化→跳过ROM →开始温度变换。
      在这里插入图片描述

     温度读取:
       初始化→跳过ROM →读暂存器→连续的读操作。
      在这里插入图片描述

   4、软件思路

     1)、复位

			/***********
			*函数名: ds18b20_reset
			*函数功能:复位DS18B20
			*输入:无
			*输出:无
			**********/
			void ds18b20_reset(void)
			{
			DS18B20_PORT=0; //拉低DQ
			delay_10us(75); //拉低750us
			DS18B20_PORT=1; //DQ=1
			delay_10us(2); //20US
			}

     2)、检测DS18B20是否存在

			/***********
			*函数名: 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;
			}

     3)、读取温度

			/********************************************************************
			***********
			*函数名: 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;
			}

     4)、温度转换

			/********************************************************************
			***********
			*函数名: ds18b20_start
			*函数功能:开始温度转换
			*输入:无
			*输出:无
			*********************************************************************
			**********/
			void ds18b20_start(void)
			{
			ds18b20_reset();//复位
			ds18b20_check();//检查DS18B20
			ds18b20_write_byte(0xcc);//SKIP ROM
			ds18b20_write_byte(0x44);//转换命令
			}

四、代码实例

   1、ds18b20

		#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

   2、ds18b20

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

   3、mian.c

		#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);
		        }                
		}

更多推荐