|
#include<reg52.h>
#include <intrins.h>
#include<math.h>
#define uint unsigned int
#define uchar unsigned char
#define LCD P0
sbit redLED=P2^7;//位定義報警顯示燈
sbit xuanze=P3^3;//位定義選擇按鍵
sbit up=P3^4;//位定義極限加
sbit down=P3^5;//位定義極限減
int th=20,tl=5,thh=0,tll=0;//初始上限值和下限值
uchar i,num=0;//定義變量
/*******************************************************
延時函數
*******************************************************/
void delay(uint z)
{
uint x,y;
for (x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*************************************************
LCD部分
***************************************************/
sbit rs=P2^0;
sbit rw=P2^1;
sbit E=P2^2;
uchar tmp5[]="temp:";
uchar tmp6[]="^C";
uchar code tab1[]="TH:";
uchar code tab2[]="TL:";
write_com(uchar com)//LCD寫地址函數
{
rs=0;
rw=0;
E=1;
LCD=com;
delay(5);
E=0;
return 0;
}
write_data(uchar dat)//LCD寫數據函數
{
rs=1;
rw=0;
E=1;
LCD=dat;
delay(5);
E=0;
return 0;
}
init_lcd()//LCD初始化函數
{
write_com(0x38);//16*2顯示,5*7點陣,8位數據
write_com(0x0c);//設置為顯示開,關光標,不閃爍
write_com(0x06);//寫操作后,AC自動加1
write_com(0x01); //LCD清屏
write_com(0x80+0x01);//LCD第一行第二個位置起顯示"TH:"
for(i=0;i<3;i++)
{
write_data(tab1[i]);
}
write_com(0x80+9);//LCD第一行第10個位置起顯示"TL:"
for(i=0;i<3;i++)
{
write_data(tab2[i]);
}
write_com(0x80+0X40+0x00);//LCD第二行開始出顯示"Temp:"
for(i=0;i<5;i++)
{
write_data(tmp5[i]);
}
write_com(0x80+0X40+10);//顯示溫度的單位
for(i=0;i<2;i++)
{
write_data(tmp6[i]);
}
//以下是溫度的上限和下限初始化顯示部分
write_com(0x80+0x00+4);
write_data('+');
write_data(th/10+0x30);
write_data(th%10+0x30);
write_com(0x80+0x00+12);
write_data('+');
write_data(tl/10+0x30);
write_data(tl%10+0x30);
return 0;
}
/*********************************************************
DS18B20部分
**********************************************************/
uchar timecount;//定義中斷次數
uchar test0,test1,test;//溫度值變量
uchar a1,a2,a3;//溫度整數部分的十位,個位和小數部分的十分位
uchar readdate[2];//定義數組,用來暫存讀取的溫度值
sbit DQ=P3^0;//DS18B20數據口
bit sflag;//定義溫度的正負標志位
void delay1(uint i)//短延時函數
{
while(i--);
}
void reset()//DS18B20的復位函數
{
uchar x=0;
DQ=1;//使總線為高電平
delay1(8);//延時
DQ=0;//使總線為低電平
delay1(80);//延時,大于480us
DQ=1;//使總線為高電平
delay1(14);//延時,等待DS18B20回應低電平
x=DQ;//將DS18B20的回應讀到變量x,用于判斷復位是否成功
delay1(20);//延時一段時間結束
}
void writecmd(uchar cmd)//DS18B20的寫字節函數
{
uchar i=0;//定義位循環變量
for(i=8;i>0;i--)//循環8次
{
DQ=0;//總線拉低
DQ=cmd&0x01;//將發送字節的最低位送到總線
delay1(5);//延時(30us),等待DS18B20取走總線數據
DQ=1;//總線拉高
cmd>>=1;//將待發送的字節右移后,繼續發送
}
}
uchar readdat()//DS18B20的讀字節函數
{
uchar i=0;//定義位循環變量
uchar temp=0;//定義暫存變量
for(i=8;i>0;i--)//循環8次
{
DQ=0;//總線為低電平
temp>>=1;//暫存變量右移
DQ=1;//總線拉高,執行如下的讀操作
if(DQ)//如果DS18B20輸出高電平
temp|=0x80;//將暫存變量的最高位置1
delay1(4);//延時一段時間
}
return temp;//程序結束后,將暫存變量返回調用程序
}
/***************************************************
按鍵設置上線溫度和下限溫度值函數
****************************************************/
void key()
{
if(xuanze==0)//如果選擇鍵按下
{delay(10);//延時消抖
if(xuanze==0)//如果按鍵還處于按下狀態
{ num++;//次數加1
while(!xuanze);//等待按鍵抬起
if(num==1)//如果按下選擇鍵的次數為1
{
TR0=0;//關閉中斷
write_com(0x80+0x00+5);//光標移到第一行第七個位置
write_com(0x0f);//設置為顯示開,開光標,閃爍
}
if(num==2)//如果按下選擇鍵的次數為2
{
write_com(0x80+0x00+13);//光標移到第一行第十五個位置
}
if(num==3)//如果按下選擇鍵的次數為3
{
num=0;//次數清零
write_com(0x0c);//設置為顯示開,關光標,不閃爍
TR0=1;//開中斷
}
}
}
if(num!=0)//在選擇鍵按下時
{
if(up==0)//如果極限加按鍵按下
{
delay(10);//延時消抖
if(up==0)//如果極限加按鍵仍處于按下狀態
{
while(!up);//等待按鍵抬起
if(num==1)//如果選擇鍵按了一次
{
th++;//上線值加1
if(th>=0)//如果上線值為正
{thh=0;//計數清零
write_com(0x80+0x00+4);
write_data('+');//顯示正號
write_com(0x80+0x00+5);
write_data(th/10+0x30);//顯示上限溫度值的十位
write_data(th%10+0x30);//顯示上限溫度值的個位
}
if(th<0)
{
thh--;
write_com(0x80+0x00+4);
write_data('-');//顯示正號
write_com(0x80+0x00+5);
write_data(thh/10+0x30);//顯示上限溫度值的十位
write_data(thh%10+0x30);//顯示上限溫度值的個位
}
}
if(num==2)//如果選擇鍵按了兩次
{
tl++;//下限溫度值加1
if(tl>=0)//如果下限溫度值為正
{
tll=0;//計數清零
write_com(0x80+0x00+12); // 顯示正號
write_data('+');//
write_com(0x80+0x00+13);
write_data(tl/10+0x30);//顯示下限溫度值的十位
write_data(tl%10+0x30);//顯示下限溫度值的個位
}
if(tl<0)
{
tll--;
write_com(0x80+0x00+12);
write_data('-');//顯示正號
write_com(0x80+0x00+13);
write_data(tll/10+0x30);//顯示上限溫度值的十位
write_data(tll%10+0x30);//顯示上限溫度值的個位
}
}
}
}
if(down==0)//如果極限減按鍵按下
{
delay(10);//延時消抖
if(down==0)//如果按鍵仍處于按下狀態
{while(!down);//等待按鍵抬起
if(num==1)//如果選擇鍵按了一次
{
th--;//上限溫度值減1
if(th>=0)//如果上限溫度值為正
{
write_com(0x80+0x00+4); //顯示正號
write_data('+');
write_com(0x80+0x00+5);
write_data(th/10+0x30);//顯示上限溫度值的十位
write_data(th%10+0x30);//顯示上限溫度值的個位
}
if(th<0)//如果上限溫度值為負
{thh++;//計數變量加1
write_com(0x80+0x00+4);
write_data('-');//顯示負號
write_com(0x80+0x00+5);
write_data(thh/10+0x30);//顯示上限溫度值的十位
write_data(thh%10+0x30);//顯示上限溫度值的個位
}
}
}
if(num==2)//如果選擇鍵按了兩次
{
tl--;//下限溫度值減1
if(tl>=0)//如果下限溫度值為正
{
write_com(0x80+0x00+12);
write_data('+');//顯示正號
write_com(0x80+0x00+13);
write_data(tl/10+0x30);//顯示下限溫度值的十位
write_data(tl%10+0x30);//顯示下限溫度值的個位
}
if(tl<0)//如果下限溫度值為負
{tll++;//計數變量加1
write_com(0x80+0x00+12);
write_data('-');//顯示負號
write_com(0x80+0x00+13);
write_data(tll/10+0x30);//顯示下限溫度值的十位
write_data(tll%10+0x30);//顯示下限溫度值的個位
}
}
}
}
}
/******************************************************
報警函數
********************************************************/
sbit ddd=P1^0;
void baojing()
{
if((sflag==0&(test>=th|test<=tl))|(sflag==1&-test<=tl))//如果測得的溫度值>=上限溫度值(TH)或<=下限溫度值(TL)
{
redLED=~redLED;//發光二極管閃爍
delay(300);//延時
}
else
{
redLED=1;//否則發光二極管滅
}
}
/********************************************************
主函數
********************************************************/
void main()
{
init_lcd();//初始化LCD
TMOD=0X01;//定時器0,方式1
TH0=0X3C;//50ms溢出一次
TL0=0XB0;
TR0=1;//啟動定時器0
ET0=1;//開定時器0
EA=1;//開總中斷
while(1)
{
key();//調用按鍵函數
baojing();//調用報警函數
}
}
/************************************************************
中斷函數
**************************************************************/
void timer0() interrupt 1//定時器0中斷,中斷標號為1
{
uint result;//
TH0=0X3C;
TL0=0XB0;
timecount++;//每中斷一次,timecount加1
if(timecount==20)//中斷定時達到1S,50ms*20=1s
{timecount=0;//timecount清零
reset();//復位DS18B20
writecmd(0xcc);//向DS18B20發送跳過ROM搜索命令
writecmd(0x44);//啟動一次溫度轉換
reset();//復位DS18B20
writecmd(0xcc);//向DS18B20發送跳過ROM搜索命令
writecmd(0xbe);//發送讀溫度的命令?
readdate[0]=readdat();//讀溫度的低8位
readdate[1]=readdat();//讀溫度的高8位
sflag=0;//置負號標志為0
if(( readdate[1]&0xf8)!=0x00)//如果是負溫度值,執行如下取補碼語句
{ sflag=1;
readdate[1]=~ readdate[1];//高位取反碼
readdate[0]=~readdate[0];//低位取反碼
result=readdate[0]+1;//反碼加1
readdate[0]=result;//將取補的高溫度值,送回數組
if(result>255)//如果低8位有進位,則高8位加1
{readdate[1]++;//
}
}
test0=readdate[0];//低8位值賦予test0
test1=readdate[1];//高8位值賦予test1
test=((readdate[1]*256)+readdate[0])/16;//取出整數部分溫度值
test0=(test0|0x0f)/16;//取出小數部分溫度值
reset();//復位DS18B20
writecmd(0xcc);//向DS18B20發送跳過ROM搜索命令
writecmd(0x44);//啟動下次溫度測量
//以下是溫度值處理部分
write_com(0x80+0X40+0x05);
if(sflag==1)
write_data('-');//如果測得的溫度為負值,顯示負號
else
write_data('+');//如果測得的溫度為正值,顯示正號
a1=(test/10)|0x30;//溫度整數部分的十位
a2=(test%10)|0x30;//溫度整數部分的個位
write_com(0x80+0X40+0x06);
write_data(a1);//顯示溫度整數部分的十位
write_data(a2);//顯示溫度整數部分的個位
write_data('.');//顯示小數點
a3=(test0/10)|0x30;//溫度小數部分的十分位
write_data(a3); // 顯示溫度小數部分的十分位
}
ddd=sflag;
}
|
|