| 先看看成功案例吧! |
|
这是数码管时钟程序,其中的按键程序可以满足你的需要: //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(); //显示 } } |