基于51单片机的温度上下限控制实时显示时间温度.docx
《基于51单片机的温度上下限控制实时显示时间温度.docx》由会员分享,可在线阅读,更多相关《基于51单片机的温度上下限控制实时显示时间温度.docx(23页珍藏版)》请在冰豆网上搜索。
基于51单片机的温度上下限控制实时显示时间温度
#include"STC89C51RC.H"
#include
#include"ds18b20.h"
#include"lcd1602.h"
#include"ds1302.h"
#include"2402.h"
uchardatadatadis[]={0x00,0x00,0x00,0x00,0x00};
uinttemp=0;
sbitK1=P3^0;
sbitK2=P3^1;
sbitK3=P3^2;
sbitK4=P3^3;
sbitK5=P3^7;
sbitL1=P1^6;
sbitL2=P1^7;
sbitled=P2^7;
sbitspeaker=P1^0;
ucharkeynum=1,flag,flag1,flag2,adder,q;
uintk,count,th,tl;
ucharth1=8;
ucharth2=5;
ucharth3=2;
ucharth4=0;
uchartab,w;
voiddelay(ucharz)
{
ucharx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
ucharkey4()
{
if(K4==0)
{
delay(5);
if(K4==0)
{
while(!
K4);
keynum++;
if(keynum==5)keynum=1;
}
}
returnkeynum;
}
voidkey_lcd()
{
if(flag1==1&&k==3)
{
if(K3==0)
{
delay(5);
if(K3==0)
{
while(!
K3);
flag++;
if(flag==5)flag=1;
}
}
switch(flag)
{
case1:
{
if(K1==0)
{
delay(5);
if(K1==0)
{
th1++;
while(!
K1);
if(th1==10)th1=0;
}
}
if(K2==0)
{
delay(5);
if(K2==0)
{
th1--;
while(!
K2);
if(th1==-1)th1=9;
}
}
write_cmd(0xc3);
write_dat(th1+0x30);
}break;
case2:
{
if(K1==0)
{
delay(5);
if(K1==0)
{
th2++;
while(!
K1);
if(th2==10)th2=0;
}
}
if(K2==0)
{
delay(5);
if(K2==0)
{
th2--;
while(!
K2);
if(th2==-1)th2=9;
}
}
write_cmd(0xc4);
write_dat(th2+0x30);
}break;
case3:
{
if(K1==0)
{
delay(5);
if(K1==0)
{
th3++;
while(!
K1);
if(th3==10)th3=0;
}
}
if(K2==0)
{
delay(5);
if(K2==0)
{
th3--;
while(!
K2);
if(th3==-1)th3=9;
}
}
write_cmd(0xcb);
write_dat(th3+0x30);
}break;
case4:
{
if(K1==0)
{
delay(5);
if(K1==0)
{
th4++;
while(!
K1);
if(th4==10)th4=0;
}
}
if(K2==0)
{
delay(5);
if(K2==0)
{
th4--;
while(!
K2);
if(th4==-1)th4=9;
}
}
write_cmd(0xcc);
write_dat(th4+0x30);
}break;
default:
break;
}
}
elseflag1=0;
th=th1*10+th2;//获取设置温度的高位
tl=th3*10+th4;//获取设置温度的低位
}
voidalarm_speaker()//报警系统与当前温度进行比较并处理
{
if(temp<(tl*10))
{
speaker=~speaker;
L1=0;
L2=1;
adder++;
tab=temp/10;
write_add(adder,tab);
}
elseif(temp>(th*10))
{
speaker=~speaker;
L1=1;
L2=0;
adder++;
tab=temp/10;
write_add(adder,tab);
}
elseif(temp<(th*10)&&temp>(tl*10))
{
speaker=1;
L1=1;
L2=1;
}
}
voidmain()
{
systemtimerealtime;
led=0;
init_18b20();
init_lcd();
init_2402();
speaker=1;
while
(1)
{
k=key4();
get_ds1302(&realtime);//取时间
temp=read_temp();//取温度
delay(200);
//延时保持数据稳定避免数据刷新
switch(k)
{
case1:
//菜单一,显示时间
{
led=0;
write_cmd(0x80);
print("Time:
");
print(realtime.TimeString);
write_cmd(0xc0);
print("Date:
");
print(realtime.DateString);
}break;
case2:
//菜单二,显示温度
{
write_cmd(0x80);
print("DS18B20isOK");
write_cmd(0xc0);
print("NOWTEMP:
.C");
if(flagt==1)datadis[0]=0x2d;
elsedatadis[0]=temp/1000+0x30;
datadis[1]=temp/100%10+0x30;
datadis[2]=temp/10%10+0x30;
datadis[3]=0x2e;
datadis[4]=temp%10+0x30;
write_cmd(0xca);
print(datadis);
}break;
case3:
//菜单三,显示温度设置值
{
write_cmd(0x80);
print("changetemp:
");
write_cmd(0xc0);
print("TH=TL=");
write_cmd(0xc3);
write_dat(th1+0x30);
write_cmd(0xc4);
write_dat(th2+0x30);
write_cmd(0xc5);
write_dat(0xdf);//摄氏度远点
write_cmd(0xc6);
write_dat(0x43);
write_cmd(0xcb);
write_dat(th3+0x30);
write_cmd(0xcc);
write_dat(th4+0x30);
write_cmd(0xcd);//摄氏度符号
write_dat(0xdf);
write_cmd(0xce);
write_dat(0x43);
flag1=1;
}break;
case4:
//菜单四,记录报警温度
{
write_cmd(0x80);
print("ALARMTEMP");
write_cmd(0xc0);
print("RECORD:
");
write_cmd(0xcb);
write_dat(0xdf);
write_cmd(0xcc);
write_dat(0x43);
flag2=1;
}break;
default:
break;
}
key_lcd();//菜单三中温度设置的按键扫描
alarm_speaker();//报警系统通过2402存储超出的温度,并记录
if(K5==0)//按下K5,就显示当前报警的温度
{
delay(5);
if(K5==0)
{
while(!
K5);
q=read_add(adder);
}
};
if(flag2==1&&k==4)
{
write_cmd(0xc9);
write_dat(q/10%10+0x30);
write_cmd(0xca);
write_dat(q%10+0x30);
led=1;
}
}
}
#ifndef_lcd1602_h_
#define_lcd1602_h_
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLCD_IOP0
sbitLCD_RS=P2^4;
sbitLCD_RW=P2^5;
sbitLCD_EN=P2^6;
voiddelay11(uintz)
{
uintx,y;
for(x=z;x>0;x--)for(y=10;y>0;y--);
}
/*测忙信号
bitlcd_busy()
{
return(bit)(lcdrc&0x80);
}
/*写数据*/
voidwrite_cmd(ucharcmd)
{
LCD_RW=0;LCD_RS=0;LCD_EN=0;//LCD_RS和R/W同时为低电平时,可以写入指令.
LCD_IO=cmd;delay11(5);//下面用EN输入一个高脉冲.
LCD_EN=1;delay11(5);LCD_EN=0;
}
/*写命令*/
voidwrite_dat(uchardat)
{
LCD_RS=1;LCD_EN=0;LCD_RW=0;//LCD_RS为高,LCD_RW为低时,可以写入数据.
LCD_IO=dat;delay11(5);//下面用EN输入一个高脉冲.
LCD_EN=1;delay11(5);LCD_EN=0;
}
/*LCD初始化*/
voidinit_lcd()
{
LCD_EN=0;
write_cmd(0x38);
write_cmd(0x0c);
write_cmd(0x06);
write_cmd(0x01);
write_cmd(0x80);
}
voidprint(uchar*str)
{
while(*str!
='\0')
{
write_dat(*str);
str++;
}
}
#endif
#ifndef_ds18b20_h_
#define_ds18b20_h_
#defineucharunsignedchar
#defineuintunsignedint
//晶振22MHZ
//延时//
sbitDQ=P1^3;
bitflagt;
voiddelay_18b20(uinti)
{
while(i--);
}
/*****初始化程序****/
voidinit_18b20()
{
ucharx=0;
DQ=1;
delay_18b20(8);
DQ=0;
delay_18b20(80);
DQ=1;
delay_18b20(15);
x=DQ;
delay_18b20(15);
}
/**读一个字节**/
ucharread_byte()
{
uchari=0;
uchardat=0;
for(i=0;i<8;i++)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)dat|=0x80;
delay_18b20(5);
}
returndat;
}
/**写一个字节**/
voidwrite_byte(uchardat)
{
uchari=0;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01;
delay_18b20(5);
DQ=1;
dat>>=1;
}
}
/**温度转换并读取温度**/
uintread_temp()
{
uchara=0;
ucharb=0;
uintt;
init_18b20();
write_byte(0xcc);//跳过读序号列号的操作
write_byte(0x44);//启动温度转换
delay_18b20(100);
init_18b20();
write_byte(0xcc);//跳过读序号列号的操作
write_byte(0xbe);//读取温度寄存器等(共可读9个寄存器)前两个就是温度
a=read_byte();//读第八位
b=read_byte();//读高八位
if(b&0x80)//高八位的最高位于是否为1,若为1,则为负温度,若为0,则是0-128;
{
flagt=1;
a=~a;
b=~b;
}
elseflagt=0;
t=(b*256+a)*5;//也可以写成t=(b*256+a)*0.625;returnt;
return(t>>3);//右移三位相当于5/8=0.625返回温度有4位,千、百、十、个,转化后有一位小数位,没有千位
}
#endif
#ifndef_2402_h_
#define_2402_h_
#defineucharunsignedchar
#defineuintunsignedint
sbitsda=P1^2;
sbitscl=P1^1;
//sbitsda=P1^6;
//sbitscl=P1^5;
voidnop()
{;;}
voidstart()//功能:
启动I2C总线,即发送I2C起始条件。
{
sda=1;
nop();
scl=1;
nop();
sda=0;
nop();
}
voidstop()//功能:
结束I2C总线,即发送I2C结束条件。
{
sda=0;
nop();
scl=1;
nop();
sda=1;
nop();
}
voidrespons()//功能:
主控器进行应答信号,(可以是应答或非应答信号)
{
uchari;
scl=1;
nop();
while((sda==1)&&(i<250))i++;
scl=0;
nop();
}
voidwrite_byte_2402(uchardat)//功能:
将数据dat发送出去,可以是地址,也可以是数据,发完后等待应答
{
uchari,temp;
temp=dat;
scl=0;
nop();
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;/*置时钟线为低,准备接收数据位*/
nop();
sda=CY;
nop();
scl=1;/*置时钟线为高,通知被控器开始接收数据位*/
nop();
}
scl=0;
nop();
sda=1;//SDA数据线空闲
nop();
}
ucharread_byte_2402()//功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数
{
uchari,k;
scl=0;/*置时钟线为低,准备接收数据位*/
nop();
for(i=0;i<8;i++)
{
scl=1;/*置时钟线为高使数据线上数据有效,保持数据的稳定*/
nop();
k=(k<<1)|sda;
scl=0;
nop();
}
returnk;
}
voidwrite_add(ucharadd,uchardat)
{
start();
write_byte_2402(0xa0);
respons();
write_byte_2402(add);
respons();
write_byte_2402(dat);
respons();
stop();
}
ucharread_add(ucharadd)
{
uchark;
start();
write_byte_2402(0xa0);
respons();
write_byte_2402(add);
respons();
start();
write_byte_2402(0xa1);
respons();
k=read_byte_2402();
stop();
returnk;
}
voidinit_2402()
{
uinti;
sda=1;
nop();
scl=1;
nop();
for(i=0;i<256;i++)
{write_add(i,0);}
}
#endif
/****************************
DS1302内部函数
*****************************/
#ifndef_ds1302_h_
#define_ds1302_h_
sbitT_RST=P3^5;
sbitT_CLK=P3^6;
sbitT_IO=P3^4;
sbitACC0=ACC^0;
sbitACC7=ACC^7;
typedefstructsystemtime
{
ucharsecond;
ucharminute;
ucharhour;
ucharweek;
ucharday;
ucharmonth;
ucharyear;
ucharDateString[9];
ucharTimeString[9];
}systemtime;//定义的时间类型
/*向DS1302中写入1BYTE数据*/
voidwriteB(ucharucda)
{
uchari;
ACC=ucda;
for(i=8;i>0;i--)
{
T_IO=ACC0;
T_CLK=1;
T_CLK=0;
ACC=ACC>>1;
}
//T_IO=0;
}
/*从DS1302中读出1BYTE数据*/
ucharreadB()
{
uchari;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=T_IO;
T_CLK=1;
T_CLK=0;
}
return(ACC);
}
/*单字节读,向DS1302某地址中读出数据,
先写地址后写命令/数据*************/
ucharr_ds1302(ucharucaddr)
{
ucharucda;
T_RST=0;
T_CLK=0;
T_RST=1;
writeB(ucaddr);
ucda=readB();
T_CLK=1;
T_RST=0;
return(ucda);
}
/**********************************
读取DS1302当前时间,
格式为:
秒,分,时,日,月,星期,年
**********************************/
voidget_ds1302(systemtime*Time)
{
ucharreadtime;
readtime=r_ds1302(0x81);//秒寄存器读操作0x81
Time->second=((readtime&0x70)>>4)*10+(readtime&0x0f);//十位+个位
readtime=r_ds1302(0x83);//分寄存器读操作0x83
Time->minute=((readtime&0x70)>>4)*10+(readtime&0x0f);
readtime=r_ds1302(0x85);
Time->hour=((readtime&0x70)>>4)*10+(readtime&0x0f);
readtime=r_ds1302(0x87);
Time->day=((readtime&0x7