从单片机基础到程序框架(全集 2019pdf版).pdf - 第428页
第九十五节: 两个独立按键的“电脑键盘式”组合按键。 【95.1 “电脑键盘式”组合按键。 】 上图 95.1.1 独立 按键电路 上图 95.1.2 L ED 电路 上图 95.1.3 有源 蜂鸣器电路 上一节也讲 了由 K1 和 K2 构成 的组合按键, 但是这种组合 按键是 普通的组合按 键,因为它们 的 K1 和 K2 是不 分先后 顺序 的, 你先按 住 K1 然 后再 按 K2, 或者 你先按 住 K2 然后再 按 K1, …

解答:
首先,我们要明白 C 语言的语法中,
if(条件 1)
{
}
else if(条件 2)
{
}
以上语句是一对组合语句,不能分开来看。当(条件 1)成立的时候,它是绝对不会判断(条件 2)的。
当(条件 1)不成立的时候,才会判断(条件 2)。
回到刚才的问题,当程序执行到(条件 2) else if(0==Su8CombinationKeyLock)的时候,就已经默认
了(条件 1) if(0!=KEY_INPUT1||0!=KEY_INPUT2)不成立,这个条件不成立,就意味着 0==KEY_INPUT1 和
0==KEY_INPUT2,也就是有两个按键被同时按下,因此,这里的 else if(0==Su8CombinationKeyLock)等效于
else if(0==Su8CombinationKeyLock&&0==KEY_INPUT1&&0==KEY_INPUT2),而 Su8CombinationKeyLock 是一
个自锁标志位,一旦组合按键被触发后,这个标志位会变 1,防止两个按键按住不松手的时候不断触发组合
按键。这样,组合按键只能同时按下一次触发一次,任意松开其中一个按键后再同时按下一次两个按键,又
触发一次新的组合按键。

第九十五节: 两个独立按键的“电脑键盘式”组合按键。
【95.1 “电脑键盘式”组合按键。】
上图 95.1.1 独立按键电路
上图 95.1.2 LED 电路
上图 95.1.3 有源蜂鸣器电路
上一节也讲了由 K1 和 K2 构成的组合按键,但是这种组合按键是普通的组合按键,因为它们的 K1 和 K2
是不分先后顺序的,你先按住 K1 然后再按 K2,或者你先按住 K2 然后再按 K1,效果都一样。本节讲的组合

按键是分先后顺序的,比如,像电脑的复制快捷键(Ctrl+C),你必须先按住 Ctrl 再按住 C 此时“复制快捷
键”才有效,如果你先按住 C 再按住 Ctrl 此时“复制快捷键”无效。本节讲的例程就是要实现这个功能,
用 K1 代表 C 这类“字符数字键”,用 K2 代表 Ctrl 这类“辅助按键”,因此,要触发组合键(K2+K1),必须
先按住 K2 再按 K1 才有效。本节讲的例程功能如下:(1)K1 每单击一次,LED 要么从“灭”变成“亮”,要
么从“亮”变成“灭”,在两种状态之间切换。(2)如果先按住 K2 再按 K1,就认为构造了“电脑键盘式”组
合键,蜂鸣器发出“嘀”的一声。代码如下:
#include "REG52.H"
#define KEY_VOICE_TIME 50 //组合按键触发后发出的声音长度 50ms
#define KEY_FILTER_TIME 25 //按键滤波的“稳定时间”25ms
void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
void BeepOpen(void);
void BeepClose(void);
void LedOpen(void);
void LedClose(void);
void VoiceScan(void);
void KeyScan(void); //按键识别的驱动函数,放在定时中断里
void SingleKeyTask(void); //单击按键任务函数,放在主函数内
void CombinationKeyTask(void); //组合按键任务函数,放在主函数内
sbit P3_4=P3^4; //蜂鸣器
sbit P1_4=P1^4; //LED
sbit KEY_INPUT1=P2^2; //K1 按键识别的输入口。
sbit KEY_INPUT2=P2^1; //K2 按键识别的输入口。
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus=0; //记录 LED 灯的状态,0 代表灭,1 代表亮
volatile unsigned char vGu8SingleKeySec=0; //单击按键的触发序号
volatile unsigned char vGu8CombinationKeySec=0; //组合按键的触发序号
void main()
{
SystemInitial();