|
#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;
}
|
|