各位大神,如果我想加一个显示报警级别的功能和灯闪烁快慢(比如1级是报警最低,灯闪烁比较慢,15为最大,灯基本上常量),这个程序应该怎么改啊? 下面是代码和原理图:
#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 EN=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[]={"TEMPE: "}; 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_data[2]={0x00,0x00}; uchar temp_alarm[2]={0x00,0x00}; uchar display[5]={0x00,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}; //温度小数位对照表 //....................................................... //报警温度上下限(取值范围:-128~+127)(DS18B20温度范围为:-55~+125) //数组中前一位为高温值,后一位为低温值 //此处类型注意设为char,否则不能进行有符号数的比较 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 LCD_Status; RS=0;//寄存器选择 RW=1;//读状态寄存器EN=1;//开始读 DelayXus(1); LCD_Status=(bit)(P0&0x80) ; EN=0; return LCD_Status; } //写LCD指令 void Write_LCD_Command(uchar cmd) { while((LCD_Busy_Check()&0x80)==0x80); //忙等待 RS=0; //写选择命令寄存器 RW=0; //写 EN=0; P0=cmd; EN=1; DelayXus(1); EN=0; } //向LCD写数据 void Write_LCD_Data(uchar dat) { while((LCD_Busy_Check()&0x80)==0x80); //忙等待 RS=1;RW=0;EN=0;P0=dat;EN=1; DelayXus(1); EN=0; } //设置液晶显示位置 void Set_LCD_POS(uchar pos) { Write_LCD_Command(pos |0x80); } //LCD初始化 void LCD_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 //.................................. void Write_NEW_LCD_Char() { uchar i; Write_LCD_Command(0x40); //写CGRAM for(i=0;i<8;i++) Write_LCD_Data(Temperature_Char); //写入温度符号 } //............................................ //延时 //........................................................ 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(); //温度低8位 Temp_Value[1]=ReadOneByte(); //温度高8位 Alarm_Temp_HL[0]=ReadOneByte(); //报警温度TH Alarm_Temp_HL[1]=ReadOneByte(); //报警温度TL DS18B20_IS_OK=1; } } //............................................... //设置DS18B20温度报警值 //............................................... void Set_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上显示当前温度 //..................................................... void Display_Temperature() { uchar i; uchar t=150; //延时值 uchar ng=0; //负数标识 char Signed_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); //在第二行显示当前温度 Set_LCD_POS(0X40); for(i=0;i<16;i++) Write_LCD_Data(Current_Temp_Display_Buffer); //显示温度符号 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&0xF0)>>4); if(t>9) t+=0x37;else t+='0'; Write_LCD_Data(t); //高位数显示 t=RomCode&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=ReadOneByte(); } //......................................... //显示ROM CODE //............................... void Display_RomCode() { uchar i; Set_LCD_POS(0x00); for(i=0;i<16;i++) //显示标题 Write_LCD_Data(RomCodeStr); Read_Rom_Code(); //读64位序列码 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_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); Set_LCD_POS(0x40); //显示高低温 for (i=0;i<16;i++) Write_LCD_Data(Alarm_HI_LO_STR); } //................................ //主函数 //.................................. 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_RomCode(); DelayXus(50); break; } } }
|