基于51单片机的智能热水器

1、设计需求及目标

具体实现功能:
1、LCD1602显示屏第一行显示温度及定时时间,第二行显示温度上限和下限值;
2、按键可以设置温度的上下限值及定时时间;定时时间到开始加热
3、用两个水位检测传感器检测水位:当水位下限传感器检测到有水时,继电器开始控制加水;当水位上限传感器检测到有水时,停止加水;
4、当温度低于设置的下限温度值时,继电器开始控制加热;当温度高于设置的上限温度值时,停止加热。

2、设计思路及方案

系统的硬件系统以STC89C51单片机为核心,主要分两部分:直流稳压电源和智能电热水器控制电路,其原理图见附录二。直流稳压电源由变压器、整流桥、滤波电路、稳压电路组成。智能电热水器系统由时钟电路、复位电路、报警电路、键盘、温度检测电路和显示接口电路组成。

3、硬件电路

基于51单片机的智能热水器_第1张图片

4、部分程序

/*
基于51单片机的智能热水器
*/
//程序头函数
#include 
//显示函数
#include 
//宏定义
#define uint unsigned int 
#define uchar unsigned char
 
//管脚声明
sbit jdq= P1^0;	//加热继电器
sbit shui=P1^3;//加水继电器
sbit Feng = P2^6; //蜂鸣器
//按键
sbit Key1=P1^4;	 //设置
sbit Key2=P1^5;	 //加
sbit Key3=P1^6;	 //减
sbit Key4=P1^7;	 //确定	  
sbit shang=P3^7;//上限
sbit xia=P3^6;//下限

sbit DQ=P2^2;     			//定义DS18B20总线I/O
signed char w,bj,bjx,bjd;     				//温度值全局变量
uchar c;				//温度值全局变量
bit bdata flag=0,flag_BJ,flag_off=1,que;
//时间计算
#define Imax 14000    //此处为晶振为11.0592时的取值, 
#define Imin 8000    //如用其它频率的晶振时,
#define Inum1 145    //要改变相应的取值。
#define Inum2 700 
#define Inum3 3000 
//解码变量
unsigned char Im[4]={0x00,0x00,0x00,0x00};

//全局变量
uchar f;
unsigned char m,Tc;
unsigned char IrOK;

//设置变量

uchar xx=29;
//下限
uchar sx=35;
//上限
int ds=0;
uchar Mode=0;

void delay(uint z)
{
	uint i,j;
	for(i=0;i0;i--)
  {
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
    dat|=0x80;
    Delay_DS18B20(4);
  }
  return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 1;
    DQ = dat&0x10;
    Delay_DS18B20(5);
    DQ = 0;
    dat>>=1;
  }
}
/*****读取温度*****/
unsigned int ReadTemperature(void)
{
  unsigned char a=0;
  unsigned char b=0;
  unsigned int t=0;
  float tt=0;
  Init_DS18B20();
  WriteOneChar(0xC1);  //跳过读序号列号的操作
  WriteOneChar(0x44);  //启动温度转换
  Init_DS18B20();
  WriteOneChar(0xC1);  //跳过读序号列号的操作
  WriteOneChar(0xBE);  //读取温度寄存器
  a=ReadOneChar();     //读低8位
  b=ReadOneChar();    //读高8位
  t=b;
  t<<=8;
  t=t|a;
  tt=t*0.00625;
  t= tt*10+0.5;     //放大10倍输出并四舍五入
  return(t);
}


/*****读取温度*****/
void check_wendu(void)
{
	c=ReadTemperature()-5;  			//获取温度值并减去DS18B20的温漂误差
	w=c/10;      						//计算得到整数位
	if(w<0){w=0;}   				//设置温度显示上限
	if(w>99){w=99;}   				//设置温度显示上限    
}
/**************************************************************************************************
***************************************************************************************************
**************************************************************************************************/


/**************************************************************************************************
************************************按键工作程序***************************************************
**************************************************************************************************/
void Key()
{
	//模式选择
	if(Key1==0)
	{
		while(Key1==0);
		Feng=0;
		Mode++;
		Display_wd();
		if(Mode==4)
		{
			Mode=1;
			Feng=1;
		}
   		write_com(0x38);//屏幕初始化
   		write_com(0x0d);//打开显示 无光标 光标闪烁
   		write_com(0x06);//当读或写一个字符是指针后一一位
		switch(Mode)
		{
			case 1:
			{
				write_com(0x80+15);//位置
				Feng=1;
				break;
			}
			case 2:
			{
				write_com(0x80+0x40+5);//位置
				Feng=1;
				break;
			}
			case 3:
			{
				write_com(0x80+0x40+14);//位置
				Feng=1;
				break;
			}
		}
	}
	if(Key2==0&&Mode!=0)
	{
		while(Key2==0);
		Feng=0;
		switch(Mode)
		{
			case 1:
			{
				if(ds<999)
				{
					ds++;
					write_com(0x80+13);
					write_data('0'+ds/100);
					write_data('0'+ds/10%10);
					write_data('0'+ds%10);
					write_com(0x80+15);//位置
				}
				Feng=1;
				break;
			}
			case 2:
			{
				if(sx<99-1)
				{
					sx++;
					write_com(0x80+0x40+4);
					write_data('0'+sx/10%10);
					write_data('0'+sx%10);
					write_com(0x80+0x40+5);//位置
				}
				Feng=1;
				break;				
			}
			case 3:
			{
				if(xx0)
				{
					ds--;
					write_com(0x80+13);
					write_data('0'+ds/100);
					write_data('0'+ds/10%10);
					write_data('0'+ds%10);
					write_com(0x80+15);//位置
				}
				Feng=1;
				break;
			}
			case 2:
			{
				if(sx>xx+1)
				{
					sx--;
					write_com(0x80+0x40+4);
					write_data('0'+sx/10%10);
					write_data('0'+sx%10);
					write_com(0x80+0x40+5);//位置
				}
				Feng=1;
				break;				
			}
			case 3:
			{
				if(xx>0)
				{
					xx--;
					write_com(0x80+0x40+13);
					write_data('0'+xx/10%10);
					write_data('0'+xx%10);
					write_com(0x80+0x40+14);//位置
				}
				Feng=1;
				break;				
			}		
		}
	}
	if(Key4==0)
	{
		while(Key4==0);
		Feng=0;
		Mode=0;
	//	write_com(0x38);//屏幕初始化
	//	write_com(0x0c);//打开显示 无光标 无光标闪烁
		Init1602();
		if(ds>0)
		{
			flag=1;
			jdq=1;
			TR1=1;
		}
		Feng=1;
	}
		if(IrOK==1) 
		{
			if(Im[2]==0x0d)	//遥控设置键
			{
				Feng=0;
				Mode++;
				Display_wd();
				if(Mode==4)
				{
					Mode=1;
					Feng=1;
				}
		   		write_com(0x38);//屏幕初始化
		   		write_com(0x0d);//打开显示 无光标 光标闪烁
		   		write_com(0x06);//当读或写一个字符是指针后一一位
				switch(Mode)
				{
					case 1:
					{
						write_com(0x80+15);//位置
						Feng=1;
						break;
					}
					case 2:
					{
						write_com(0x80+0x40+5);//位置
						Feng=1;
						break;
					}
					case 3:
					{
						write_com(0x80+0x40+14);//位置
						Feng=1;
						break;
					}
				}				 
			}
			//+键
			else if(Im[2]==0x40)
			{
				if(Mode!=0)
				{
					Feng=0;
					switch(Mode)
					{
						case 1:
						{
							if(ds<999)
							{
								ds++;
								write_com(0x80+13);
								write_data('0'+ds/100);
								write_data('0'+ds/10%10);
								write_data('0'+ds%10);
								write_com(0x80+15);//位置
							}
							Feng=1;
							break;
						}
						case 2:
						{
							if(sx<99-1)
							{
								sx++;
								write_com(0x80+0x40+4);
								write_data('0'+sx/10%10);
								write_data('0'+sx%10);
								write_com(0x80+0x40+5);//位置
							}
							Feng=1;
							break;				
						}
						case 3:
						{
							if(xx0)
							{
								ds--;
								write_com(0x80+13);
								write_data('0'+ds/100);
								write_data('0'+ds/10%10);
								write_data('0'+ds%10);
								write_com(0x80+15);//位置
							}
							Feng=1;
							break;
						}
						case 2:
						{
							if(sx>xx+1)
							{
								sx--;
								write_com(0x80+0x40+4);
								write_data('0'+sx/10%10);
								write_data('0'+sx%10);
								write_com(0x80+0x40+5);//位置
							}
							Feng=1;
							break;				
						}
						case 3:
						{
							if(xx>0)
							{
								xx--;
								write_com(0x80+0x40+13);
								write_data('0'+xx/10%10);
								write_data('0'+xx%10);
								write_com(0x80+0x40+14);//位置
							}
							Feng=1;
							break;				
						}		
					}
				}
			}
			//确定键
			else if(Im[2]==0x15)
			{
				Feng=0;
				Mode=0;
				Init1602();
				if(ds>0)
				{
					flag=1;
					jdq=1;
					TR1=1;
				}
				Feng=1;
			} 
			IrOK=0;	  
		}
}
/**************************************************************************************************
***************************************************************************************************
**************************************************************************************************/



/**************************************************************************************************
************************************报警部分程序***************************************************
**************************************************************************************************/
void Alam()
{
	if(flag_BJ==1&&flag_off==1)
	{
		Feng=0;
		delay(1000);
		Feng=1;
		flag_off=0;
//		flag_BJ=0;
	}
}
/**************************************************************************************************
***************************************************************************************************
**************************************************************************************************/

/**************************************************************************************************
*********************************************主程序************************************************
**************************************************************************************************/
void main()
{
	Init1602();
	EA=1;//打开中断总开关
	IT1=1;//下降沿有效
	EX1=1;//外部中断1开
	ET1=1;//打开允许开关
	TMOD=0x01;//设置工作方式
	TL1=0x3c;
	TH1=0xb0;//赋初值
	TH0=0;//T0赋初值
	TL0=0;
	TR0=0;//t0开始计时
	check_wendu();
	delay(1000);
	bjd=99;
	bjx=0;				 //这两个变量的作用就是,防止温度大范围跳动造成加热设备误动作
	while(1)
	{	
		check_wendu();
		if(Mode==0)
		{	
			Display_1602(c,ds,sx,xx);
			if((xia==1)&&(shang==1)) //低于下限
			{
			 	que=1;
				shui=0;
				jdq=1;
			}
			else
			{
				que=0;
			}
			if((shang==0)&&(xia==0)) //高于上限
			{
				shui=1;
				if(flag_BJ==0)
				flag_BJ=1;
			}
			if((shang==0)&&(xia==1)) //错误
			{
				shui=1;
				jdq=1;
				Feng=0;
				que=1;
			}
			if(flag==0)
			{
				if((wbjx))
				{
					if(w>=sx)
					{
						jdq=1;
						if(flag_BJ==0)
						flag_BJ=1;
					}
					else if((w=sx)
			{
				jdq=1;
				if(flag_BJ==0)
				flag_BJ=1;
			}
			else if((w

 

你可能感兴趣的:(51单片机实例)