|
| 先看看成功案例吧! |
|
這是數碼管時鐘程序,其中的按鍵程序可以滿足你的需要: //K1鍵調整選擇,K2鍵+,長按連+,K3鍵-,長按連- //定時器初始化程序根據晶振頻率選擇 //主程序循環一次必須小于100us,否則要更改定時器周期 //用計數法代替軟件延時,提高走時精度 //數碼管采用分時動態顯示,約2ms顯示1位 #include <reg51.h> #define uint unsigned int #define uchar unsigned char #define key_S 300 //宏定義短按(約20ms) #define key_L 6000 //宏定義長按(約2/3s) #define key_M 3000 //宏定義長按(約1/3s) sbit K1 = P3^4; //調整選擇/退出 sbit K2 = P3^5; //++,長按連+ sbit K3 = P3^6; //--,長按連- sbit dula=P2^6; //段選 sbit wela=P2^7; //位選 uchar code table[]={ //0~F數組 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; uint Cnt100us; //定義100微秒變量 uchar hour=12,min=0,sec=0; //定義時、分、秒變量 uchar Choice=0; //調整時間選擇變量 bit Twinkle; //閃爍標志 /************************************** 定時器0初始化程序 100微秒@12.000MHz **************************************/ /* void Timer0Init() //100微秒@12.000MHz { TMOD = 0x02; //設置自動重載模式 TL0 = 0x9C; //設置定時初值 TH0 = 0x9C; //設置定時重載值 TF0 = 0; //清除TF0標志 TR0 = 1; //定時器0開始計時 } */ /*************************************** 定時器0初始化程序 100微秒@11.0592MHz ***************************************/ void Timer0Init() //100微秒@11.0592MHz { TMOD = 0x02; //設置自動重載模式 TL0 = 0xA4; //設置定時初值 TH0 = 0xA4; //設置定時重載值 TF0 = 0; //清除TF0標志 TR0 = 1; //定時器0開始計時 } /************************* 按鍵掃描程序 *************************/ void key_scan() { static bit key1_sign; //按鍵自鎖標志變量 static uint count1,count2,count3=0;//消抖計數變量 if(!K1) //檢測按鍵1按下 { count1++; //消抖計數1自+1 if((count1>=key_S)&&(key1_sign==0))//檢測消抖計數與按鍵1自鎖標志 { key1_sign=1; //按鍵1自鎖標志置1 Choice++; //調整選擇變量自+1 if(Choice>=4) //調整時間選擇0正常走時,1調時,2調分,3調秒 { Choice=0; //調整時間選擇清0 TF0=0; //定時器溢出標志TF0清0 Cnt100us=0; //時間變量Cnt100us自+1 } } } else { key1_sign=0; //按鍵1自鎖標志清0 count1=0; //消抖計數count1清0 } if(!K2) { count2++; if(count2>=key_L) //長按快調 { if(Choice==1) //選擇變量1調時 { hour++; if(hour>=24) hour=0; } if(Choice==2) //選擇變量2調分 { min++; if(min>=60) min=0; } if(Choice==3) //選擇變量3調秒 { sec++; if(sec>=60) sec=0; } count2=key_M; } } else //按鍵抬起 { if(count2>key_S && count2<key_L)//短按 { if(Choice==1) //選擇變量1調時 { hour++; if(hour>=24) hour=0; } if(Choice==2) //選擇變量2調分 { min++; if(min>=60) min=0; } if(Choice==3) //選擇變量3調秒 { sec++; if(sec>=60) sec=0; } } count2=0; //count2清0 } if(!K3) { count3++; if(count3>=key_L) //長按 { if(Choice==1) //選擇變量 { hour--; if(hour>=24) hour=23; } if(Choice==2) //選擇變量 { min--; if(min>=60) min=59; } if(Choice==3) //選擇變量 { sec--; if(sec>=60) sec=59; } count3=key_M; } } else //按鍵抬起 { if(count3>key_S && count3<key_L)//短按 { if(Choice==1) //選擇變量 { hour--; if(hour>=24) hour=23; } if(Choice==2) //選擇變量 { min--; if(min>=60) min=59; } if(Choice==3) //選擇變量 { sec--; if(sec>=60) sec=59; } } count3=0; //count3清0 } } /************************************ 計時子程序 ************************************/ void Time() { if(TF0==1) //如果查詢定時器溢出標志TF0為1 { //定時器溢出周期100us TF0=0; //定時器溢出標志TF0清0 Cnt100us++; //時間變量Cnt100us自+1 if((Cnt100us>2500 && Cnt100us<5000)||(Cnt100us>7500 && Cnt100us<10000))//閃爍頻率2Hz Twinkle=1; //閃爍標志 else Twinkle=0; if(Cnt100us>=9982) //在此可以按萬分之一秒調整精度 { Cnt100us=0; //變量Cnt100us清0 if(Choice!=3) //調整選擇變量為3停止走秒 sec++; //秒自+1 if(sec>=60) //如果秒>=60 { sec=0; //秒清0 min++; //分自+1 if(min>=60) //分>=60 { min=0; //分清0 hour++; //小時自+1 if(hour>=24) //小時>=24 hour=0; //小時清0 } } } } } /******************************** 數碼管顯示程序 ********************************/ void display() { static uchar num=0; //分時顯示變量 static uchar num1=0; //計數延時變量 num1++; if(num1>=30) //1~255可調,數碼管閃爍可減小,有鬼影可加大 { num1=0; switch(num) { case 0: P0=table[hour/10]; //時十位段碼 dula=1; dula=0; P0=0x7e; //時十位位碼 wela=1; wela=0; num++; break; case 1: if((Twinkle==1)&&(Choice==1))//時點閃爍 P0=table[hour%10]; else P0=table[hour%10]|0x80;//時個位段碼+點 dula=1; dula=0; P0=0x7d; //時個位位碼 wela=1; wela=0; num++; break; case 2: P0=table[min/10]; //分十位段碼 dula=1; dula=0; P0=0x7b; //分十位位碼 wela=1; wela=0; num++; break; case 3: if((Twinkle==1)&&(Choice==2))//分點閃爍 P0=table[min%10]; else P0=table[min%10]|0x80;//分個位段碼+點 dula=1; dula=0; P0=0x77; //分個位位碼 wela=1; wela=0; num++; break; case 4: P0=table[sec/10]; //秒十位段碼 dula=1; dula=0; P0=0xef; //秒十位位碼 wela=1; wela=0; num++; break; case 5: if((Twinkle==1)&&(Choice==3))//秒點閃爍+點 P0=table[sec%10]|0x80; else P0=table[sec%10];//秒個位段碼 dula=1; dula=0; P0=0xdf; //秒個位位碼 wela=1; wela=0; num=0; break; } } } /******************************** 主程序 ********************************/ void main(void) { Timer0Init(); //初始化定時器 while(1) { key_scan(); //按鍵掃描 Time(); //計時 display(); //顯示 } } |