按键长按短按
长按是在短按的基础上,以一个很短的时间(10ms)再次判断按键是否片于按下状态,当达到一定的时间(1s)后,按键还处于按下状态,说明是长按状态,结合上一节的短按,下面实现一个从0-99的累加,短按时一次加1,长按后,进入快速累加的过程,同时使用了定时器来定时刷新数码管,在Display的处理上就和之前的不同,原来在Display里通过循环刷新每个数码管的显示,现在放到了定时器定时触发的事件里,设置定时时间为2ms,这2ms只负责刷新共阴极的8位数码的一位,所以需要在定时事件里处理每次刷新不同位置的数码管。
#include <reg52.h> sbit KeyAdd = P0^0; sbit LED = P0^1; sbit LATCH1=P2^2;//段锁存 sbit LATCH2=P2^3;//位锁存 unsigned char code DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9 unsigned char code WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位码 unsigned char TempData[8]; //存储显示值 unsigned char vT = 0; void Delay(unsigned int t); void Display(unsigned char Index); void InitTime0(void); void main(void) { unsigned char numadd = 0; // 累加的结果 unsigned int vExtend = 0; // 用于判断是否满足长按标准 LED = 0; TempData[0] = DuanMa[0]; TempData[1] = DuanMa[0]; InitTime0(); while (1) { if (!KeyAdd) // 发现按下 { Delay(1500); // 延时去抖 if (!KeyAdd) // 如果还处于按下 { while (!KeyAdd) //等待弹起 { Delay(100); // 延时,这里要短一点,vExtend长些,这样有利于精确的判断是否放开 vExtend++; // 长按计数 if (vExtend == 1000) // 按下时间大约1s认为长按 { vExtend = 0; //清空计数初值 while(!KeyAdd) // 如果按键还处于按下状态,则快速增加 { if (numadd == 99) numadd = 0; else numadd++; TempData[0] = DuanMa[numadd / 10]; TempData[1] = DuanMa[numadd % 10]; Delay(10000); //延时让数字显示一段时间,否则数字不动直到放开按钮后突然跳变 } } } vExtend = 0; //设置初值,为下一次长按做准备 if (numadd == 99) numadd = 0; else numadd++; TempData[0] = DuanMa[numadd / 10]; TempData[1] = DuanMa[numadd % 10]; } } } } void Delay(unsigned int t) { while (--t); } void Display(unsigned char Index) { P1 = 0; //清空数据,防止有交替重影 LATCH1 = 1; //段锁存 LATCH1 = 0; P1 = WeiMa[Index]; //取位码 LATCH2=1; //位锁存 LATCH2=0; P1 = TempData[Index]; //取显示数据,段码 LATCH1=1; //段锁存 LATCH1=0; } void InitTime0(void) { TMOD = 0x01; TH0 = 0xF8; // 计数初值F830H = 2000 (65536-63536=2000 * 1us = 2ms) TL0 = 0x30; ET0 = 1; // EA即IE^1 等于1时申请中断定时器0中断打开 EA = 1; // 总中断打开 TR0 = 1; // 启动定时器0 } void MyInterrept(void) interrupt 1 { LED = !LED; TH0 = 0xF8; //重新赋值 2ms TL0 = 0x30; Display(vT); vT++; if (vT == 8) vT = 0; }