|
#include<reg51.h>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar i;
sbit RS=P2^7;
sbit RW=P2^6;
sbit E=P2^5;
sbit D1=P1^0;
sbit D2=P1^1;
sbit k1=P2^1;//加按键
sbit k2=P2^2;//减按键
sbit k3=P2^0;//设置按键
uint th=360;//设定 高温
uint tl=350;//设定 低温
uint ta;//实际温度
uchar code t0[]="WD= . ";
uchar code t1[]="TH= . TL= . ";
uchar code wendu[]="0123456789"; //利用一个温度表解决温度显示乱码
sbit DQ=P2^3;//定义DS18B20总线IO
uchar position;//设置的位置
//延时子函数
void delay(uint z)
{
uint x,y;
for(x=100;x>1;x--)
for(y=z;y>1;y--);
}
//LCD1602液晶写命令子函数
void write_com(uchar com)
{
RS=0;
P0=com;
delay(5);
E=1;
delay(5);
E=0;
}
//LCD1602液晶写数据子函数
void write_date(uchar date)
{
RS=1;
P0=date;
delay(5);
E=1;
delay(5);
E=0;
}
//LCD1602液晶初始化子函数
void LCD1602_init()
{
E=0;
RW=0;
write_com(0x38);
write_com(0x01);
write_com(0x0c);
write_com(0x06);
write_com(0x80);
for(i=0;i<16;i++)
{
write_date(t0[i]);
delay(0);
}
write_com(0x80+0x40);
for(i=0;i<16;i++)
{
write_date(t1[i]);
delay(0);
}
}
//延时子函数
void tmpDelay(int num)
{
while(num--);
}
//DS18B20温度传感器初始化子函数
void DS18B20_init()
{
uchar x=0;
DQ=1; //DQ复位
tmpDelay(8); //稍做延时
DQ=0; //单片机将DQ拉低
tmpDelay(80); //精确延时 大于 480us
DQ=1; //拉高总线
tmpDelay(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
tmpDelay(20);
}
//DS18B20温度传感器读一个字节子函数
uchar ReadOneChar()
{
uchar i=0;
uchar dat=0;
for(i=8;i>0;i--)
{
DQ=0; // 给脉冲信号
dat>>=1;
DQ=1; // 给脉冲信号
if(DQ)
dat|=0x80;
tmpDelay(4);
}
return(dat);
}
//DS18B20温度传感器写一个字节子函数
void WriteOneChar(uchar dat)
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
tmpDelay(5);
DQ=1;
dat>>=1;
}
}
//读取温度子函数
uint Readtemp()
{
uchar a=0;
uchar b=0;
uint t=0;
float tt=0;
DS18B20_init();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
DS18B20_init();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
a=ReadOneChar(); //连续读两个字节数据 //读低8位
b=ReadOneChar(); //读高8位
t=b;
t<<=8;
t=t|a; //两字节合成一个整型变量。
tt=t*0.0625; //得到真实十进制温度值,因为DS18B20可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度
t=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
return(t);
}
//LCD1602液晶显示子函数
void display()
{
uint shi,ge,xiaoshu; //这里的num,shi,ge,xiaoshu 必须用unsigned int无符号整数来表示,用unshigned char 字符型则显示错误
shi=th/100; //显示 最高温度 Th
ge=th/10%10;
xiaoshu=th%10;
write_com(0x80+0x40+3);
write_date(wendu[shi]);
write_com(0x80+0x40+4);
write_date(wendu[ge]);
write_com(0x80+0x40+6);
write_date(wendu[xiaoshu]);
shi=tl/100; //显示 最低文帝 Tl
ge=tl/10%10;
xiaoshu=tl%10;
write_com(0x80+0x40+11);
write_date(wendu[shi]);
write_com(0x80+0x40+12);
write_date(wendu[ge]);
write_com(0x80+0x40+14);
write_date(wendu[xiaoshu]);
}
//报警子函数
void temp_check()
{
uint shi,ge,xiaoshu; //这里的num,shi,ge,xiaoshu 必须用unsigned int无符号整数来表示,用unshigned char 字符型则显示错误
ta=Readtemp();
if(ta>th)
{
D1=0;
D2=1;
}
else if(ta<tl)
{
D1=1;
D2=0;
}
else
{
D1=1;
D2=1;
}
shi=ta/100; //显示 实际温度
ge=ta/10%10;
xiaoshu=ta%10;
write_com(0x80+3);
write_date(wendu[shi]);
write_com(0x80+4);
write_date(wendu[ge]);
write_com(0x80+6);
write_date(wendu[xiaoshu]);
}
//按键扫描子函数
void key()
{
if(k3==0) //set 按键 按下
{
delay(1);
if(k3==0)
{ //设置位置设定
position++;
if(position>2)
position=0;
if(position==0) // 无设置位置
{
write_com(0x80+0x40+7);
write_date(' ');
write_com(0x80+0x40+15);
write_date(' ');
}
if(position==1) //设置TH 在th后显示< 标识当前位置
{
write_com(0x80+0x40+7);
write_date('<');
write_com(0x80+0x40+15);
write_date(' ');
}
if(position==2) //设置Tl 在tl后显示< 标识当前位置
{
write_com(0x80+0x40+7);
write_date(' ');
write_com(0x80+0x40+15);
write_date('<');
}
while(k3==0);
}
}
if(k1==0)
{
delay(1);
if(k1==0)
{
if(position==1)
{
th+=5;
if(th>1000)
th=990;
}
if(position==2)
{
tl+=5; //tl>th时 是个错误,这里避免此情况发生
if(tl>=th)
tl=th-5;
}
display();
}
while(k1==0);
}
if(k2==0)
{
delay(1);
if(k2==0)
{
if(position==1)
{
th-=5; //th<tl时 是个错误,这里避免此情况发生
if(th<=tl)
th=tl+5;
}
if(position==2)
{
if(tl<10)
tl=10;
else
tl-=5;
}
display();
}
while(k2==0);
}
}
//主函数
void main()
{
uint i;
LCD1602_init();
display();
while(1)
{
delay(1);
if((++i)>500) //500ms 检测一次温度
{
temp_check();
i=0;
}
key();
}
}
|
评分
-
查看全部评分
|