单键控制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中断标志赋值
- }
复制代码 |