這是我設計的智能熱水器的控制方案基本功能:將水溫控制在一個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)
2018-6-28 23:11 上傳
點擊文件名下載附件
智能熱水器
|