#include <reg52.H>
#define uint unsigned int
#define uchar unsigned char //宏定义
#include <glzxj.h>
sbit RS=P2^5;
sbit RW=P2^6;
sbit E=P2^7;
sbit DQ=P2^0; //定义DS18B20总线I/O
sbit k1=P3^2;//定义按键K1
sbit k2=P3^3;//定义按键K2
sbit k3=P3^4;//定义按键K3
sbit k4=P3^5;//定义按键K4
sbit beep=P1^0; //蜂鸣器报警
sbit wendushangxian=P1^1; //上限报警控制
sbit wenduxiaxian=P1^2; //下限报警控制
uchar i,key_flag;
uchar set_temp_H_shi,set_temp_H_ge;//设定温度的变量
uchar set_temp_L_shi,set_temp_L_ge;//设定温度的变量
signed char set_temp_H=38, set_temp_L=8; //温度上限赋值38,温度下限赋值8
uint a,b,c,e,m;
uchar code tab_hy[]={"AT89C51+DS18B20 "};
uchar code tab_t[]={"TEMPERATURE:"};
uchar code tab_set_temp_H[]={"SET_TEMP_HIGH"};
uchar code tab_set_temp_L[]={"SET_TEMP_ LOW"};
uchar code tab_lcd_num[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code tab_lcd_xsd[]={'.'};
void delay1ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Delay(uint i)
{
while( i-- );
}
void delay_1602(uchar x)
{
uchar a,b;
for(a=0;a<10;a++)
{ for(b=x;b>0;b--); }
}
void write_cmd(uchar x)
{
E=0;
RS=0;
RW=0;
E=1;
P0=x;
delay_1602(50);
}
void write_dat(uchar y)
{
E=0;
RS=1;
RW=0;
E=1;
P0=y;
delay_1602(50);
E=0;
}
void busy()
{uchar a;
while(a==0x80)
{E=0;
RS=0;
RW=1;
E=1;
delay_1602(50);
a=P0;
}
}
void init_lcd()
{
busy();
write_cmd(0x38);
delay_1602(5);
busy();
write_cmd(0x01);
delay_1602(5);
busy();
write_cmd(0x0C);
delay_1602(5);
}
/*****初始化DS18B20*****/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1;
Delay(8); //稍做延时
DQ=0; //单片机将DQ拉低
Delay(80); //精确延时,大于480us
DQ=1; //拉高总线
Delay(14);
x=DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
Delay(20);
}
/*****读一个字节*****/
unsigned char ReadOneChar(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(4);
}
return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ=0;
DQ=dat&0x01;
Delay(5);
DQ=1;
dat>>=1;
}
}
void Tmpchange(void) //发送温度转换命令
{
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0x44); //启动温度转换
}
/*****读取温度*****/
unsigned int ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=0;
Tmpchange();
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
a=ReadOneChar(); //读低8位
b=ReadOneChar(); //读高8位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t= tt*100+0.5; //放大10倍输出并四舍五入
return(t);
}
void Display()
{
e=ReadTemperature(); //获取温度值
a=e/1000; //计算得到十位数字
b=e/100-a*10; //计算得到个位数字
c=(e%100)/10; //计算得到小数点后一位
m=e/100;
}
/////////////////////////显示温度 //////////////////////////
void disp_t_h()
{
write_cmd(0xcc);
write_dat(tab_lcd_num[a]);//显示温度十位
write_cmd(0xcd);
write_dat(tab_lcd_num[b]);//显示温度个位
write_cmd(0xce);
write_dat(tab_lcd_xsd[0]);//显示小数点
write_cmd(0xcf);
write_dat(tab_lcd_num[c]);//显示温度小数位
}
///////////////////////开机显示////////////////////////////////////
void disp_start()
{for(i=0;i<16;i++)
{write_cmd(0x80+i);
write_dat(tab_hy[i]);//AT89c51+ds18b20
delay1ms(150);
}
for(i=0;i<12;i++)
{write_cmd(0xc0+i);
write_dat(tab_t[i]);//温度
delay1ms(150);
}
}
///////////////////////扫描按键////////////////////////////////
void key_scan()
{
if(k1==0)//按下K1
{
//设置温度上限////////////////////////////////
if(key_flag==0)//按键标志0
{
write_cmd(0x01);//清屏
write_cmd(0x80);//显示位置第一行第一列
for(i=0;i<13;i++)
write_dat(tab_set_temp_H[i]);//显示SET_TEMP_HIGH字符
while(k4==1)//按下K4
{
if(k2==0)//按下K2
{ while(k2==0);
set_temp_H++;//设置温度数值加
if(set_temp_H==100)//到100,清0
set_temp_H=0;
}
if(k3==0)//按下K2
{ while(k3==0);//松手检测
set_temp_H--;//设置温度数值减
if(set_temp_H==0)//到0,加为100
set_temp_H=100;
}
set_temp_H_ge=set_temp_H%10;//计算设置温度个位
set_temp_H_shi=set_temp_H/10;//计算设置温度十位
write_cmd(0xc6);
write_dat(tab_lcd_num[set_temp_H_shi]);//显示设置温度个位
write_cmd(0xc7);
write_dat(tab_lcd_num[set_temp_H_ge]);//显示设置温度十位
}
}
//设置温度下限////////////////////////////////
if(key_flag==1)//按键标志1
{
write_cmd(0x01);//清屏
write_cmd(0x80);//显示位置第一行第一列
for(i=0;i<13;i++)
write_dat(tab_set_temp_L[i]);//显示SET_TEMP_ LOW字符
while(k4==1)//按下K4
{
if(k2==0)//按下K2
{ while(k2==0);
set_temp_L++;//设置温度数值加
if(set_temp_L==100)//到100,清0
set_temp_L=0;
}
if(k3==0)//按下K2
{ while(k3==0);//松手检测
set_temp_L--;//设置温度数值减
if(set_temp_L==0)//到0,加为100
set_temp_L=100;
}
set_temp_L_ge=set_temp_L%10;//计算设置温度个位
set_temp_L_shi=set_temp_L/10;//计算设置温度十位
write_cmd(0xc6);
write_dat(tab_lcd_num[set_temp_L_shi]);//显示设置温度个位
write_cmd(0xc7);
write_dat(tab_lcd_num[set_temp_L_ge]);//显示设置温度十位
}
}
//按键功能结束/////////////////////////////////////////////
key_flag++;
if(key_flag==2)//按键标志6
key_flag=0;
write_cmd(0x01);//清屏
//显示字符
for(i=0;i<16;i++)
{write_cmd(0x80+i);
write_dat(tab_hy[i]);//at89c51+ds18b20
delay1ms(5);
}
for(i=0;i<12;i++)
{write_cmd(0xc0+i);
write_dat(tab_t[i]);//温度
delay1ms(5);
}
}
}
////////////比较数据,开启或关闭 LED灯或者继电器以及蜂鸣器/////////////////////////////////////
void bijiao()
{
if(m>=set_temp_H)//如果温度大于设置温度上限,打开超出温度上限温度继电器和温度LED,
wendushangxian=0;//P1.1
else wendushangxian=1; //否则关闭超出温度上限温度继电器和温度LED
if(m<set_temp_L)//如果温度低于设置温度下限,打开低于温度下限温度继电器和温度LED
wenduxiaxian=0;//P1.2
else wenduxiaxian=1; //否则关闭低于温度下限温度继电器和温度LED
if(m>=set_temp_H||m<set_temp_L) //如果温度大于设置温度上限或者温度低于设置温度下限
beep=0; //打开蜂鸣器
else beep=1; //否则关闭蜂鸣器
}
uint wendu;
void main()
{
Init();
init_lcd();//初始化液晶1602
disp_start();//显示字符
while(1)
{
wendu=ReadTemperature();
DatW[0]=wendu;
DatW[1]=set_temp_H;
DatW[2]=set_temp_L;
Display();
disp_t_h();//显示温度
key_scan();
bijiao();
}
}