• 【蓝桥杯单片机】五、DS18B20


    1、DS18B20基本介绍

    S18B20 采用一线通信接口(DQ)。因为一线通信接口,必须在先完成 ROM 设定,否则记忆和控制功能将无法使用。主要首先提供以下功能命令之一∶读ROMROM匹配搜索 ROM跳过ROM报警检查。这些指令操作作用在没有一个器件的64 位光刻 ROM序列号,可以在挂在一线上多个器件选定某一个器件,同时总线也可以知道总线上挂有多少,是什么样的设备。
    若指令成功地使 DS18B20完成温度测量,数据存储在 DS18B20的存储器
    一个控制功能指挥指示DS18B20的演出测温。测量结果将被放置在 DS18B20
    内存中,并可以让阅读发出记忆功能的指挥,阅读内容的片上存储器。温度报警
    触发器 TH和 TL都有一字节 EEPROM 的数据
    。如果 DS18B20不使用报警检查
    指令,这些寄存器可作为一般的用户记忆用途。在片上还载有配置字节以理想的
    解决温度数字转换。写 TH、TL 指令以及配置字节利用一个记忆功能的指令完成。
    通过缓存器读寄存器。所有数据的读,写都是从最低位开始。
    DS18B20 的存储器包括高速暂存器 RAM可电擦除 RAM,可电擦除 RAM
    又包括温度触发器 TH和 TL,以及一个配置寄存器。存储器能完整的确定一线
    端口的通讯,数字开始用写寄存器的命令写进寄存器,接着也可以用读寄存器的
    命令来确认这些数字
    。当确认以后就可以用复制寄存器的命令来将这些数字转移
    到可电擦除 RAM 中
    。当修改过寄存器中的数时,这个过程能确保数字的完整性。
    高速暂存器 RAM是由 8个字节的存储器组成,用读寄存器的命令能读出第九个
    字节,这个字节是对前面的八个字节进行校验。
    注∶某些非官方板子采用的是劣质的 DS18B20温度传感器,需先声明延时函数,
    再将延时函数体放至所有驱动函数之后,才能正常使用

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    2、写时序和读时序

    在这里插入图片描述
    延时函数

    void Delay_OneWire(unsigned int t)  
    {
     	t *= 12;
    	while(t--);
    }
    

    2.1、写时序

    由两种写时序:写 1 时序和写 0 时序
    所有写时序必须最少持续 60us
    包括两个写周期之间至少 1us 的恢复时间
    当总线控制器把数据线从逻辑高电平拉到低电平的时候,写时序开始。
    总线控制器要生产一个写时序,
    必须把数据线拉到低电平然后释放在写时序开始后的 15us 释放总线
    总线被释放的时候,5K 的上拉电阻将拉高总线
    总控制器要生成一个写 0 时序,必须把数据线拉到低电平并持续保持(至少 60us)
    总线控制器初始化写时序后,DS18B20 在一个 15us 到 60us 的窗口内对 I/O 线采 样
    如果线上是高电平,就是写 1
    如果线上是低电平,就是写 0

    void Write_DS18B20(unsigned char dat)
    {
    	unsigned char i;
    	for(i=0;i<8;i++)
    	{
    		DQ = 0; //先拉低
    		DQ = dat&0x01; //开始写 取最低位
    		Delay_OneWire(5); //保持
    		DQ = 1; //释放总线
    		dat >>= 1; //把次第位移至最低位
    	}
    	Delay_OneWire(5); //一个字节写完再延时一会
    }
    

    2.2、读时序

    总线控制器发起读时序时,DS18B20 仅被用来传输数据给控制器
    因此,总线控 制器在发出读暂存器指令[BEh]或读电源模式指令[B4H]后必须立刻开始读时序,DS18B20可以提供请求信息。除此之外,总线控制器在发出发送温度转换指令[44h]或召回 EEPROM 指令[B8h]之后读时序。
    所有读时序必须最少 60us,包括两个读周期间至少 1us 的恢复时间
    当总线控制器把数据线从高电平拉到低电平时
    读时序开始,数据线必须至少保持 1us,然 后总线被释放。在总线控制器发出读时序后,DS18B20 通过拉高或拉低总线上来传输 1 或 0
    当传输逻辑 0 结束后,总线将被释放,通过上拉电阻回 到上升沿状态。从 DS18B20 输出的数据在读时序的下降沿出现后 15us 内有效。因此,总线控制器在读时序开始后必须停止把 I/O 脚驱动为低电平 15us,以读取I/O 脚状态

    unsigned char Read_DS18B20(void)
    {
    	unsigned char i;
    	unsigned char dat;
      
    	for(i=0;i<8;i++)
    	{
    		DQ = 0; //拉低
    		dat >>= 1;
    		DQ = 1; //释放
    		if(DQ){dat |= 0x80;}	//读   
    		Delay_OneWire(5); //延迟一段时间
    	}
    	return dat;
    }
    

    3、操作步骤

    3.1、 初始化

    在初始化序列期间,总线控制器拉低总线并保持 480us 以发出(TX)一个复位脉 冲,然后释放总线,进入接收状态(RX)。单总线由 5K 上拉电阻拉到高电平。当DS18B20 探测到 I/O 引脚上的上升沿后,等待 15-60us,然后发出一个由 60-240us低电平信号构成的存在脉冲。
    在这里插入图片描述

    bit init_ds18b20(void)
    {
      	bit initflag = 0;
      	
      	DQ = 1; //释放总线
      	Delay_OneWire(12); //保持一端时间
      	DQ = 0; //拉低总线
      	Delay_OneWire(80); //延时大于480us
      	DQ = 1; //释放总线
      	Delay_OneWire(10);  //等待一段时间
        initflag = DQ;    //读取DQ
      	Delay_OneWire(5);
      
      	return initflag; //0表示初始化成功
    }
    
    

    3.2、ROM操作指令

    在这里插入图片描述

    3.3、DS18B20功能指令

    在这里插入图片描述

    3.4、DS18B20 读温度

    unsigned int Read_Temp(void)
    {
    	unsigned char low,high;
    	init_ds18b20();
    	Write_DS18B20(0xcc); //跳过ROM
    	Write_DS18B20(0x44);
    
    	init_ds18b20();
    	Write_DS18B20(0xcc); //跳过ROM
    	Write_DS18B20(0xbe); //读暂存器
    	low = Read_DS18B20();
    	high = Read_DS18B20();
    
    	return (high<<8)+low; //构成16位数据
    	
    }
    

    4、DS18B20操作练习

    用DS18B20读取温度,并用数码管显示
    main.c

    #include "STC15F2K60S2.h"
    #include "onewire.h"
    #include "intrins.h"
    
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    uchar dsp_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    
    uchar dsp_temp[8]={0xff,0xff,0xff,0xff,0xff};
    
    uint temp;
    uint count_temp;
    
    
    void time0_init(void)
    {
      AUXR |= 0x80;
      TMOD &= 0XF0;
      TL0 = 0xCD;
      TH0 = 0XD4;
      TR0=1;
      ET0=1;
      EA=1;
    }
    
    void time0_isr() interrupt 1
    {
      static uchar dsp_com = 0;
      
      P0=0,P2=0xc0,P2=0;
      P0=dsp_temp[dsp_com],P2=0xe0;P2=0;
      P0=1<<dsp_com;P2=0xc0,P2=0;
      
      if(++dsp_com==8) dsp_com=0;
      
      ++count_temp;
    }
    
    void main()
    {
      uchar i=0;
      
      P0=0xff,P2=0x80,P2=0;
      P0=0x00,P2=0xa0,P2=0;
      
      for(i=0;i<70;i++) //待温度读取稳定后再显示
      {
        temp = read_temp()*100+0.5;
      }
      
      time0_init();
      
      while(1)
      {
        //如果未配置精度,默认为最大精度一12位,其最大转换时间为750ms。
        
        if(count_temp>749)
        {
          count_temp=0;
          temp = Read_Temp()*100+0.5;
        }
        dsp_temp[4]=dsp_code[temp/1000];
        dsp_temp[5]=dsp_code[temp/100%10] &0x7F;
        dsp_temp[6]=dsp_code[temp/10%10];
        dsp_temp[7]=dsp_code[temp%10];
      }
    }
    

    onewire.c

    #include "onewire.h"
    
    void Delay_OneWire(unsigned int t)  ;
    
    void Write_DS18B20(unsigned char dat)
    {
    	unsigned char i;
    	for(i=0;i<8;i++)
    	{
    		DQ = 0;
    		DQ = dat&0x01;
    		Delay_OneWire(5);
    		DQ = 1;
    		dat >>= 1;
    	}
    	Delay_OneWire(5);
    }
    
    
    unsigned char Read_DS18B20(void)
    {
    	unsigned char i;
    	unsigned char dat;
      
    	for(i=0;i<8;i++)
    	{
    		DQ = 0;
    		dat >>= 1;
    		DQ = 1;
    		if(DQ)
    		{
    			dat |= 0x80;
    		}	    
    		Delay_OneWire(5);
    	}
    	return dat;
    }
    
    bit init_ds18b20(void)
    {
      	bit initflag = 0;
      	
      	DQ = 1;
      	Delay_OneWire(12);
      	DQ = 0;
      	Delay_OneWire(80);
      	DQ = 1;
      	Delay_OneWire(10); 
        initflag = DQ;     
      	Delay_OneWire(5);
      
      	return initflag;
    }
    
    
    //再将延时函数放至所有驱动函数之后
    void Delay_OneWire(unsigned int t)  
    {
      t*=11;  //修改驱动,将驱动延时增加至 11倍
    	while(t--);
    }
    
    
    float Read_Temp(void)
    {
      float temp;
    	unsigned char low,high;
    	init_ds18b20();
    	Write_DS18B20(0xcc); //跳过ROM
    	Write_DS18B20(0x44);
      Delay_OneWire(200);
      
    	init_ds18b20();
    	Write_DS18B20(0xcc); //跳过ROM
    	Write_DS18B20(0xbe); //读暂存器
    	low = Read_DS18B20();
    	high = Read_DS18B20();
      temp = (high<<8|low)*0.0625;
      
    	return temp;
    	
    }
    

    onewire.h

    #ifndef __ONEWIRE_H
    #define __ONEWIRE_H
    
    #include 
    #include "intrins.h"
    
    sbit DQ = P1^4;  
    
    float Read_Temp(void);
    
    #endif
    
    
  • 相关阅读:
    Python二进制序列类型(一)bytes与bytearray
    9.2、面向对象高级特性(类方法和静态方法、property类属性、单例模式)
    protobuf相关安装
    2022辽宁省赛(A,B,D,E,F,G,I,M)
    SqlServer单机发布订阅
    Git常用命令
    生产环境下调试的技巧
    【React】useSyncExternalStore的作用是什么,怎么使用
    【nosql】redis之高可用(主从复制、哨兵、集群)搭建
    VR会议:远程带看功能,专为沉浸式云洽谈而生
  • 原文地址:https://blog.csdn.net/ai_moe/article/details/127110035