欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
單片機+LCD1602顯示冷熱水調和系統Proteus仿真程序 精度為±1℃
[打印本頁]
作者:
飛啊豬
時間:
2019-7-11 17:53
標題:
單片機+LCD1602顯示冷熱水調和系統Proteus仿真程序 精度為±1℃
實現的功能(1)用LCD1602液晶顯示水溫、設置上下限和定時時間,(2)水溫檢測顯示范圍為00~99℃,精度為±1℃。(3)溫度預設范圍為0~99℃,當檢測溫度低于預設溫度時,開始加熱;檢測溫度高于預設溫度時,停止加熱。(4)設置4個程序按鍵。分別是設置按鍵、加鍵、減鍵、確定。(5)可以紅外遙控,通過紅外一體接收探頭接收遙控器信號,執行與主板按鍵同等功能。(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:定時狀態標志位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);
}
/*****讀一個字節*****/
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);
}
/*****寫一個字節*****/
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
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1