从单片机基础到程序框架(全集 2019pdf版).pdf - 第410页
Su16KeyCnt 1++; //累加 定时中断次数 if(Su16Key Cnt1>=KEY _FILTER_TIME ) //滤波的“稳定 时间”K EY_FILT ER_TIME,长度 是 25ms。 { Su8KeyLock 1=1; //按键的 自锁,避免一直触 发 vGu8KeySec =1; //触发 1 号键 } } //2 号按键 if(0!=KEY_ INPUT2) { Su8KeyLock 2=0; Su1…

}
else
{
vGu16BeepTimerCnt--;
if(0==vGu16BeepTimerCnt)
{
Su8Lock=0;
BeepClose();
}
}
}
}
/* 注释一:
* 独立按键扫描的详细过程,以按键 K1 为例,如下:
* 第一步:平时没有按键被触发时,按键的自锁标志,去抖动延时计数器一直被清零。
* 第二步:一旦有按键被按下,去抖动延时计数器开始在定时中断函数里累加,在还没累加到
* 阀值 KEY_FILTER_TIME 时,如果在这期间由于受外界干扰或者按键抖动,而使
* IO 口突然瞬间触发成高电平,这个时候马上把延时计数器 Su16KeyCnt1 清零了,这个过程
* 非常巧妙,非常有效地去除瞬间的杂波干扰。以后凡是用到开关感应器的时候,
* 都可以用类似这样的方法去干扰。
* 第三步:如果按键按下的时间达到阀值 KEY_FILTER_TIME 时,则触发按键,把编号 vGu8KeySec 赋值。
* 同时,马上把自锁标志 Su8KeyLock1 置 1,防止按住按键不松手后一直触发。
* 第四步:等按键松开后,自锁标志 Su8KeyLock1 及时清零(解锁),为下一次自锁做准备。
* 第五步:以上整个过程,就是识别按键 IO 口下降沿触发的过程。
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock1; //1 号按键的自锁
static unsigned int Su16KeyCnt1; //1 号按键的计时器
static unsigned char Su8KeyLock2; //2 号按键的自锁
static unsigned int Su16KeyCnt2; //2 号按键的计时器
//1 号按键
if(0!=KEY_INPUT1)//IO 是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
Su8KeyLock1=0; //按键解锁
Su16KeyCnt1=0; //按键去抖动延时计数器清零,此行非常巧妙,是全场的亮点。
}
else if(0==Su8KeyLock1)//有按键按下,且是第一次被按下。这行很多初学者有疑问,请看专题分析。
{

Su16KeyCnt1++; //累加定时中断次数
if(Su16KeyCnt1>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME,长度是 25ms。
{
Su8KeyLock1=1; //按键的自锁,避免一直触发
vGu8KeySec=1; //触发 1 号键
}
}
//2 号按键
if(0!=KEY_INPUT2)
{
Su8KeyLock2=0;
Su16KeyCnt2=0;
}
else if(0==Su8KeyLock2)
{
Su16KeyCnt2++;
if(Su16KeyCnt2>=KEY_FILTER_TIME)
{
Su8KeyLock2=1;
vGu8KeySec=2; //触发 2 号键
}
}
}
void KeyTask(void) //按键任务函数,放在主函数内
{
if(0==vGu8KeySec)
{
return; //按键的触发序号是 0 意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
}
switch(vGu8KeySec) //根据不同的按键触发序号执行对应的代码
{
case 1: //1 号按键
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=KEY_VOICE_TIME; //触发按键后,发出固定长度的声音
vGu8BeepTimerFlag=1;
vGu8KeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触发
break;

case 2: //2 号按键
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=KEY_VOICE_TIME; //触发按键后,发出固定长度的声音
vGu8BeepTimerFlag=1;
vGu8KeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一直触发
break;
}
}
【92.2 专题分析:else if(0==Su8KeyLock1)。】
疑问:
if(0!=KEY_INPUT1)
{
Su8KeyLock1=0;
Su16KeyCnt1=0;
}
else if(0==Su8KeyLock1)//有按键按下,且是第一次被按下。为什么?为什么?为什么?
{
Su16KeyCnt1++;
if(Su16KeyCnt1>KEY_FILTER_TIME)
{
Su8KeyLock1=1;
vGu8KeySec=1;
}
}
解答:
首先,我们要明白 C 语言的语法中,
if(条件 1)
{
}
else if(条件 2)
{
}
以上语句是一对组合语句,不能分开来看。当(条件 1)成立的时候,它是绝对不会判断(条件 2)的。
当(条件 1)不成立的时候,才会判断(条件 2)。
回到刚才的问题,当程序执行到(条件 2) else if(0==Su8KeyLock1)的时候,就已经默认了(条件 1)
if(0!=KEY_INPUT1)不成立,这个条件不成立,就意味着 0==KEY_INPUT1,也就是有按键被按下,因此,这里
的 else if(0==Su8KeyLock1)等效于 else if(0==Su8KeyLock1&&0==KEY_INPUT1),而 Su8KeyLock1 是一个自