實現(xiàn)的功能(1)用LCD1602液晶顯示水溫、設置上下限和定時時間,(2)水溫檢測顯示范圍為00~99℃,精度為±1℃。(3)溫度預設范圍為0~99℃,當檢測溫度低于預設溫度時,開始加熱;檢測溫度高于預設溫度時,停止加熱。(4)設置4個程序按鍵。分別是設置按鍵、加鍵、減鍵、確定。(5)可以紅外遙控,通過紅外一體接收探頭接收遙控器信號,執(zhí)行與主板按鍵同等功能。(6)有水位檢測功能,無水自動上水,無水不加熱。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
0.png (42.82 KB, 下載次數: 58)
下載附件
2019-7-14 20:13 上傳
單片機源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit LCDRS = P1^1; //命令數據選擇
- sbit LCDEN= P1^2; //使能
- 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; //溫度值全局變量
- uint c; //溫度值全局變量
- bit bdata flag=0,flag_BJ,flag_off=1,que;//flag:定時狀態(tài)標志位flag_BJ:報警標志位flag_off:手動關閉報警標志位que:缺水標志位
- /*******遙控時間計算********/
- #define Imax 14000 //此處為晶振為12時的取值,
- #define Imin 8000 //如用其它頻率的晶振時,
- #define Inum1 1450 //要改變相應的取值。
- #define Inum2 700
- #define Inum3 3000
- //解碼變量
- unsigned char Im[4]={0x00,0x00,0x00,0x00};
- //全局變量
- uchar f;
- unsigned char m,Tc;
- unsigned char IrOK;
- uint xx=28; //T設定下限
- uint sx=37; //T設定上限
- int ds=0;
- uchar Mode=0;
- /********設置變量**********/
- //初始畫時顯示的內容
- uchar code Init1[]="Tp:00.0 C Ti:000";
- uchar code Init2[]=" Up:00 Down:00 ";
- /*********液晶的基本操作程序**********/
- //LCD延時
- void LCDdelay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=10;y>0;y--);
- }
- //寫命令
- void write_com(uchar com)
- {
- LCDRS=0;
- P0=com;
- LCDdelay(5);
- LCDEN=1;
- LCDdelay(5);
- LCDEN=0;
- }
- //寫數據
- void write_data(uint date)
- {
- LCDRS=1;
- P0=date;
- LCDdelay(5);
- LCDEN=1;
- LCDdelay(5);
- LCDEN=0;
- }
- /*******1602初始化程序********/
- void Init1602()
- {
- uchar i=0;
- uchar j=0;
-
- write_com(0x38); //屏幕初始化
- write_com(0x0c); //打開顯示 無光標 無光標閃爍
- write_com(0x06); //當讀或寫一個字符是指針后一一位
- write_com(0x01); //清屏
- write_com(0x80); //設置位置
-
- for(i=0;i<16;i++)
- {
- write_data(Init1[i]);
- }
- write_com(0xc0);//設置位置
- for(j=0;j<16;j++)
- {
- write_data(Init2[j]);
- }
- }
- /*******顯示時間溫度數據程序***********/
- void Display_1602(uint c,uint ds,uint sx,uint xx)
- {
- //溫度顯示
- write_com(0x80+3);
- write_data('0'+c/100);
- write_data('0'+c/10%10);
- write_data('.');
- write_data('0'+c %10);
- write_data(0xdf);
- //定時顯示
- write_com(0x80+13);
- write_data('0'+ds/100);
- write_data('0'+ds/10%10);
- write_data('0'+ds%10);
- //上限顯示
- write_com(0x80+0x40+4);
- write_data('0'+sx/10%10);
- write_data('0'+sx%10);
- //下限顯示
- write_com(0x80+0x40+13);
- write_data('0'+xx/10%10);
- write_data('0'+xx%10);
-
- }
- /****字符顯示程序*****/
- void Display_wd()
- {
- //溫度顯示
- write_com(0x80);
- write_data('S');
- write_data('e');
- write_data('t');
- write_data(' ');
- write_data('s');
- write_data('t');
- write_data('a');
- write_data('t');
- write_data('e');
- }
- 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*****/
- uchar Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ復位
- Delay_DS18B20(8); //稍做延時
- DQ = 0; //單片機將DQ拉低
- Delay_DS18B20(80); //精確延時,大于480us
- DQ = 1; //拉高總線
- Delay_DS18B20(14);
- x = DQ; //稍做延時后,如果x=0則初始化成功,x=1則初始化失敗
- Delay_DS18B20(20);
- return(x);
- }
- /*****讀一個字節(jié)*****/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1;
- _nop_();
- _nop_(); // 給脈沖信號
- if(DQ)
- dat|=0x80;
- Delay_DS18B20(4);
- DQ=1;
- }
- return(dat);
- }
- /*****寫一個字節(jié)*****/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- Delay_DS18B20(5);
- DQ = 1;
- dat>>=1;
- }
- }
- /*****讀取溫度*****/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- float tt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0x44); //啟動溫度轉換
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器
- a=ReadOneChar(); //讀低8位
- b=ReadOneChar(); //讀高8位
- t=b;
- t<<=8;
- t=t|a;
- tt=t*0.0625;
- t= tt*10+0.5; //放大10倍輸出并四舍五入
- return(t);
- }
- /*****讀取溫度*****/
- void check_wendu(void)
- {
- c=ReadTemperature(); //獲取溫度值并減去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();
- //Display_1602(c,ds,sx,xx);
- 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=0x11; //設置工作方式
- TL1=0x3c;
- TH1=0xb0; //T1賦初值50ms
- 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//定時器T1函數
- {
- 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))
- {
- jdq=0;
- if(flag_BJ==0)
- flag_BJ=1;
- }
- else
- {
- flag_BJ=0;
- flag_off=1;
- }
- bjd=w+10;
- bjx=w-10;
- TR1=0;
- }
- }
- }
- /*****************紅外解碼定時器程序****************************/
- //外部中斷解碼程序_外部中斷1
- void intersvr1(void) interrupt 2 using 1
- {
- TR0=1;
- Tc=TH0*256+TL0;//提取中斷時間間隔時長
- TH0=0;
- TL0=0; //定時中斷重新置零
- if((Tc>Imin)&&(Tc<Imax))
- {
- m=0;
- f=1;
- return;
- } //找到啟始碼
- if(f==1)
- {
- if(Tc>Inum1&&Tc<Inum3)
- {
- Im[m/8]=Im[m/8]>>1|0x80; m++;
- }
- if(Tc>Inum2&&Tc<Inum1)
- {
- Im[m/8]=Im[m/8]>>1; m++; //取碼
- }
- if(m==32)
- {
- m=0;
- f=0;
- if(Im[2]==~Im[3])
- {
- IrOK=1;
- TR0=0;
- }
- else IrOK=0; //取碼完成后判斷讀碼是否正確
- }
- //準備讀下一碼
- }
- }
復制代碼
所有資料51hei提供下載:
水溫調試.zip
(106.34 KB, 下載次數: 35)
2019-7-11 17:53 上傳
點擊文件名下載附件
proteus仿真+程序 下載積分: 黑幣 -5
|