單鍵控制9分59秒倒計時
- #include <reg51.H>
- #include <intrins.H>
- #define uint unsigned int
- #define uchar unsigned char
- sbit bai=P3^0;
- sbit shi=P3^1;
- sbit ge=P3^2;
- sbit key=P3^6;
-
- //定義需要顯示的數字
- //反序共陰極數碼管段碼表,段碼a-h順序接PX7-PX0
- unsigned char code dis[]={//共陰數碼管段碼"0~f-."
- 0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,
- 0xFE,0xF6,0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,0x02,0x01};
- uchar data buf[3];
- char sec=0,sec_1=0,min=1,min_1=1; //秒、分
- uchar Key_value; //鍵值
- uchar set=0; //設置標志
- uint cnt=0,cnt1=0; //中斷計數
- uint count=0; //長/短按計數
- uint rst=0; //復位計數
- bit flag_ms=0; //1ms中斷標志
- bit flicker=0; //閃爍標志
- bit start=0; //開始標志
- bit On_Off=1; //開關標志
- void Timer0Init(void) //1毫秒@12.000MHz
- {
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0x18; //設置定時初始值
- TH0 = 0xFC; //設置定時初始值
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- EA = 1;
- ET0 = 1;
- }
- //數碼管顯示函數
- void display()
- {
- static uchar i;
- if(On_Off)
- {
- P1=0x00;
- if(set==0)
- {
- switch(i)
- {
- case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
- case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
- case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
- }
- }
- if(set==1)
- {
- switch(i)
- {
- case 0: bai=0;shi=1;ge=1;
- if(flicker)P1=dis[min]|0x01; else P1=0x01; break;
- case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
- case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
- }
- }
- if(set==2)
- {
- switch(i)
- {
- case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
- case 1: bai=1;shi=0;ge=1;
- if(flicker)P1=dis[sec/10];else P1=0x00; break;
- case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
- }
- }
- if(set==3)
- {
- switch(i)
- {
- case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
- case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
- case 2: bai=1;shi=1;ge=0;
- if(flicker)P1=dis[sec%10];else P1=0x00; break;
- }
- }
- }
- else
- {
- P1=0xff;
- bai=1;
- shi=1;
- ge=1;
- }
- i=++i%4;
- }
- //按鍵掃描
- void key_scan()
- {
- if(!key)
- {
- count++;
- if(count>1000) //長按時長
- count=1001;
- if(count==10) //大于10ms小于500ms算短按
- {
- Key_value=0x01;
- }
- if(count==1000) //達到1s算長按
- {
- Key_value|=0x10;
- }
- }
- else //按鍵松手
- {
- if(count>0)rst=5000;//復位計數賦值
- count=0;//長/短按計數清0
- }
- }
- //按鍵服務程序
- void key_service()
- {
- //短按等待松手后響應,長按達1s不論是否松手立即響應
- if((count==0||count==1000) && Key_value!=0x00)
- {
- switch(Key_value)
- {
- case 0x01://短按1任務
- if(On_Off==0 && !start && set==0)On_Off=1;//開機
- else if(On_Off && !start && set==0){min=min_1;sec=sec_1;start=1;}//啟動倒計時
- else if(On_Off && !start && set>0)//設置時間
- {
- switch(set)
- {
- case 1: min++; if(min>9)min=0; break;//設置分
- case 2: sec+=10;if(sec>=60)sec%=10; break;//設置秒十位
- case 3: sec++; if(sec%10==0)sec-=10; break;//設置秒個位
- }
- min_1=min;//緩存分
- sec_1=sec;//緩存秒
- }
- break;
- case 0x11:
- if(On_Off && !start)
- {
- if(++set==4)set=0;//操作設置狀態
- rst=5000;
- }
- break;
- }
- Key_value=0x00;//鍵值清0
- }
- }
- //復位/關機函數
- void reset()
- {
- if(rst>0)
- {
- rst--;
- if(rst==0)
- {
- if(count==0)//按鍵已松手
- set=0;//設置狀態復位
- else if(!start)//長按5秒不松手關機(倒計時運行中不可關機)
- {
- set=0;//設置狀態復位
- On_Off=0;//關機
- }
- }
- }
- }
- //主函數
- void main()
- {
- Timer0Init();
- while(1)
- {
- if(flag_ms)
- {
- flag_ms=0;//1ms標志清0
- display();//數碼管顯示函數
- key_scan();//按鍵掃描函數
- key_service();//按鍵服務函數
- reset();//復位/關機函數
- }
- }
- }
- //T0中斷服務函數
- void InterruptTimer0() interrupt 1
- {
- TL0 = 0x18; //設置定時初始值
- TH0 = 0xFC; //設置定時初始值
- if(start)
- {
- if(++cnt>=1000)//1s
- {
- cnt=0;
- sec--;
- if(sec==0 && min==0)//倒計時結束
- {
- start=0; //開始標志清0
- }
- else if(sec<0)
- {
- sec=59;
- min --;
- }
- }
- }
- if(++cnt1>=200) //200ms 5Hz閃爍,可以任意調整閃爍頻率
- {
- cnt1=0;
- flicker=~flicker; //閃爍標志取反
- }
- flag_ms=1;//1ms中斷標志賦值
- }
復制代碼 |