#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写数据
{
RS=1; //RS为1
LCD_BUS=dat; //装载数据
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); //发送初始化指令
command(0x0c); //发送初始化指令
command(0x06); //发送初始化指令
command(0x01); //发送初始化指令
command(0x80+0x02); //发送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)/*读数据*/
{
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)/*写数据*/
{
unsigned char i=0;
for (i=8; i>0; i--) //写一个字节数据到DS18B20
{
DQ = 0;
DQ = wdata&0x01; //写一位数据
delay_18B20(10); //延时
DQ = 1; //拉高数据线
wdata>>=1; //准备下一位
}
}
unsigned int Read_Temperature(void)/*读取温度值并转换*/
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd(); //读取低位数据
b=ds1820rd(); //读取高位数据
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a; //取得16位数据
if(tvalue<0x0fff) tflag=0; //判断是否正温度
else {tvalue=~tvalue+1;tflag=1;} //负温度,数据取反,温度标志位为1
tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
CurrentT=tvalue;//保存当前温度
return(tvalue);//返回温度值
}
void Display_Temperature() //显示温度
{
uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位
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);//显示小数点
writeChar(15,0,disdata[3]);//显示小数位
}
else
{
writeChar(10,0,disdata[0]);//显示百位
writeChar(11,0,disdata[1]);//显示十位
writeChar(12,0,disdata[2]);//显示个位
writeChar(13,0,0X2e);//显示小数点
writeChar(14,0,disdata[3]);//显示小数位
writeChar(15,0,' ');//显示小数位
}
}
void SetFun(void) //进入设置参数子函数
{
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++; //设置按键次数累计
else Set=0;
}
switch(Set) //根据设置按键次数,指向对应设置位置
{
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)//根据设置按键次数,设置上下限
{
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," "); //清除之前的内容
writestring(13,1," "); //清除之前的内容
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)//根据设置按键次数,设置上下限
{
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," "); //清除之前的内容
writestring(13,1," ");//清除之前的内容
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)//报警子函数
{
if((CurrentT>=(AlarmTempTop*10))||(CurrentT<=(AlarmTempLow*10))||(tflag==1)) //超出设定范围
{
BEEP=0;//启动报警
}
else //在设定范围内
{
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();//参数设置,按键功能
Alarm();//报警子函数
if((CurrentT<(AlarmTempTop*10))&&(CurrentT>(AlarmTempLow*10)))//当前温度在设置范围内
{
Cool=1;Heat=1;//不加热,不降温
}
else if((CurrentT>=(AlarmTempTop*10)))//当前温度高过设定值上限
{
Cool=0;Heat=1;//不加热,降温
}
else if((CurrentT<=(AlarmTempLow*10))||(tflag==1))//当前温度低于下限
{
Cool=1;Heat=0;//加热,不降温
}
}
}
|