从单片机基础到程序框架(全集 2019pdf版).pdf - 第425页
if(Su16Key Cnt1>=KEY _FILTER_TIME ) { Su8KeyLock 1=1; vGu8Single KeySec=1; / /触发 K1 的单 击键 } } //K2 按键的单击 if(0!=KEY_ INPUT2) { Su8KeyLock 2=0; Su16KeyCnt 2=0; } else if(0= =Su8KeyLo ck2) { Su16KeyCnt 2++; if(Su16Key Cn…

* IO 口突然瞬间触发成高电平,这个时候马上把延时计数器 Su16CombinationKeyTimeCnt
* 清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。
* 第三步:如果两个按键按下的时间超过了阀值 KEY_FILTER_TIME,马上把自锁标志 Su8CombinationKeyLock
* 置 1,防止按住两个按键不松手后一直触发。并把按键编号 vGu8CombinationKeySec 赋值,
* 触发一次组合按键。
* 第四步:等其中一个按键松开后,自锁标志 Su8CombinationKeyLock 及时清零,为下一次自锁做准备。
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock1;
static unsigned int Su16KeyCnt1;
static unsigned char Su8KeyLock2;
static unsigned int Su16KeyCnt2;
static unsigned char Su8CombinationKeyLock; //组合按键的自锁
static unsigned int Su16CombinationKeyCnt; //组合按键的计时器
//K1 按键与 K2 按键的组合触发
if(0!=KEY_INPUT1||0!=KEY_INPUT2)//两个按键只要有一个按键没有按下,处于“非组合按键”的状态。
{
Su8CombinationKeyLock=0; //组合按键解锁
Su16CombinationKeyCnt=0; //组合按键去抖动延时计数器清零,此行非常巧妙,是全场的亮点。
}
else if(0==Su8CombinationKeyLock)//两个按键被同时按下,且是第一次被按下。此行请看专题分析。
{
Su16CombinationKeyCnt++; //累加定时中断次数
if(Su16CombinationKeyCnt>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME。
{
Su8CombinationKeyLock=1; //组合按键的自锁,避免一直触发
vGu8CombinationKeySec=1; //触发 K1 与 K2 的组合键操作
}
}
//K1 按键的单击
if(0!=KEY_INPUT1)
{
Su8KeyLock1=0;
Su16KeyCnt1=0;
}
else if(0==Su8KeyLock1)
{
Su16KeyCnt1++;

if(Su16KeyCnt1>=KEY_FILTER_TIME)
{
Su8KeyLock1=1;
vGu8SingleKeySec=1; //触发 K1 的单击键
}
}
//K2 按键的单击
if(0!=KEY_INPUT2)
{
Su8KeyLock2=0;
Su16KeyCnt2=0;
}
else if(0==Su8KeyLock2)
{
Su16KeyCnt2++;
if(Su16KeyCnt2>=KEY_FILTER_TIME)
{
Su8KeyLock2=1;
vGu8SingleKeySec=2; //触发 K2 的单击键
}
}
}
void CombinationKeyTask(void) //组合按键任务函数,放在主函数内
{
if(0==vGu8CombinationKeySec)
{
return; //按键的触发序号是 0 意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
}
switch(vGu8CombinationKeySec) //根据不同的按键触发序号执行对应的代码
{
case 1: //K1 与 K2 的组合按键任务
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=KEY_VOICE_TIME; //触发一次组合按键后,发出“嘀”一声
vGu8BeepTimerFlag=1;
vGu8CombinationKeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触发
break;
}
}

void SingleKeyTask(void) //单击按键任务函数,放在主函数内
{
if(0==vGu8SingleKeySec)
{
return; //按键的触发序号是 0 意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
}
switch(vGu8SingleKeySec) //根据不同的按键触发序号执行对应的代码
{
case 1: //K1 单击任务
LedOpen(); //LED 亮
vGu8SingleKeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触发
break;
case 2: //K2 单击任务
LedClose(); //LED 灭
vGu8SingleKeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触发
break;
}
}
【94.2 专题分析:else if(0==Su8CombinationKeyLock)。】
疑问:
if(0!=KEY_INPUT1||0!=KEY_INPUT2)
{
Su8CombinationKeyLock=0;
Su16CombinationKeyCnt=0;
}
else if(0==Su8CombinationKeyLock)//两个按键被同时按下,且是第一次被按下。为什么?
{
Su16CombinationKeyCnt++;
if(Su16CombinationKeyCnt>=KEY_FILTER_TIME)
{
Su8CombinationKeyLock=1;
vGu8CombinationKeySec=1;
}
}