#include<reg51.h>
//#include<temp.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs=P1^0;
sbit rw=P1^1;
sbit lcden=P2^5;
sbit jidianqi=P2^7;
sbit s1=P3^4;//功能鍵
sbit s2=P3^5;//增加鍵
sbit s3=P3^6;//減小鍵
sbit beep=P2^3;//蜂鳴器
sbit led1=P1^3;
sbit led2=P1^4;
sbit ds=P2^2; //溫度傳感器
uint warnl=20; //下限溫度
uint warnh=40; //上限溫度
uint temp; //整形溫度數據
float f_temp; //浮點型溫度數據
uchar count,stop,s1num,s2num;//其它變量定義
char miao,shi,fen;
uchar code table[]=" : : T: ";//液晶固定顯示內容
uchar code table1[]=" L: H: ";
void delay(uint z)//延時函數
{
uint x,y;
for(x=z;x>0;x--)
for(y=124;y>0;y--)
;
}
void di() //蜂鳴器報警聲音
{
beep=0;
delay(100);
beep=1;
}
/*================液晶操作============*/
void write_com(uchar com)
{//寫液晶命令函數
rs=0;
lcden=0;
P0=com;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void write_date(uchar date)
{//寫液晶數據函數
rs=1;
lcden=0;
P0=date;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void write_sfm(uchar add,char date) //1602液晶刷新時分秒函數1為時,4為分,7為秒
{
char shiwei,gewei;
shiwei=date/10;
gewei=date%10;
write_com(0x80+add);
write_date(0x30+shiwei);
write_date(0x30+gewei);
}
void write_nyr(uchar add,char date)
{//1602液晶刷新年月日函數3為年,6為分,9為秒
char shiwei,gewei;
shiwei=date/10;
gewei=date%10;
write_com(0xc0+add);
write_date(0x30+shiwei);
write_date(0x30+gewei);
}
/*==================================================*/
/*==============ds18B20程序=========================*/
void dsreset(void) //18B20復位,初始化函數
{
uint i;
ds=0;
i=103;
while(i>0)i--;
ds=1;
i=4;
while(i>0)i--;
}
bit tempreadbit(void) //讀1位函數
{
uint i;
bit dat;
ds=0;i++; //i++ 起延時作用
ds=1;i++;i++;
dat=ds;
i=8;while(i>0)i--;
return (dat);
}
uchar tempread(void) //讀1個字節
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好一個字節在DAT里
}
return(dat);
}
void tempwritebyte(uchar dat) //向18B20寫一個字節數據
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //寫 1
{
ds=0;
i++;i++;
ds=1;
i=8;while(i>0)i--;
}
else
{
ds=0; //寫 0
i=8;while(i>0)i--;
ds=1;
i++;i++;
}
}
}
void tempchange(void) //DS18B20 開始獲取溫度并轉換
{
dsreset();
delay(1);
tempwritebyte(0xcc); // 寫跳過讀ROM指令
tempwritebyte(0x44); // 寫溫度轉換指令
}
uint get_temp() //讀取寄存器中存儲的溫度數據
{
uchar a,b;
dsreset();
delay(1);
tempwritebyte(0xcc);
tempwritebyte(0xbe);
a=tempread(); //讀低8位
b=tempread(); //讀高8位
temp=b;
temp<<=8; //兩個字節組合為1個字
temp=temp|a;
f_temp=temp*0.0625; //溫度在寄存器中為12位 分辨率位0.0625°
temp=f_temp+0.5; //加0.5是四舍五入
return temp; //temp是浮點型
}
/*=========================================================================*/
/*========================溫度處理========================*/
void deal(uint t)
{
if (t>warnh)
{
jidianqi=0;
TR0=0;
led1=0;
di();
delay(200);
di();
delay(100);
}
if (t>warnl&&t<=warnh)
{
led2=0;
di();
delay(400);
di();
delay(100);
}
}
/*=========================液晶處理=============*/
void init()
{//初始化函數
uchar num;
s1num=0;
count=0;
fen=0;
miao=0;
shi=0;
lcden=0;
jidianqi=1;
led1=1;
led2=1;
write_com(0x38);//1602液晶初始化
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)//寫入液晶固定部分顯示
{
write_date(table[num]);
delay(1);
}
write_sfm(7,miao);//分別送去液晶顯示
write_sfm(4,fen);
write_sfm(1,shi);
write_com(0x8e);
write_date(0xdf);
write_date(0x43);
write_com(0x80+0x40);
for(num=0;num<15;num++)
{
write_date(table1[num]);
delay(1);
}
write_com(0xc5);
write_date(0xdf);
write_date(0x43);
write_com(0xcd);
write_date(0xdf);
write_date(0x43);
TMOD=0x01;//設置定時器0工作模式1
TH0=(65536-50000)/256;//定時器裝初值
TL0=(65536-50000)%256;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
}
/*==================按鍵處理=============*/
void keyscan()//按鍵掃描函數
{
if(s1==0)
{
delay(5);
if(s1==0)//確認功能鍵被按下
{ s1num++;//功能鍵按下次數記錄
while(!s1);//釋放確認
di();//每當有按鍵釋放蜂鳴器發出滴聲
if(s1num==1)//第一次被按下時
{
TR0=0; //關閉定時器
write_com(0x80+7);//光標定位到秒位置
write_com(0x0f); //光標開始閃爍
}
if(s1num==2)//第二次按下光標閃爍定位到分鐘位置
{
write_com(0x80+4);
}
if(s1num==3)//第三次按下光標閃爍定位到小時位置
{
write_com(0x80+1);
}
if(s1num==4)
{
write_com(0xc0+3);
}
if(s1num==5)
{
write_com(0xc0+11);
}
if(s1num==6)//第四次按下
{
s1num=0;//記錄按鍵數清零
write_com(0x0c);//取消光標閃爍
TR0=1; //啟動定時器使時鐘開始走
}
}
}
if(s1num!=0)//只有功能鍵被按下后,增加和減小鍵才有效
{
if(s2==0)
{
delay(5);
if(s2==0)//增加鍵確認被按下
{
while(!s2);//按鍵釋放
di();//每當有按鍵釋放蜂鳴器發出滴聲
if(s1num==1)//若功能鍵第一次按下
{
miao++; //則調整秒加1
if(miao==60)//若滿60后將清零
miao=0;
write_sfm(7,miao);//每調節一次送液晶顯示一下
write_com(0x80+7);//顯示位置重新回到調節處
}
if(s1num==2)//若功能鍵第二次按下
{
fen++;//則調整分鐘加1
if(fen==60)//若滿60后將清零
fen=0;
write_sfm(4,fen);//每調節一次送液晶顯示一下
write_com(0x80+4);//顯示位置重新回到調節處
}
if(s1num==3)//若功能鍵第三次按下
{
shi++;//則調整小時加1
if(shi==24)//若滿24后將清零
shi=0;
write_sfm(1,shi);;//每調節一次送液晶顯示一下
write_com(0x80+1);//顯示位置重新回到調節處
}
if(s1num==4)
{
warnl++;
write_nyr(3,warnl);
write_com(0xc0+3);
}
if(s1num==5)
{
warnh++;
write_nyr(11,warnh);
write_com(0xc0+11);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)//確認減小鍵被按下
{
while(!s3);//按鍵釋放
di();//每當有按鍵釋放蜂鳴器發出滴聲
if(s1num==1)//若功能鍵第一次按下
{
miao--;//則調整秒減1
if(miao==-1)//若減到負數則將其重新設置為59
miao=59;
write_sfm(7,miao);//每調節一次送液晶顯示一下
write_com(0x80+7);//顯示位置重新回到調節處
}
if(s1num==2)//若功能鍵第二次按下
{
fen--;//則調整分鐘減1
if(fen==-1)//若減到負數則將其重新設置為59
fen=59;
write_sfm(4,fen);//每調節一次送液晶顯示一下
write_com(0x80+4);//顯示位置重新回到調節處
}
if(s1num==3)//若功能鍵第二次按下
{
shi--;//則調整小時減1
if(shi==-1)//若減到負數則將其重新設置為23
shi=23;
write_sfm(1,shi);//每調節一次送液晶顯示一下
write_com(0x80+1);//顯示位置重新回到調節處
}
if(s1num==4)
{
warnl--;
write_nyr(3,warnl);
write_com(0xc0+3);
}
if(s1num==5)
{
warnh--;
write_nyr(11,warnh);
write_com(0xc0+11);
}
}
}
}
}
/*=====================主函數=================*/
void main()
{
init();//調用初始化函數
while(1)
{
if (stop>=60)
deal(temp);
keyscan();//按鍵掃描
}
}
void timer0() interrupt 1//定時器0中斷服務程序
{
TH0=(65536-50000)/256;//再次裝定時器初值
TL0=(65536-50000)%256;
stop++;
if(stop>=100)
stop--;
count++; //中斷次數累加
if(count==20) //20次50毫秒為1秒
{
count=0;
miao++;
if(miao==60)//秒加到60則進位分鐘
{
miao=0;//同時秒數清零
fen++;
if(fen==60)//分鐘加到60則進位小時
{
fen=0;//同時分鐘數清零
shi++;
if(shi==24)//小時加到24則小時清零
{
shi=0;
}
write_sfm(1,shi);//小時若變化則重新寫入
}
write_sfm(4,fen);//分鐘若變化則重新寫入
}
write_sfm(7,miao);//秒若變化則重新寫入
tempchange();
write_sfm(12,get_temp());
write_nyr(3,warnl);
write_nyr(11,warnh);
}
}
|