当前位置:网站首页>温度报警器

温度报警器

2022-06-26 06:03:00 比特冬哥


前言

上节中对 “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;
}

发送一位︰ 主机将总线拉低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~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;
}

发送一个字节

void OneWire_SendByte(unsigned char Byte)
{
    
	unsigned char i;
	for(i=0;i<8;i++)
	{
    
		OneWire_SendBit(Byte&(0x01<<i));
	}
}

接收一个字节

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

二、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;
}

三、主函数

以下涉及到的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调用一次按键驱动函数
	}
}

原网站

版权声明
本文为[比特冬哥]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Dustinthewine/article/details/125431369