//------------------------------------------------------------------------
// 名称:用1602LCD与DS18B20设计的温敏报警器(含读ROM CODE,温度上下限显示)
//------------------------------------------------------------------------
// 说明:本例将报警温度为高:70℃,低:-20℃ 当DS18B20感知温度达此临界
// 值时对应的LED闪烁,且发出警报声。
// 本例还可以显示DS18B20的ROM CODE及报警温度上下限。
//------------------------------------------------------------------------
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_();_nop_();_nop_();nop_()}
sbit HI_LED = P2^3; // 高温,低温报警闪烁LED
sbit LO_LED = P2^6;
sbit DQ = P3^3; //DS18B20 数据线
sbit BEEP = P3^7; //报警器
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
sbit K1=P1^7; //正常显示温度,越界时报警
sbit K2=P1^4; //显示报警温度
sbit K3=P1^1; //查看ROM CODE
uchar code RomCodeStr[]={"-- ROM CODE --"};
uchar RomCode[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//64位ROM CODE
uchar code Temp_Disp_Title[] ={"Current Temp:"};
uchar Current_Temp_Display_Buffer [ ] ={"TEMP: "};
uchar code Temperature_Char[8] ={0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00};
//温度字符
uchar code Alarm_Temp[] = {"ALARM Temp HI LO"};
uchar Alarm_HI_LO_STR[] ={"HI: LO: "};
uchar temp_date[2]= {0x00,0x00};
uchar temp_alarm[2]= {0x00,0x00};
uchar display[5] = {0x00,0x00,0x00,0x00};
uchar display1[3] = {0x00,0x00,0x00};
uchar code df_Table[] = {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
char Alarm_Temp_HL[2] ={ 70, -20 };
uchar CurrentT = 0; //读取当前的温度整数部分
uchar Temp_Value []= {0x00,0x00}; //从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0};
bit HI_Alarm = 0 , LO_Alarm = 0;
bit DS18B20_IS_OK = 1;
uint Time0_Count = 0;
//-------------------------------------------------------
//延时
//-------------------------------------------------------
void DelayXus(int x)
{
uchar i;
while(x--) for(i=0; i<200;i++);
}
bit LCD_Busy_check( )
{
bit result;
RS=0;RW=1;E=1;DelayXus(4); result=(bit)(P0& 0x80);E=0;
return result;
}
//-------------------------------------------------------
//向LCD发送命令
//-------------------------------------------------------
void Write_LCD_Command( uchar c)
{
while(LCD_Busy_check()); //判断LCD是否忙碌
RS=0;RW=0;E=0; _nop_();_nop_();P0=c;DelayXus(4);
E=1;DelayXus(4);E=0;
}
//-------------------------------------------------------
//设置LCD显示位置
//-------------------------------------------------------
void Set_LCD_POS(uchar pos)
{
Write_LCD_Command(pos | 0x80);
}
//-------------------------------------------------------
// 向LCD发送数据
//-------------------------------------------------------
void Write_LCD_Data(uchar dat)
{
while(LCD_Busy_check()) ;
RS= 1;RW=0;E=0;
P0= dat;DelayXus(4);
E=1;DelayXus(4);E=0;
}
//-------------------------------------------------------
//初始化LCD
//-------------------------------------------------------
void LCD_Initialise()
{
Write_LCD_Command(0x38); //开显示
Write_LCD_Command(0x0f); //清屏
Write_LCD_Command(0x01); //画面不动光标右移
Write_LCD_Command(0x06);
}
//-------------------------------------------------------------------------------
//
//通用显示函数
//
//-------------------------------------------------------------------------------
void Write_NEW_LCD_Char()
{
uchar i;
Write_LCD_Command( 0x40);
for ( i= 0;i<8;i++)
Write_LCD_Data(Temperature_Char[i]) ;
}
void Delay(uint num)
{
while(--num);
}
//-------------------------------------------------------
//初始化DS18B20
//-------------------------------------------------------
uchar Init_DS18B20()
{
uchar status;
DQ=1;Delay(8);
DQ=0;Delay(90);
DQ=1;Delay(8);
status=DQ;
Delay(100);
DQ=1;
return status; //初始化成功时返回0
}
//-------------------------------------------------------------
//读一字节
//-------------------------------------------------------------
uchar ReadOneByte()
{
uchar i,dat =0;
DQ=1; _nop_();
for(i= 0;i<8;i++)
{
DQ=0;dat>>=1; DQ=1;_nop_();_nop_();
if(DQ) dat|=0x80;Delay(30);DQ=1;
}
return dat;
}
void WriteOneByte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0;DQ=dat &0x01;Delay(5);DQ=1;dat>>=1;
}
}
//-------------------------------------------------------------
//读取温度值
//-------------------------------------------------------------
void Read_Temperature()
{
if( Init_DS18B20() ==1) //DS18B20故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xCC);
WriteOneByte(0x44);
Init_DS18B20() ;
WriteOneByte(0xCC);
WriteOneByte(0xBE);
Temp_Value[0]=ReadOneByte();
Temp_Value[1]=ReadOneByte();
Alarm_Temp_HL[0] = ReadOneByte();
Alarm_Temp_HL[1] = ReadOneByte();
DS18B20_IS_OK=1;
}
}
//-------------------------------------------------------------
//设置DS18B20温度报警值
//-------------------------------------------------------------
void Set_Alarm_Temp_Value()
{
Init_DS18B20();
WriteOneByte(0xCC);
WriteOneByte(0x4E);
WriteOneByte(Alarm_Temp_HL[0]) ;
WriteOneByte(Alarm_Temp_HL[1]) ;
WriteOneByte(0x7F);
WriteOneByte(0x48);
}
//-------------------------------------------------------------
//在LCD上显示温度
//-------------------------------------------------------------
void Display_Temperature()
{
uchar i;
uchar t=150;
uchar ng=0;
char Signed_Current_Temp;
if( ( Temp_Value[1] & 0xF8) ==0xF8)
{
Temp_Value[1]= ~Temp_Value[1];
Temp_Value[0]= ~Temp_Value[0]+1;
if ( Temp_Value[0] == 0x00 ) Temp_Value[1]++;
ng=1;
}
Display_Digit[0] =df_Table [ Temp_Value[0] & 0x0F ];
CurrentT = ( (Temp_Value[0] & 0x0F)>>4) |(Temp_Value[1] & 0x07)<<4;
Signed_Current_Temp = ng? -CurrentT : CurrentT;
HI_Alarm =Signed_Current_Temp >= Alarm_Temp_HL[0] ? 1 : 0;
LO_Alarm =Signed_Current_Temp <= Alarm_Temp_HL[1] ? 1 : 0;
Display_Digit[3]=CurrentT /100;
Display_Digit[2]=CurrentT %100 /10;
Display_Digit[1]=CurrentT % 10;
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11] = Display_Digit[0] +'0';
Current_Temp_Display_Buffer[10] = '.' ;
Current_Temp_Display_Buffer[9]=Display_Digit[1] +'0';
Current_Temp_Display_Buffer[8] = Display_Digit[2] +'0';
Current_Temp_Display_Buffer[7] = Display_Digit[3] +'0';
// 高位为0时不显示
if (Display_Digit[3] == 0) Current_Temp_Display_Buffer[7] = ' ';
//
if (Display_Digit[2] == 0 && Display_Digit[3] == 0)
Current_Temp_Display_Buffer[8] = ' ' ;
if(ng)
{
if (Current_Temp_Display_Buffer[8] == ' ' )
Current_Temp_Display_Buffer[8] = '-';
else
if (Current_Temp_Display_Buffer[7] ==' ')
Current_Temp_Display_Buffer[7] = '-' ;
else
Current_Temp_Display_Buffer[6] = '-';
}
//在第一行显示标题
Set_LCD_POS(0x00);
for( i=0; i<16;i++) Write_LCD_Data( Temp_Disp_Title[i]);
// 在第二行显示标题
Set_LCD_POS(0x40);
for( i=0; i<16;i++) Write_LCD_Data( Current_Temp_Display_Buffer[i]);
//显示温度符号
Set_LCD_POS(0x4D); Write_LCD_Data(0x00);
Set_LCD_POS(0x4E); Write_LCD_Data('C');
}
//---------------------------------------------------------------------------
//定时器中断,控制警报声音
//---------------------------------------------------------------------------
void T0_INT() interrupt 1
{
TH0 = -1000/256;
TL0 = -1000%256;
BEEP = !BEEP;
if( ++Time0_Count == 400)
{
Time0_Count =0;
if (HI_Alarm) HI_LED = ~HI_LED; else HI_LED = 0;
if (LO_Alarm) LO_LED = ~LO_LED; else LO_LED = 0;
TR0=0;
}
}
//---------------------------------------------------------------------------
//ROM CODE 转换与显示
//---------------------------------------------------------------------------
void Display_Rom_Code()
{
uchar i,t;
Set_LCD_POS(0x40);
for(i= 0;i<8;i++)
{
t=((RomCode[i]& 0xF0)>>4);
if(t>9) t+= 0x37;else t+='0';
Write_LCD_Data(t); //高位显示
t= RomCode[i]& 0x0F;
if(t>9) t+= 0x37;else t+='0';
Write_LCD_Data(t);
}
} //低位显示
// ---------------------------------------------------------------------------
// 读64位序列码
//---------------------------------------------------------------------------
void Read_Rom_Code()
{
uchar i;
Init_DS18B20();
WriteOneByte(0x33);
for (i=0;i<8;i++) RomCode[i]= ReadOneByte();
}
//---------------------------------------------------------------------------
//显示ROM CODE
//---------------------------------------------------------------------------
void Display_RomCode()
{
uchar i;
Set_LCD_POS(0x00) ;
for(i=0;i<16;i++)
Write_LCD_Data(RomCodeStr[i]);
Read_Rom_Code();
Display_Rom_Code();
} //显示64位ROM CODE
//------------------------------------------------------------------------------
//显示报警温度
//------------------------------------------------------------------------------
void Disp_Alarm_Temperature()
{
uchar i,ng;
//------------------------------------------------------------------------------
//显示Alarm_Temp_HL数组中的报警温度
//由于Alarm_Temp_HL类型为char故可以直接进行正负比较
//高温报警----------------------------------------------------------------------
ng=0;
if (Alarm_Temp_HL[0]<0) //如果为负数则取反加1
{
Alarm_Temp_HL[0]=~Alarm_Temp_HL[0]+1;
ng=1;
}
//分解高温各数位到待显示串中
Alarm_Temp_HL[0]=Alarm_HI_LO_STR[4] =Alarm_Temp_HL[0]/100 + '0';
Alarm_Temp_HL[0]=Alarm_HI_LO_STR[5] =Alarm_Temp_HL[0]/10 %10 + '0';
Alarm_Temp_HL[0]=Alarm_HI_LO_STR[6] =Alarm_Temp_HL[0]%10 + '0';
//屏蔽高位不显示的0
if( Alarm_HI_LO_STR[4]=='0') Alarm_HI_LO_STR[4] = ' ';
if( Alarm_HI_LO_STR[4]==' ' && Alarm_HI_LO_STR[5] == '0' )
Alarm_HI_LO_STR[5] = ' ';
//“-”符号显示
if (ng)
{
if( Alarm_HI_LO_STR[5] ==' ') Alarm_HI_LO_STR[5] = '-' ;
else
if( Alarm_HI_LO_STR[4] ==' ') Alarm_HI_LO_STR[4] = '-' ;
else
Alarm_HI_LO_STR[3] = '-';
}
//低温报警值
ng=0;
if(Alarm_Temp_HL[1]<0) //如果为负数则取反加1
{
Alarm_Temp_HL[1]= ~Alarm_Temp_HL[1]+1;
ng=1;
}
//分解高温各数位到待显示串中
Alarm_HI_LO_STR[12] =Alarm_Temp_HL[1]/100+'0';
Alarm_HI_LO_STR[13] =Alarm_Temp_HL[1]/10 %10+'0';
Alarm_HI_LO_STR[14] =Alarm_Temp_HL[1]%10+'0';
// 屏蔽高位不显示的0
if( Alarm_HI_LO_STR[12]=='0') Alarm_HI_LO_STR[12] =' ';
if( Alarm_HI_LO_STR[12]==' ' && Alarm_HI_LO_STR[13] =='0');
Alarm_HI_LO_STR[13] =' ';
if(ng)
{
if(Alarm_HI_LO_STR[13] == ' ') Alarm_HI_LO_STR[13] ='-';
else
if(Alarm_HI_LO_STR[12] == ' ') Alarm_HI_LO_STR[12] ='-';
else
Alarm_HI_LO_STR[11] ='-';
}
//显示高低温报警温度值
Set_LCD_POS(0x00);
for(i=0;i<16;i++) Write_LCD_Data(Alarm_Temp[i]);
Set_LCD_POS(0x40); //显示高低温
for(i=0;i<16;i++) Write_LCD_Data(Alarm_HI_LO_STR[i]);
}
//-------------------------------------------------------------------
//主函数
//-------------------------------------------------------------------
void main()
{
uchar Current_Operation= 1;
LCD_Initialise();
IE=0x82;
TMOD=0x01;
TH0=-1000/256;
TL0=-1000%256;
TR0=0;
HI_LED=0;
LO_LED=0;
Set_Alarm_Temp_Value();
Read_Temperature();
Delay(50000) ;
Delay(50000);
while(1)
{
if(K1==0) Current_Operation= 1;
if(K2==0) Current_Operation= 2;
if(K3==0) Current_Operation= 3;
switch(Current_Operation)
{
case 1: // 正常显示当前温度,越界时报警
Read_Temperature();
if(DS18B20_IS_OK)
{
if(HI_Alarm==1|| LO_Alarm ==1) TR0=1;
else TR0=0;
Display_Temperature();
}
DelayXus(100);
break;
case 2: //显示报警温度上下限
Read_Temperature();
Disp_Alarm_Temperature();
DelayXus(100);
break;
case 3: //显示DS18B20 ROM CODE
Display_Rom_Code();
DelayXus(100);
break;
}
}
}