• 温度报警器



    前言

    上节中对 “DS18B20” 进行初步的介绍,,本节则是对其的基本应用之一。

    在实例应用之前需要先了解一下“单总线

    一、单总线

    简介

    1. 单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
    2. —根通信线︰DQ
    3. 异步、半双工
    4. 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线

    电路规范

    1. 设备的DQ均要配置成开漏输出模式
    2. DQ添加一个上拉电阻,阻值一般为4.7KQ左右
    3. 若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
      在这里插入图片描述
      时序结构
      初始化︰ 主机将总线拉低至少480us,然后释放总线,等待15~ 60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线
      在这里插入图片描述
    unsigned char OneWire_Init(void)
    {
    	unsigned char i;
    	unsigned char AckBit;
    	EA=0;
    	OneWire_DQ=1;
    	OneWire_DQ=0;
    	i = 247;while (--i);		//Delay 500us
    	OneWire_DQ=1;
    	i = 32;while (--i);			//Delay 70us
    	AckBit=OneWire_DQ;
    	i = 247;while (--i);		//Delay 500us
    	EA=1;
    	return AckBit;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    发送一位︰ 主机将总线拉低60~ 120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us

    在这里插入图片描述

    void OneWire_SendBit(unsigned char Bit)
    {
    	unsigned char i;
    	EA=0;
    	OneWire_DQ=0;
    	i = 4;while (--i);			//Delay 10us
    	OneWire_DQ=Bit;
    	i = 24;while (--i);			//Delay 50us
    	OneWire_DQ=1;
    	EA=1;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    接收一位︰ 主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平((尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us
    在这里插入图片描述

    unsigned char OneWire_ReceiveBit(void)
    {
    	unsigned char i;
    	unsigned char Bit;
    	EA=0;
    	OneWire_DQ=0;
    	i = 2;while (--i);			//Delay 5us
    	OneWire_DQ=1;
    	i = 2;while (--i);			//Delay 5us
    	Bit=OneWire_DQ;
    	i = 24;while (--i);			//Delay 50us
    	EA=1;
    	return Bit;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    发送一个字节

    void OneWire_SendByte(unsigned char Byte)
    {
    	unsigned char i;
    	for(i=0;i<8;i++)
    	{
    		OneWire_SendBit(Byte&(0x01<<i));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    接收一个字节

    unsigned char OneWire_ReceiveByte(void)
    {
    	unsigned char i;
    	unsigned char Byte=0x00;
    	for(i=0;i<8;i++)
    	{
    		if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
    	}
    	return Byte;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    二、DS18B20温度读取

    //DS18B20指令
    #define DS18B20_SKIP_ROM			0xCC
    #define DS18B20_CONVERT_T			0x44
    #define DS18B20_READ_SCRATCHPAD 	0xBE
    
    /**
      * @brief  DS18B20开始温度变换
      * @param  无
      * @retval 无
      */
    void DS18B20_ConvertT(void)
    {
    	OneWire_Init();
    	OneWire_SendByte(DS18B20_SKIP_ROM);
    	OneWire_SendByte(DS18B20_CONVERT_T);
    }
    
    /**
      * @brief  DS18B20读取温度
      * @param  无
      * @retval 温度数值
      */
    float DS18B20_ReadT(void)
    {
    	unsigned char TLSB,TMSB;
    	int Temp;
    	float T;
    	OneWire_Init();
    	OneWire_SendByte(DS18B20_SKIP_ROM);   
    	OneWire_SendByte(DS18B20_READ_SCRATCHPAD);     
    	TLSB=OneWire_ReceiveByte();
    	TMSB=OneWire_ReceiveByte();
    	Temp=(TMSB<<8)|TLSB;
    	T=Temp/16.0;
    	return T;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    三、主函数

    以下涉及到的AT24C02在前几节介绍IIC时 已有提交,了解详情请移步 “IIC 协议”

    void main()
    {
    	DS18B20_ConvertT();		//上电先转换一次温度,防止第一次读数据错误
    	Delay(1000);			//等待转换完成
    	THigh=AT24C02_ReadByte(0);	//读取温度阈值数据
    	TLow=AT24C02_ReadByte(1);
    	if(THigh>125 || TLow<-55 || THigh<=TLow)
    	{
    		THigh=20;			//如果阈值非法,则设为默认值
    		TLow=15;
    	}
    	LCD_Init();
    	LCD_ShowString(1,1,"T:");
    	LCD_ShowString(2,1,"TH:");
    	LCD_ShowString(2,9,"TL:");
    	LCD_ShowSignedNum(2,4,THigh,3);
    	LCD_ShowSignedNum(2,12,TLow,3);
    	Timer0_Init();
    	
    	while(1)
    	{
    		KeyNum=Key();
    		
    		/*温度读取及显示*/
    		DS18B20_ConvertT();	//转换温度
    		T=DS18B20_ReadT();	//读取温度
    		if(T<0)				//如果温度小于0
    		{
    			LCD_ShowChar(1,3,'-');	//显示负号
    			TShow=-T;		//将温度变为正数
    		}
    		else				//如果温度大于等于0
    		{
    			LCD_ShowChar(1,3,'+');	//显示正号
    			TShow=T;
    		}
    		LCD_ShowNum(1,4,TShow,3);		//显示温度整数部分
    		LCD_ShowChar(1,7,'.');		//显示小数点
    		LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
    		
    		/*阈值判断及显示*/
    		if(KeyNum)
    		{
    			if(KeyNum==1)	//K1按键,THigh自增
    			{
    				THigh++;
    				if(THigh>125){THigh=125;}
    			}
    			if(KeyNum==2)	//K2按键,THigh自减
    			{
    				THigh--;
    				if(THigh<=TLow){THigh++;}
    			}
    			if(KeyNum==3)	//K3按键,TLow自增
    			{
    				TLow++;
    				if(TLow>=THigh){TLow--;}
    			}
    			if(KeyNum==4)	//K4按键,TLow自减
    			{
    				TLow--;
    				if(TLow<-55){TLow=-55;}
    			}
    			LCD_ShowSignedNum(2,4,THigh,3);	//显示阈值数据
    			LCD_ShowSignedNum(2,12,TLow,3);
    			AT24C02_WriteByte(0,THigh);		//写入到At24C02中保存
    			Delay(5);
    			AT24C02_WriteByte(1,TLow);
    			Delay(5);
    		}
    		if(T>THigh)			//越界判断
    		{
    			LCD_ShowString(1,13,"OV:H");
    		}
    		else if(T<TLow)
    		{
    			LCD_ShowString(1,13,"OV:L");
    		}
    		else
    		{
    			LCD_ShowString(1,13,"    ");
    		}
    	}
    }
    
    void Timer0_Routine() interrupt 1
    {
    	static unsigned int T0Count;
    	TL0 = 0x18;		//设置定时初值
    	TH0 = 0xFC;		//设置定时初值
    	T0Count++;
    	if(T0Count>=20)
    	{
    		T0Count=0;
    		Key_Loop();	//每20ms调用一次按键驱动函数
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
  • 相关阅读:
    读取并显示.pcd/.ply/.txt/.bin/.stl格式的点云
    JAVA经典面试题附答案(持续更新版)
    代码随想录 | Day 60(完结) - LeetCode 84. 柱状图中最大的矩形
    Rust入门教程(五):错误处理
    Linux I2C调试分享
    Animator动画状态机
    mysql基础问题三问(底层逻辑;正在执行;日志观察)
    【迅投qmt系列】3、获取实时数据
    正则表达式
    云计算修罗场
  • 原文地址:https://blog.csdn.net/Dustinthewine/article/details/125431369