从单片机基础到程序框架(全集 2019pdf版).pdf - 第454页

} } } //K2 按键 if(0!=KEY_ INPUT2) { Su8KeyLock 2=0; Su16KeyCnt 2=0; Su16KeyCon tinuityCn t2=0; Su16KeyCon tinuityTi me2=KEY_CONT INUITY_IN ITIAL_TIME; } else if(0= =Su8KeyLo ck2) { Su16KeyCnt 2++; if(Su16Key Cnt2>=KEY …

100%1 / 836
static unsigned char Su8KeyLock2;
static unsigned int Su16KeyCnt2;
static unsigned int Su16KeyContinuityCnt2; //连击计数器
static unsigned int Su16KeyContinuityTime2=KEY_CONTINUITY_INITIAL_TIME; //动态时间阀值
//K1 按键
if(0!=KEY_INPUT1)//单个 K1 键没有按下,及时清零一些标志。
{
Su8KeyLock1=0; //按键解锁
Su16KeyCnt1=0; //去抖动延时计数器清零,此行非常巧妙,是全场的亮点
Su16KeyContinuityCnt1=0; //连击计数器
Su16KeyContinuityTime1=KEY_CONTINUITY_INITIAL_TIME; //动态时间阀值。重装初始值。
}
else if(0==Su8KeyLock1)//单个按键 K1 被按下
{
Su16KeyCnt1++; //累加定时中断次数,每一次累加额度是 1ms
if(Su16KeyCnt1>=KEY_SHORT_TIME) //按键的“滤波”时间 25ms
{
Su8KeyLock1=1; //“自锁”
vGu8KeySec=1; //触发一次 K1 按键
Su16KeyCnt1=0; //清零,为了下一步用来累加“从单击进入连击的间隔时间 300ms”
}
}
else if(Su16KeyCnt1<=KEY_ENTER_CONTINUITY_TIME)//按住不松手累加到 300ms
{
Su16KeyCnt1++; //累加定时中断次数,每一次累加额度是 1ms
}
else //按住累加到 300ms 后仍然不放手,这个时候进入有节奏的连续触发
{
Su16KeyContinuityCnt1++; //连击计数器开始累加,每一次累加额度 1ms
if(Su16KeyContinuityCnt1>=Su16KeyContinuityTime1) //按住没松手,每隔一会就触发一次
{
Su16KeyContinuityCnt1=0; //清零,为了继续连击。
vGu8KeySec=1; //触发一次 K1 按键
vGu8ShieldVoiceFlag=1; //把当前按键触发的声音屏蔽掉
if(Su16KeyContinuityTime1>=KEY_SUB_DT_TIME)
{
//此数值不断被减小,按键的触发速度就不断变快
Su16KeyContinuityTime1=Su16KeyContinuityTime1-KEY_SUB_DT_TIME;//变快节奏
}
if(Su16KeyContinuityTime1<KEY_CONTINUITY_MIN_TIME) //最小间隔时间就是“高速匀速”
{
Su16KeyContinuityTime1=KEY_CONTINUITY_MIN_TIME; //最后以此最高速进行“匀速
}
}
}
//K2 按键
if(0!=KEY_INPUT2)
{
Su8KeyLock2=0;
Su16KeyCnt2=0;
Su16KeyContinuityCnt2=0;
Su16KeyContinuityTime2=KEY_CONTINUITY_INITIAL_TIME;
}
else if(0==Su8KeyLock2)
{
Su16KeyCnt2++;
if(Su16KeyCnt2>=KEY_SHORT_TIME)
{
Su8KeyLock2=1;
vGu8KeySec=2; //触发一次 K2 按键
Su16KeyCnt2=0;
}
}
else if(Su16KeyCnt2<=KEY_ENTER_CONTINUITY_TIME)
{
Su16KeyCnt2++;
}
else
{
Su16KeyContinuityCnt2++;
if(Su16KeyContinuityCnt2>=Su16KeyContinuityTime2)
{
Su16KeyContinuityCnt2=0;
vGu8KeySec=2; //触发一次 K2 按键
vGu8ShieldVoiceFlag=1;
if(Su16KeyContinuityTime2>=KEY_SUB_DT_TIME)
{
Su16KeyContinuityTime2=Su16KeyContinuityTime2-KEY_SUB_DT_TIME;
}
if(Su16KeyContinuityTime2<KEY_CONTINUITY_MIN_TIME)
{
Su16KeyContinuityTime2=KEY_CONTINUITY_MIN_TIME;
}
}
}
}
void KeyTask(void) //按键任务函数,放在主函数内
{
if(0==vGu8KeySec)
{
return; //按键的触发序号是 0 意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
}
switch(vGu8KeySec) //根据不同的按键触发序号执行对应的代码
{
case 1: //K1 发的任务
if(Gu16SetData>0)
{
Gu16SetData--; //“设置参数”
Gu8DisplayUpdate=1; //刷新显示
}
if(0==vGu8ShieldVoiceFlag) //声音没有被屏蔽
{
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=KEY_VOICE_TIME; //发出“嘀”一声
vGu8BeepTimerFlag=1;
}
vGu8ShieldVoiceFlag=0; //及时把屏蔽标志清零,避免平时正常的单击声音也被淹没。
vGu8KeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触
break;
case 2: //K2 发的任务
if(Gu16SetData<800)
{
Gu16SetData++; //“设置参数”
Gu8DisplayUpdate=1; //刷新显示
}
if(0==vGu8ShieldVoiceFlag) //声音没有被屏蔽
{
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=KEY_VOICE_TIME; //发出“嘀”一声
vGu8BeepTimerFlag=1;