这是我设计的智能热水器的控制方案基本功能:将水温控制在一个0到99摄氏度的温度上,同时还具有无水自动加水,水满停止加水以及延时和红外控制的功能。
里面包含:
1源代码
2器件清单
3系统仿真
单片机智能热水器仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
仿真视频讲解:
单片机源程序如下:
- //程序头函数
- #include <reg52.h>
- //显示函数
- #include <display.h>
- //宏定义
- #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;i<z;i++)
- for(j=0;j<121;j++);
- }
- /**************************************************************************************************
- **************************温度工作程序*************************************************************
- **************************************************************************************************/
- /*****延时子程序*****/
- void Delay_DS18B20(int num)
- {
- while(num--) ;
- }
- /*****初始化DS18B20*****/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- Delay_DS18B20(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delay_DS18B20(8); //精确延时,大于480us
- DQ = 1; //拉高总线
- Delay_DS18B20(14);
- x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
- Delay_DS18B20(20);
- }
- /*****读一个字节*****/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;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(xx<sx-1)
- {
- 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(Key3==0&&Mode!=0)
- {
- while(Key3==0);
- Feng=0;
- switch(Mode)
- {
- case 1:
- {
- if(ds>0)
- {
- 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(xx<sx-1)
- {
- 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]==0x19)
- {
- if(Mode!=0)
- {
- Feng=0;
- switch(Mode)
- {
- case 1:
- {
- if(ds>0)
- {
- 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((w<bjd)&&(w>bjx))
- {
- if(w>=sx)
- {
- jdq=1;
- if(flag_BJ==0)
- flag_BJ=1;
- }
- else if((w<xx)&&(que==0))
- {
- jdq=0;
- if(flag_BJ==0)
- flag_BJ=1;
- }
- else
- {
- flag_BJ=0;
- flag_off=1;
- }
- bjd=w+5;
- bjx=w-5;
- }
- }
- }
- Key();
- Alam();
- }
- }
- /**************************************************************************************************
- ***************************************************************************************************
- **************************************************************************************************/
- /**************************************************************************************************
- ****************************************定时器工作程序*********************************************
- **************************************************************************************************/
- void time1() interrupt 3//定时器函数
- {
- uint s;
- TH1=0x3c;
- TL1=0xb0;//重新赋初值
- s++;
- if(s==1200) //s=20为1s钟 1200为1分钟
- {
- s=0;
- ds--;
- if(ds==0)
- {
- flag=0;
- if(w>=sx)
- {
- jdq=1;
- if(flag_BJ==0)
- flag_BJ=1;
- }
- else if((w<xx)&&(que==0))
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
本人初学,仅供参考,存在错误和不足之处,请大家回帖多多指教,切勿照搬,文件下载:
新建文件夹.rar
(2.31 MB, 下载次数: 363)
|