#include<reg51.h>
#include<intrins.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef char int8;
typedef int int16;
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit BUSY=P0^7;
sbit DQ=P2^4; //温度输入口
sbit EQ=P2^5;
sbit FQ=P2^6;
sbit SET=P3^2;//设置
sbit ADD=P1^1;//加减
sbit SUB=P1^2;//减键
sbit OK=P1^3;//确定键
sbit LED=P1^7;
sbit BEEP=P1^6;
uint8 flag;
int p=30,q=0,k=0;
int data set[4];
uint8 num_temp[]={"0123456789"};
#define nops(); {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令 4us
void delay(uint16 n)
{
while (n--);
}
void delay_ms(uint16 m)
{
uint8 n=120;
while(m--)
while(n--);
}
/*
* DQ:18B20复位函数
*/
void DS1802_reset()
{
uint8 flag=1;
while(flag)
{
while(flag)
{
DQ=1;
delay(1);
DQ=0;
delay(50); //550us
DQ=1;
while(DQ);
delay(6); //66us
flag=DQ;
}
delay(45);//延时500us
flag=~DQ;//500us后总线释放,DQ=1;
}
DQ=1;
}
/*
* EQ:18B20复位函数
*/
void EQDS1802_reset()
{
uint8 flag=1;
while(flag)
{
while(flag)
{
EQ=1;
delay(1);
EQ=0;
delay(50); //550us
EQ=1;
while(EQ);
delay(6); //66us
flag=EQ;
}
delay(45);//延时500us
flag=~EQ;//500us后总线释放,DQ=1;
}
EQ=1;
}
/*
* FQ:18B20复位函数
*/
void FQDS1802_reset()
{
uint8 flag=1;
while(flag)
{
while(flag)
{
FQ=1;
delay(1);
FQ=0;
delay(50); //550us
FQ=1;
while(FQ);
delay(6); //66us
flag=FQ;
}
delay(45);//延时500us
flag=~FQ;//500us后总线释放,DQ=1;
}
FQ=1;
}
/*
* 18B20写1个字节函数
* 向1-WIRE总线上写一个字节
*/
void write_byte(uint8 dat)
{
uint8 i;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
nops();
DQ=dat&0x01;//最低位移出
delay(6); //66us
dat>>=1; //右移一位
}
DQ=1;
delay(1);
}
/*EQ: 向1-WIRE总线上写一个字节
*/
void EQwrite_byte(uint8 dat)
{
uint8 i;
for(i=0;i<8;i++)
{
EQ=1;
_nop_();
EQ=0;
nops();
EQ=dat&0x01;//最低位移出
delay(6); //66us
dat>>=1; //右移一位
}
EQ=1;
delay(1);
}
/*FQ: 向1-WIRE总线上写一个字节
*/
void FQwrite_byte(uint8 dat)
{
uint8 i;
for(i=0;i<8;i++)
{
FQ=1;
_nop_();
FQ=0;
nops();
FQ=dat&0x01;//最低位移出
delay(6); //66us
dat>>=1; //右移一位
}
FQ=1;
delay(1);
}
/*
* 18B20读1个字节函数
* 从1-WIRE总线上读取一个字节
*/
uint8 read_byte()
{
uint8 i,byte=0;
for(i=0;i<8;i++)
{
byte>>=1;
DQ=1;
_nop_();
DQ=0;
nops();
DQ=1;
nops();
if(DQ==1) byte|=0x80;
delay(6);
}
DQ=1;
return byte;
}
/*EQ*/
uint8 EQread_byte()
{
uint8 i,byte=0;
for(i=0;i<8;i++)
{
byte>>=1;
EQ=1;
_nop_();
EQ=0;
nops();
EQ=1;
nops();
if(EQ==1) byte|=0x80;
delay(6);
}
EQ=1;
return byte;
}
/*FQ*/
uint8 FQread_byte()
{
uint8 i,byte=0;
for(i=0;i<8;i++)
{
byte>>=1;
FQ=1;
_nop_();
FQ=0;
nops();
FQ=1;
nops();
if(FQ==1) byte|=0x80;
delay(6);
}
FQ=1;
return byte;
}
/*
* 启动温度转换
*/
void start_temp_sensor()
{
DS1802_reset();
write_byte(0xcc); // 发Skip ROM命令
write_byte(0x44); // 发转换命令
}
/**EQ启动温度转换**/
void EQstart_temp_sensor()
{
EQDS1802_reset();
EQwrite_byte(0xcc); // 发Skip ROM命令
EQwrite_byte(0x44); // 发转换命令
}
/**FQ启动温度转换**/
void FQstart_temp_sensor()
{
FQDS1802_reset();
FQwrite_byte(0xcc); // 发Skip ROM命令
FQwrite_byte(0x44); // 发转换命令
}
/*
* 读出温度
*/
int16 read_temp()
{
uint8 temp_data[2]; // 读出温度暂放
uint16 temp;
DS1802_reset(); // 复位
write_byte(0xcc); // 发Skip ROM命令
write_byte(0xbe); // 发读命令
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp=temp_data[1];
temp<<=8;
temp|=temp_data[0];
//temp>>=4; //右移四位,相当于除以16(1/16=0.0625)
return temp;
}
/****EQ读出温度****/
int16 EQread_temp()
{
uint8 EQtemp_data[2]; // 读出温度暂放
uint16 EQtemp;
EQDS1802_reset(); // 复位
EQwrite_byte(0xcc); // 发Skip ROM命令
EQwrite_byte(0xbe); // 发读命令
EQtemp_data[0]=EQread_byte(); //温度低8位
EQtemp_data[1]=EQread_byte(); //温度高8位
EQtemp=EQtemp_data[1];
EQtemp<<=8;
EQtemp|=EQtemp_data[0];
//temp>>=4; //右移四位,相当于除以16(1/16=0.0625)
return EQtemp;
}
/****FQ读出温度****/
int16 FQread_temp()
{
uint8 FQtemp_data[2]; // 读出温度暂放
uint16 FQtemp;
FQDS1802_reset(); // 复位
FQwrite_byte(0xcc); // 发Skip ROM命令
FQwrite_byte(0xbe); // 发读命令
FQtemp_data[0]=FQread_byte(); //温度低8位
FQtemp_data[1]=FQread_byte(); //温度高8位
FQtemp=FQtemp_data[1];
FQtemp<<=8;
FQtemp|=FQtemp_data[0];
//temp>>=4; //右移四位,相当于除以16(1/16=0.0625)
return FQtemp;
}
/*
* 读忙状态
*/
void wait()
{
P0=0xff;
do
{
EN=0;
RS=0;
RW=1;
EN=1;
}while(BUSY==1);
EN=0;
}
/*
* 写指令
*/
void write_cmd(uint8 cmd)
{
wait();
EN=0;
P0=cmd;
RS=0;
RW=0;
EN=1;
EN=0;
}
/*
* 写数据
*/
void write_dat(uint8 dat)
{
wait();
EN=0;
P0=dat;
RS=1;
RW=0;
EN=1;
EN=0;
}
/*
* 写地址和数据
*/
void write_lcd1602(uint8 addr,uint8 dat)
{
write_cmd(addr);
write_dat(dat);
}
/*
* 初始化
*/
void lcd1602_init()
{
write_cmd(0x38);
delay_ms(5);
write_cmd(0x38);
delay_ms(5);
write_cmd(0x38);
delay_ms(5);
write_cmd(0x0c);
write_cmd(0x06);
write_cmd(0x01);
write_lcd1602(0x80,'A');//标识符固定显示。
write_lcd1602(0x81,':');
write_lcd1602(0x88,'B');
write_lcd1602(0x89,':');
write_lcd1602(0xC0,'C');
write_lcd1602(0xC1,':');
}
/**上、下限温度显示函数*/
void Show_ptemp(void)
{
uint16 pt;
if(p<0)
{
pt=~p+1;
write_lcd1602(0x82,'-');
}
else
{
pt=p;
write_lcd1602(0x82,'+');
}
set[0]=pt/10+0x30; //显示上限值
set[1]=pt%10+0x30;
write_lcd1602(0x80,'H');
write_lcd1602(0x81,':');
write_lcd1602(0x83,set[0]);
write_lcd1602(0x84,set[1]);
}
void Show_qtemp(void)
{
uint16 qt;
if(q<0)
{
qt=~q+1;
write_lcd1602(0xc2,'-');
}
else
{
qt=q;
write_lcd1602(0xc2,'+');
}
set[2]=qt/10+0x30;
set[3]=qt%10+0x30;
write_lcd1602(0xc0,'L');
write_lcd1602(0xc1,':');
write_lcd1602(0xc3,set[2]);
write_lcd1602(0xc4,set[3]);//显示下限值
}
/************报警功能**********/
void alarm(float temp)
{
int i;
if(temp>=p)
{
LED=1;
for(i=0;i<3;i++)
{
BEEP=1;
delay_ms(1000);
BEEP=0;
delay_ms(50);
}
LED=0; }
if(temp<=q)
{ BEEP=1;delay_ms(2000);BEEP=0;}
}
void show_temp(uint16 temp,uint8 saddr){
temp=(temp*0.0625)*10+0.5;
write_lcd1602(saddr,num_temp[(temp%1000)/100]);
write_lcd1602(saddr+1,num_temp[(temp%100)/10]);
write_lcd1602(saddr+2,'.');
write_lcd1602(saddr+3,num_temp[temp%10]);
// if(1==flag){
alarm(temp/10);
// }
// else{
// alarm(temp/10);
// }
}
/*
* 主函数
*/
void main()
{
uint16 temp;
uint16 EQtemp;
uint16 FQtemp;
lcd1602_init();
BEEP=0;
LED=0;
EA=1; //全局中断开
EX0=1; //外部中断0开
//EX1=1; //外部中断1开
IT0=0; //边沿触发,为0则为低电平触发
//IT1=1; //边沿触发,为0则为低电平触发
while(1)
{
/*按下SET键进入上下限温度调节,SET键同时是调节上下限温度的切换键*/
// start_temp_sensor();
temp=read_temp();
if(temp&0x8000) //判定是否为负
{
write_lcd1602(0x82,'-');
temp=~temp+1;
// flag=1;
}
else{
write_lcd1602(0x82,' ');
// flag=0;
}
show_temp(temp,0x83);
// EQstart_temp_sensor();
EQtemp=EQread_temp();
if(EQtemp&0x8000) //判定是否为负
{
EQtemp=~EQtemp+1;
write_lcd1602(0x8a,'-');
// flag=1;
}
else
{
write_lcd1602(0x8a,' ');
// flag=0;
}
show_temp(EQtemp,0x8b);
// FQstart_temp_sensor();
FQtemp=FQread_temp();
if(FQtemp&0x8000) //判定是否为负
{
FQtemp=~FQtemp+1;
write_lcd1602(0xC2,'-');
// flag=1;
}
else
{
write_lcd1602(0xC2,' ');
// flag=0;
}
show_temp(FQtemp,0xC3);
}
}
/***按键***/
void ISR0_Key() interrupt 0
{
delay_ms(20);//等待系统稳定
if(!SET){
write_cmd(0x38);
delay_ms(5);
write_cmd(0x0c);
write_cmd(0x06);
write_cmd(0x01);
}
else{
return;
}
while(1)
{
if(!SET)
{
delay_ms(20);
if(!SET){
if(k==2)
k=0;
k++;
}
}
///*调节上限温度
if(!ADD && k==1)//如果端口电平不为高,说明可能该键已被按下
{
delay_ms(20);//延时去抖动
if(!ADD)//P11仍然不为高,确定该键已被按下
{
p++; //加1
while(!ADD);//等待按键释放
}
}
if(!SUB && k==1)//如果端口电平不为高,说明可能该键已被按下
{
delay_ms(20);//延时去抖动
if(!SUB)//P12仍然不为高,确定该键已被按下
{
p--; //减1
while(!SUB);//等待按键释放
}
}
///*调节下限温度
if(!ADD && k==2)//如果端口电平不为高,说明可能该键已被按下
{
delay_ms(20);//延时去抖动
if(!ADD)//P11仍然不为高,确定该键已被按下
{
q++; //加1
while(!ADD);//等待按键释?
}
}
if(!SUB && k==2)//如果端口电平不为高,说明可能该键已被按下
{
delay_ms(20);//延时去抖动
if(!SUB)//P12仍然不为高,确定该键已被按下
{
q--; //减1
while(!SUB);//等待按键释?
}
}
Show_ptemp();
Show_qtemp();
if(!OK)
{ //按下OK键退出调节
delay_ms(20);
if(!OK)
break;
}
}
lcd1602_init();
}
|