基于单片机的温度报警系统proteus仿真.docx
《基于单片机的温度报警系统proteus仿真.docx》由会员分享,可在线阅读,更多相关《基于单片机的温度报警系统proteus仿真.docx(17页珍藏版)》请在冰豆网上搜索。
基于单片机的温度报警系统proteus仿真
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definedelayNOP(){_nop_();_nop_();_nop_();_nop_();}
sbitHI_LED=P2^3;//高温,低温白净闪烁LED
sbitLO_LED=P2^6;
sbitDQ=P3^3;//DS18B20数据线
sbitBEEP=P3^7;//报警
sbitRS=P2^0;
sbitRW=P2^1;
sbitEN=P2^2;
sbitK1=P1^7;//正常显示温度,越界时报警
sbitK2=P1^4;//显示报警温度
sbitK3=P1^1;//查看ROMCODE
ucharcodeRomCodeStr[]={"--ROMCODE--"};
ucharRomCode[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//64位ROMCODE
ucharcodeTemp_Disp_Title[]={"CurrentTemp:
"};
ucharCurrent_Temp_Display_Buffer[]={"TEMPE:
"};
ucharcodeTemperature_Char[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};//温度示字符
ucharcodeAlarm_Temp[]={"ALARMTEMPHiLo"};
ucharAlarm_HI_LO_STR[]={"Hi:
Lo:
"};
uchartemp_data[2]={0x00,0x00};
uchartemp_alarm[2]={0x00,0x00};
uchardisplay[5]={0x00,0x00,0x00,0x00,0x00,};//温度值
uchardisplay1[3]={0x00,0x00,0x00};//温度报警值
ucharcodedf_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};//温度小数位对照表
//.......................................................
//报警温度上下限(取值范围:
-128~+127)(DS18B20温度范围为:
-55~+125)
//数组中前一位为高温值,后一位为低温值
//此处类型注意设为char,否则不能进行有符号数的比较
charAlarm_Temp_HL[2]={70,-20};
//............................................................
ucharCurrentT=0;//当前读取温度整数部分
ucharTemp_Value[]={0x00,0x00};//从DS18B20读取的温度值
ucharDisplay_Digit[]={0,0,0,0};//待显示的各温度数位
bitHI_Alarm=0,LO_Alarm=0;//高低温报警标志
bitDS18B20_IS_OK=1;//传感器正常标志
uintTime0_Count=0;//定时器延时累加
//...........................
//延时
//...........................
voidDelayXus(intx)
{
uchari;
while(x--)for(i=0;i<200;i++);
}
//.......................................
//忙检测
bitLCD_Busy_Check()
{
bitLCD_Status;
RS=0;//寄存器选择
RW=1;//读状态寄存器EN=1;//开始读
DelayXus
(1);
LCD_Status=(bit)(P0&0x80);
EN=0;
returnLCD_Status;
}
//写LCD指令
voidWrite_LCD_Command(ucharcmd)
{
while((LCD_Busy_Check()&0x80)==0x80);//忙等待
RS=0;//写选择命令寄存器
RW=0;//写
EN=0;
P0=cmd;EN=1;DelayXus
(1);EN=0;
}
//向LCD写数据
voidWrite_LCD_Data(uchardat)
{
while((LCD_Busy_Check()&0x80)==0x80);//忙等待
RS=1;RW=0;EN=0;P0=dat;EN=1;DelayXus
(1);EN=0;
}
//设置液晶显示位置
voidSet_LCD_POS(ucharpos)
{
Write_LCD_Command(pos|0x80);
}
//LCD初始化
voidLCD_Initialise()
{
Write_LCD_Command(0x38);
DelayXus
(1);
Write_LCD_Command(0x01);//清屏
DelayXus
(1);
Write_LCD_Command(0x06);//字符进入模式:
屏幕不动,字符后移
DelayXus
(1);
Write_LCD_Command(0x0C);//显示开,关光标
DelayXus
(1);
}
//...............................................
//..........................................
//自定义字符写CGRAM
//..................................
voidWrite_NEW_LCD_Char()
{
uchari;
Write_LCD_Command(0x40);//写CGRAM
for(i=0;i<8;i++)
Write_LCD_Data(Temperature_Char[i]);//写入温度符号
}
//............................................
//延时
//........................................................
voidDelay(uintnum)
{
while(--num);
}
//...............................................
//初始化DS18B20
//...............................................
ucharInit_DS18B20()
{
ucharstatus;
DQ=1;Delay(8);
DQ=0;Delay(90);
DQ=1;Delay(8);
status=DQ;
Delay(100);
DQ=1;
returnstatus;//初始化成功时返回0
}
//...............................................
//读一节
//...............................................
ucharReadOneByte()
{
uchari,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;
}
returndat;
}
//...............................................
//写一字节
//...............................................
voidWriteOneByte(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
DQ=0;DQ=dat&0x01;Delay(5);DQ=1;dat>>=1;
}
}
//...............................................
//读取温度值
//...............................................
voidRead_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();//温度低8位
Temp_Value[1]=ReadOneByte();//温度高8位
Alarm_Temp_HL[0]=ReadOneByte();//报警温度TH
Alarm_Temp_HL[1]=ReadOneByte();//报警温度TL
DS18B20_IS_OK=1;
}
}
//...............................................
//设置DS18B20温度报警值
//...............................................
voidSet_Alarm_Temp_Value()
{
Init_DS18B20();
WriteOneByte(0xCC);//跳过序列号
WriteOneByte(0x4E);//将设定的温度报警值写入DS18B20
WriteOneByte(Alarm_Temp_HL[0]);//写TH
WriteOneByte(Alarm_Temp_HL[1]);//写TL
WriteOneByte(0x7F);//12位精度
Init_DS18B20();
WriteOneByte(0xCC);//跳过序列号
WriteOneByte(0x48);//温度报警值存入DS18B20
}
//......................................................
//在LCD上显示当前温度
//.....................................................
voidDisplay_Temperature()
{
uchari;
uchart=150;//延时值
ucharng=0;//负数标识
charSigned_Current_Temp;
//如果为负数则取反加1,并设置负数标识
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]&0xF0)>>4)|((Temp_Value[1]&0x07)<<4);
//有符号的当前温度值,注意此处定义为char,其值可为-128~+127
Signed_Current_Temp=ng?
-CurrentT:
CurrentT;
//高低温报警标志设置(与定义为char类型的Alarm_Temp_HL比较,这样可区分正负比较)
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]='';
//高位为0且次高位为0时,次高位不显示
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');
}
//.....................................
//定时器中断,控制报警声音
//.................................
voidT0_INT()interrupt1
{
TH0=-1000/256;
TL0=-1000%256;
BEEP=!
BEEP;
if(++Time0_Count==400)
{
Time0_Count=0;
if(HI_Alarm)HI_LED=~HI_LED;elseHI_LED=0;
if(LO_Alarm)LO_LED=~LO_LED;elseLO_LED=0;
TR0=0;
}
}
//...............................................
//ROMCODE转换与显示
//.....................................................
voidDisplay_Rom_Code()
{
uchari,t;
Set_LCD_POS(0x40);
for(i=0;i<8;i++)
{
t=((RomCode[i]&0xF0)>>4);
if(t>9)t+=0x37;elset+='0';
Write_LCD_Data(t);//高位数显示
t=RomCode[i]&0x0F;
if(t>9)t+=0x37;elset+='0';
Write_LCD_Data(t);//低位数显示
}
}
//..................................
//读64位序列码
//...............................
voidRead_Rom_Code()
{
uchari;
Init_DS18B20();
WriteOneByte(0x33);//读序列码
for(i=0;i<8;i++)RomCode[i]=ReadOneByte();
}
//.........................................
//显示ROMCODE
//...............................
voidDisplay_RomCode()
{
uchari;
Set_LCD_POS(0x00);
for(i=0;i<16;i++)//显示标题
Write_LCD_Data(RomCodeStr[i]);
Read_Rom_Code();//读64位序列码
Display_Rom_Code();//显示64位ROMCODE
}
//.......................................
//显示报警温度
//...............................................
voidDisp_Alarm_Temperature()
{
uchari,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_HI_LO_STR[4]=Alarm_Temp_HL[0]/100+'0';
Alarm_HI_LO_STR[5]=Alarm_Temp_HL[0]/10%10+'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[0]/10%10+'0';
Alarm_HI_LO_STR[14]=Alarm_Temp_HL[0]%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]);
}
//................................
//主函数
//..................................
voidmain()
{
ucharCurrent_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)
{
case1:
//正常显示当前温度,越界时报警
Read_Temperature();
if(DS18B20_IS_OK)
{
if(