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

} } } /* 注释一: * “电脑键盘式 ”组合按键扫 描的详细过 程: * 第一步:K2 与 K1 构成的组合按键触 发是融 合在 K1 单击按键程 序里的,只需 稍微更改一下 K1 单击的程序 * ,就可以兼容到 K2 与 K 1 构成的“电脑键 盘式”组合 按键。平时只 要 K1 没有被按下 时,按 * 键的自锁标志 Su8Ke yLock1 和去抖动延 时计数器 S u16KeyCnt 1 一直被清零。 * 第二步:一 旦 …

100%1 / 836
}
void BeepOpen(void)
{
P3_4=0;
}
void BeepClose(void)
{
P3_4=1;
}
void LedOpen(void)
{
P1_4=0;
}
void LedClose(void)
{
P1_4=1;
}
void VoiceScan(void)
{
static unsigned char Su8Lock=0;
if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0)
{
if(0==Su8Lock)
{
Su8Lock=1;
BeepOpen();
}
else
{
vGu16BeepTimerCnt--;
if(0==vGu16BeepTimerCnt)
{
Su8Lock=0;
BeepClose();
}
}
}
}
/* 注释一:
* “电脑键盘式”组合按键扫描的详细过程:
* 第一步:K2 K1 构成的组合按键触发是融合在 K1 单击按键程序里的,只需稍微更改一下 K1 单击的程序
* ,就可以兼容到 K2 K1 构成的“电脑键盘式”组合按键。平时只 K1 没有被按下时,按
* 键的自锁标志 Su8KeyLock1 和去抖动延时计数器 Su16KeyCnt1 一直被清零。
* 第二步:一 K1 按键被按下,去抖动延时计数器 Su16KeyCnt1 开始在定时中断函数里累加,在还没
* 累加到阀值 KEY_FILTER_TIME 时,如果在这期间由于受外界干扰或者按键抖动,而使
* IO 口突然瞬间触发成高电平,这个时候马上把延时计数 Su16KeyCnt1 清零了,
* 这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。
* 第三步:如 K1 按键按下的时间超过了阀 KEY_FILTER_TIME,马上把自锁标志 Su8KeyLock1 1,
* 防止按住按键不松手后一直触发,此时才开始判断一次 K2 按键的电平状态,如果 K2 为低电
* 平就认为是组合按键,并给按键编号 vGu8CombinationKeySec 赋值,否则,就认为是 K1 的单击
* 按键,并给按键编号 vGu8SingleKeySec 赋值
* 第四步:等 K1 按键松开后,自锁标志 Su8KeyLock1 及时清零,为下一次自锁做准备
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock1;
static unsigned int Su16KeyCnt1;
//K1 的单击,或 K2 K1 构成的“电脑键盘式组合按键”
if(0!=KEY_INPUT1)//单个 K1 键没有按下,及时清零一些标志。
{
Su8KeyLock1=0; //按键解锁
Su16KeyCnt1=0; //去抖动延时计数器清零,此行非常巧妙,是全场的亮点
}
else if(0==Su8KeyLock1)//单个按键 K1 被按下
{
Su16KeyCnt1++; //累加定时中断次数
if(Su16KeyCnt1>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME。
{
if(0==KEY_INPUT2) //此时才开始判断一 K2 的电平状态,为低电平则是组合按键。
{
Su8KeyLock1=1;
vGu8CombinationKeySec=1; //组合按键的触发
}
else
{
Su8KeyLock1=1;
vGu8SingleKeySec=1; //K1 单击按键的触发
}
}
}
}
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 击任务
if(0==Gu8LedStatus)
{
Gu8LedStatus=1;
LedOpen(); //LED
}
else