#include<reg51.h> #include<intrins.h> #include"KEY.h" #include"IIC.h" #define uint unsigned int #define uchar unsigned char #define IICADDR 0x20 //存儲地址 #define LEDIO P0 //P0掃描段碼,P2掃描位選信號 #define LEDCHIP P2 sbit DQ=P3^2; //18B20接口 sbit BEEP=P3^7; // 蜂鳴器接口 uchar i=0,mod=0; //掃描變量 uchar key1,key2=20; //按鍵寄存 uchar Tmp_max=10,Tmp_min=5,Tmp; //溫度寄存 uint k=0,p=0,num=5000; //有關掃描的變量 /****************溫度小數部分用查表法*********************/ uchar code LedTab[14]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x063}; /***共陰數碼管段碼表 0 1 2 3 4 5 6 7 8 9 不亮 - ° */ uchar code selchip[6]={0x01,0x02,0x04,0x08,0x10,0x20};//列掃描位選信號 uchar data temp_data[2]={0x00,0x00};//讀出溫度暫放 uchar data display[3][7]={{0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x00}, //顯示單元數據,共6個數據一個用作運算 {0x00,0x3f,0x3f,0x3f,0x3f,0x76,0x00}, //顯示H設置最大值 {0x00,0x3f,0x3f,0x3f,0x3f,0x38,0x00}}; //顯示L設置最小值 /////////////////////////////////////////////////////////////////////////////// void Delay_tmp(uchar time) //延時10us { while(time--) { _nop_(); _nop_(); } } void Delay_2s() //延時兩秒開機檢測數碼管 { unsigned char a,b,c; for(c=23;c>0;c--) for(b=216;b>0;b--) for(a=184;a>0;a--); } /*********************定時器初始化***********************************/ void TimerInit() { TMOD=0x01; //定時器1定時掃描 ET0=1; EA=1; TH0=0xfc; TL0=0xd8; TR0=1; } /******************定時器中斷掃描程序**********************/ void timedis() interrupt 1 { if(mod) //閃爍程序,提醒用戶正在設置 { if(num--) //自動退出閃爍,返回主界面 { if(k++<190) { P2=0x00; } else { LEDIO=display[mod][i]; LEDCHIP=selchip[i]; if(i>=5) i=0; else i++; if(p++>190) { p=0; k=0; } } } else mod=0; } else //正常數碼管掃描顯示 { LEDIO=display[mod][i]; LEDCHIP=selchip[i]; if(i>=5) i=0; else i++; } TH0=0xfc; TL0=0xd8; } /*********************DS18B20復位函數*****************************/ void Temp_Reset(void) { EA=0; CY = 1; while (CY) { DQ = 0; //送出低電平復位信號 Delay_tmp(48); //延時至少480us DQ = 1; //釋放數據線 Delay_tmp(6); //等待60us CY = DQ; //檢測存在脈沖 Delay_tmp(42); //等待設備釋放數據線 } EA=1; } /************************寫一字節********************/ void Temp_Write_byte(uchar val) { uchar i; EA=0; for (i=8;i>0;i--) { DQ=0;_nop_();_nop_(); val >>=1;; //寫數據 DQ=CY; Delay_tmp(6); //延時66us等待采樣結束 DQ=1; //右移一位 } EA=1; } /***********************讀一字節****************************/ char Temp_Read_byte() { uchar i; uchar value=0; EA=0; for(i=0;i<8;i++) { value >>=1; //18B20右移一位 DQ=0;_nop_();_nop_(); //2us DQ=1;_nop_();_nop_(); //2us if(DQ) //讀出來的是1 value |=0x80; Delay_tmp(6); //66us } DQ=1; EA=1; return value; } /***********************讀出溫度函數*****************************************/ void Read_temp() { Temp_Reset(); //總線復位 Temp_Write_byte(0xcc);//發skip ROM命令 Temp_Write_byte(0xbe);//發讀命令 temp_data[0]=Temp_Read_byte();//讀低8位 temp_data[1]=Temp_Read_byte();//讀高8位 Temp_Reset(); Temp_Write_byte(0xcc);//發skip ROM命令 Temp_Write_byte(0x44); //溫度變換 while(!DQ); } /************************溫度數據處理函數************************************/ void Temp_Change() { bit n=0,n1=0,n2=0; Tmp= ((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4); //記錄當前的溫度值,用于比較 if(temp_data[1]>127) // 溫度為負時 { temp_data[1]=(256-temp_data[1]); //負溫度求補碼 temp_data[0]=(256-temp_data[0]); n=1; } display[0][6]=temp_data[0]&0x0f; display[0][4]=LedTab[(uchar)display[0][6]*5/8]; //小數部分 display[0][6]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4); //整數部分 display[0][1]=LedTab[display[0][6]/100]; //十六進制轉BCD碼 display[0][6]=display[0][6]%100; display[0][2]=LedTab[display[0][6]/10]; //十位段碼 display[0][3]=LedTab[(display[0][6]%10)]|0x80; //個位段碼帶小數點 display[0][5]=LedTab[12]; //顯示度 if(display[0][1]==LedTab[0]) //最高位為零時都不顯示 { display[0][1]=LedTab[10]; if(display[0][2]==LedTab[0]) //次高位處理 { display[0][2]=LedTab[10]; } } if(n) //負溫度時最高位顯示“-” display[0][0]=LedTab[11]; else display[0][0]=LedTab[10]; //////////////////////////////////////////////////處理鍵盤值 if(Tmp_max>127) //最高溫度上限處理 { n1=1; display[1][6]=(256-Tmp_max); //負數去反 } else display[1][6]=Tmp_max; display[1][1]=LedTab[display[1][6]/100]; //求最高位 display[1][6]=display[1][6]%100; //求次高位 display[1][2]=LedTab[display[1][6]/10]; display[1][3]=LedTab[display[1][6]%10]|0x80; //求個位段碼帶小數點 if(display[1][1]==LedTab[0]) //最高位為0不顯示 { display[1][1]=LedTab[10]; if(display[1][2]==LedTab[0]) //最高位為0次高位為0不顯示 { display[1][2]=LedTab[10]; } } if(n1) //負溫度時最高位顯示“-” display[1][0]=LedTab[11]; else { display[1][0]=LedTab[10]; //不顯示正 } ////////////////////////////////////////////////////////////// if(Tmp_min>127) //最低溫度下限處理 { n2=1; display[2][6]=(256-Tmp_min); //取反 } else display[2][6]=Tmp_min; display[2][1]=LedTab[display[2][6]/100]; //求最高位 display[2][6]=display[2][6]%100; //求次高位 display[2][2]=LedTab[display[2][6]/10]; display[2][3]=LedTab[display[2][6]%10]|0x80; //求個位段碼帶小數點 if(display[2][1]==LedTab[0]) //最高位為0不顯示 { display[2][1]=LedTab[10]; if(display[2][2]==LedTab[0]) //最高位為0次高位為0不顯示 { display[2][2]=LedTab[10]; } } if(n2) display[2][0]=LedTab[11]; //負溫度時最高位顯示“-” else { display[2][0]=LedTab[10]; //不顯示正 } } /***************************鍵盤掃描***************************************/ void Key_scanf() { key1=KeyTab[KeyRvs()]; //讀取鍵盤值 if(key2!=key1) //防止連續跳動,釋放按鍵 { if(key1=='*') //mod選擇 { mod=mod%2+1; num=5000; } if((key1=='0')&&(mod)) //按鍵加 { num=5000; if(mod==1) { if(Tmp_max==125) //最高上限溫度 Tmp_max=202; //最低溫度下限 else Tmp_max++; } if(mod==2) { if(Tmp_min==125) //最高上限溫度 Tmp_min=202; //最低溫度下限 else Tmp_min++; } } if((key1=='#')&&(mod)) //按鍵減 { num=5000; if(mod==1) { if(Tmp_max==202) //最低溫度下限 Tmp_max=125; //最高上限溫度 else Tmp_max--; } if(mod==2) { if(Tmp_min==202) //最低溫度下限 Tmp_min=125; //最高上限溫度 else Tmp_min--; } } if(key1=='D') //確定以后把修改的數據保存起來 { mod=0; //恢復正常顯示 EA=0; //IIC寫時候保護 while(!Write_Byte_iic(IICADDR,0xaa)); //寫判斷是否設置標志 while(!Write_Byte_iic(IICADDR+2,Tmp_max)); //寫溫度上限 while(!Write_Byte_iic(IICADDR+4,Tmp_min)); //寫溫度下限 EA=1; } } key2=key1; //鍵值保存。釋放按鍵用 } /**************************蜂鳴器報警***************************/ void Beep() { char a,b,c; a=Tmp;b=Tmp_max;c=Tmp_min; if((a>=b)||(a<c)) //比較上下限溫度, BEEP=~BEEP; //開蜂鳴器 else BEEP=1; //關閉蜂鳴器 } /////////////////////////////////////////////////////////// main() { if(Read_Byte_iic(IICADDR)==0xaa) //判斷是否修改過,若是修改過則讀取溫度上下限 { Tmp_max=Read_Byte_iic(IICADDR+2); //讀取報警溫度上限 Tmp_min=Read_Byte_iic(IICADDR+4); //讀取報警溫度下限 } Temp_Reset(); //開機先轉換一次 Temp_Write_byte(0xcc); //Skip ROM Temp_Write_byte(0x44); //發轉換命令 while(!DQ); TimerInit(); for(i=0;i<6;i++) { display[0][i]=LedTab[8]; } //開機顯示“888888” Delay_2s(); //顯示兩秒 while(1) { //讀出溫度數據 Read_temp(); //處理溫度數據 Temp_Change(); //溫度數據轉換 Key_scanf(); //鍵盤掃描 Beep(); //蜂鳴器掃描; } } ////////////////////////////////////////////////////////// 頭文件與電子鐘類似