#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit DQ=P2^3; //ds18b20與單片機連接口
sbit RS=P2^5; //液晶控制線接口
sbit RW=P2^6;
sbit EN=P2^7;
uchar data disdata[5];
uint tvalue,CurrentT=0; //溫度值
uchar tflag; //溫度正負標志
#define LCD_BUS P0
sbit SetKey = P2^0; //設置按鍵
sbit UpKey = P2^1; //加按鍵
sbit DnKey = P2^2; //減按鍵
sbit BEEP = P2^4; //蜂鳴器
sbit Heat = P1^0; //加熱繼電器控制
sbit Cool = P1^1; //降溫繼電器控制
unsigned char AlarmTempLow=0,AlarmTempTop=30,Set=0;
void delayms(uint ms) //延時xx毫秒
{
uchar i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void command(uint com) //LCD寫指令
{
RS=0; //RS為0
LCD_BUS=com; //裝載指令
delayms(5); //延時5ms
EN=1; //LCD使能
delayms(5); //延時5ms
EN=0; //LCD不使能
}
void write_dat(uchar dat) //LCD寫數(shù)據(jù)
{
RS=1; //RS為1
LCD_BUS=dat; //裝載數(shù)據(jù)
delayms(5); //延時5ms
EN=1; //LCD使能
delayms(5); //延時5ms
EN=0; //LCD不使能
}
void writestring(uchar x,uchar y,uchar *s) //LCD 寫字符串
{
if (y == 0) command(0x80 + x); //表示第一行
else command(0xC0 + x); //表示第二行
while (*s) //判斷是否字符串的結尾
{
write_dat( *s); //顯示當前字符
s ++; //字符串地址加1
}
}
void writeChar(uchar x,uchar y,uchar s) //LCD 寫字符串
{
if (y == 0) command(0x80 + x); //表示第一行
else command(0xC0 + x); //表示第二行
{
write_dat( s); //顯示當前字符
}
}
void LCD_Initial() //LCD初始化
{
EN=0; //LCD不使能
RW=0; //RW為0
command(0x38); //發(fā)送初始化指令
command(0x0c); //發(fā)送初始化指令
command(0x06); //發(fā)送初始化指令
command(0x01); //發(fā)送初始化指令
command(0x80+0x02); //發(fā)送LCD初始位置
}
/*************************DS1820程序****************************/
void delay_18B20(unsigned int i)//延時1微秒
{
while(i--);
}
void ds1820rst(void)/*ds1820復位*/
{
unsigned char x=0;
DQ = 1; //DQ復位
delay_18B20(4); //延時
DQ = 0; //DQ拉低
delay_18B20(100); //精確延時大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd(void)/*讀數(shù)據(jù)*/
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; //給脈沖信號
dat>>=1;
DQ = 1; //給脈沖信號
if(DQ)
dat|=0x80;
delay_18B20(10);
DQ=1;
}
return(dat);
}
void ds1820wr(uchar wdata)/*寫數(shù)據(jù)*/
{
unsigned char i=0;
for (i=8; i>0; i--) //寫一個字節(jié)數(shù)據(jù)到DS18B20
{
DQ = 0;
DQ = wdata&0x01; //寫一位數(shù)據(jù)
delay_18B20(10); //延時
DQ = 1; //拉高數(shù)據(jù)線
wdata>>=1; //準備下一位
}
}
unsigned int Read_Temperature(void)/*讀取溫度值并轉(zhuǎn)換*/
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳過讀序列號*/
ds1820wr(0x44);//*啟動溫度轉(zhuǎn)換*/
ds1820rst();
ds1820wr(0xcc);//*跳過讀序列號*/
ds1820wr(0xbe);//*讀取溫度*/
a=ds1820rd(); //讀取低位數(shù)據(jù)
b=ds1820rd(); //讀取高位數(shù)據(jù)
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a; //取得16位數(shù)據(jù)
if(tvalue<0x0fff) tflag=0; //判斷是否正溫度
else {tvalue=~tvalue+1;tflag=1;} //負溫度,數(shù)據(jù)取反,溫度標志位為1
tvalue=tvalue*(0.625);//溫度值擴大10倍,精確到1位小數(shù)
CurrentT=tvalue;//保存當前溫度
return(tvalue);//返回溫度值
}
void Display_Temperature() //顯示溫度
{
uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位數(shù)
disdata[1]=tvalue%1000/100+0x30;//十位數(shù)
disdata[2]=tvalue%100/10+0x30;//個位數(shù)
disdata[3]=tvalue%10+0x30;//小數(shù)位
if(tflag==0) flagdat=0x20;//正溫度不顯示符號
else flagdat=0x2d;//負溫度顯示負號:-
if(tflag==1)
{
writeChar(10,0,flagdat);//顯示符號位
writeChar(11,0,disdata[0]);//顯示百位
writeChar(12,0,disdata[1]);//顯示十位
writeChar(13,0,disdata[2]);//顯示個位
writeChar(14,0,0X2E);//顯示小數(shù)點
writeChar(15,0,disdata[3]);//顯示小數(shù)位
}
else
{
writeChar(10,0,disdata[0]);//顯示百位
writeChar(11,0,disdata[1]);//顯示十位
writeChar(12,0,disdata[2]);//顯示個位
writeChar(13,0,0X2e);//顯示小數(shù)點
writeChar(14,0,disdata[3]);//顯示小數(shù)位
writeChar(15,0,' ');//顯示小數(shù)位
}
}
void SetFun(void) //進入設置參數(shù)子函數(shù)
{
unsigned char i1=0,i2=0,i3=0,i4=0,i5=0,i6=0;
if(SetKey==0) //設置按鍵
{
delayms(20); //延時防抖
if(SetKey==0) //設置按鍵
{
if(Set<2) Set++; //設置按鍵次數(shù)累計
else Set=0;
}
switch(Set) //根據(jù)設置按鍵次數(shù),指向?qū)O置位置
{
case 0: writestring(0,1," ");writestring(8,1," ");break;//清除設置符號
case 1: writestring(0,1,">");writestring(8,1," ");break;//指向設置下限
case 2: writestring(0,1," ");writestring(8,1,">");break;//指向設置上限
}
while(SetKey==0);//等待按鍵松開
}
if((UpKey==0)&&(Set!=0))//加按鍵按下
{
delayms(20);//延時防抖
if(UpKey==0)//加按鍵按下
{
switch(Set)//根據(jù)設置按鍵次數(shù),設置上下限
{
case 1: if(AlarmTempLow<99) AlarmTempLow++;else AlarmTempLow=99; break;//設置下限
case 2: if(AlarmTempTop<99) AlarmTempTop++;else AlarmTempTop=99; break;//設置上限
}
i1 = AlarmTempLow/100; //獲得下限溫度值的百位
i2 = (AlarmTempLow%100)/10; //獲得下限溫度值的十位
i3 = AlarmTempLow%10; //獲得下限溫度值的個位
i4 = AlarmTempTop/100; //獲得上限溫度值的百位
i5 = (AlarmTempTop%100)/10; //獲得上限溫度值的十位
i6 = AlarmTempTop%10; //獲得上限溫度值的個位
writestring(5,1," "); //清除之前的內(nèi)容
writestring(13,1," "); //清除之前的內(nèi)容
if(i1!=0) writeChar(5,1,i1+'0'); //在第二行第5位 ,顯示下限溫度值的百位
if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0'); //在第二行第5位 ,顯示下限溫度值的十位
if(i1!=0) writeChar(6,1,i2+'0'); //在第二行第6位 ,顯示下限溫度值的十位
if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0'); //在第二行第5位 ,顯示下限溫度值的個位
else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0'); //在第二行第6位 ,顯示下限溫度值的個位
if((i1!=0)) writeChar(7,1,i3+'0'); //在第二行第7位 ,顯示下限溫度值的個位
if(i4!=0) writeChar(13,1,i4+'0'); //在第二行第13位 ,顯示上限溫度值的百位
if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0'); //在第二行第13位 ,顯示上限溫度值的十位
if(i4!=0) writeChar(14,1,i5+'0'); //在第二行第14位 ,顯示上限溫度值的十位
if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0'); //在第二行第13位 ,顯示上限溫度值的個位
else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0'); //在第二行第14位 ,顯示上限溫度值的個位
if((i4!=0)) writeChar(15,1,i6+'0'); //在第二行第15位 ,顯示上限溫度值的個位
while(UpKey==0); //等待按鍵松開
}
}
if((DnKey==0)&&(Set!=0))//減按鍵
{
delayms(20);
if(DnKey==0)//減按鍵
{
switch(Set)//根據(jù)設置按鍵次數(shù),設置上下限
{
case 1: if(AlarmTempLow>0) AlarmTempLow--;else AlarmTempLow=0; break;//設置下限
case 2: if(AlarmTempTop>0) AlarmTempTop--;else AlarmTempTop=0; break;//設置上限
}
i1 = AlarmTempLow/100; //獲得下限溫度值的百位
i2 = AlarmTempLow%100/10; //獲得下限溫度值的十位
i3 = AlarmTempLow%10; //獲得下限溫度值的個位
i4 = AlarmTempTop/100; //獲得上限溫度值的百位
i5 = AlarmTempTop%100/10; //獲得上限溫度值的十位
i6 = AlarmTempTop%10; //獲得上限溫度值的個位
writestring(5,1," "); //清除之前的內(nèi)容
writestring(13,1," ");//清除之前的內(nèi)容
if(i1!=0) writeChar(5,1,i1+'0');//在第二行第5位 ,顯示下限溫度值的百位
if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,顯示下限溫度值的十位
if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,顯示下限溫度值的十位
if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0');//在第二行第5位 ,顯示下限溫度值的個位
else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0');//在第二行第6位 ,顯示下限溫度值的個位
if((i1!=0)) writeChar(7,1,i3+'0');//在第二行第7位 ,顯示下限溫度值的個位
if(i4!=0) writeChar(13,1,i4+'0');//在第二行第13位 ,顯示上限溫度值的百位
if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,顯示上限溫度值的十位
if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,顯示上限溫度值的十位
if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0');//在第二行第13位 ,顯示上限溫度值的個位
else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0');//在第二行第14位 ,顯示上限溫度值的個位
if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,顯示上限溫度值的個位
while(DnKey==0);
}
}
}
void Alarm(void)//報警子函數(shù)
{
if((CurrentT>=(AlarmTempTop*10))||(CurrentT<=(AlarmTempLow*10))||(tflag==1)) //超出設定范圍
{
BEEP=0;//啟動報警
}
else //在設定范圍內(nèi)
{
BEEP=1;//取消報警
}
}
void main(void)
{
unsigned char i=0;
//P3=0xef;
P2=0xef;P1=0xff;BEEP=1;//端口初始化,
LCD_Initial(); //LCD 初始化
Read_Temperature(); //讀取溫度值
writestring(1,0,"DS18B20 Alarmer"); //顯示“DS18B20 Alarmer”
delayms(1000); //延時1S
writestring(0,0,"Current T= "); //顯示“Current T= ”
writestring(0,1," Low=0 Top=30 "); //顯示“ Low=10 Top=40 ”
//NG=0;
while(1)
{
Read_Temperature(); // //讀取溫度值
Display_Temperature(); //顯示溫度值
SetFun();//參數(shù)設置,按鍵功能
Alarm();//報警子函數(shù)
if((CurrentT<(AlarmTempTop*10))&&(CurrentT>(AlarmTempLow*10)))//當前溫度在設置范圍內(nèi)
{
Cool=1;Heat=1;//不加熱,不降溫
}
else if((CurrentT>=(AlarmTempTop*10)))//當前溫度高過設定值上限
{
Cool=0;Heat=1;//不加熱,降溫
}
else if((CurrentT<=(AlarmTempLow*10))||(tflag==1))//當前溫度低于下限
{
Cool=1;Heat=0;//加熱,不降溫
}
}
}
|