从单片机基础到程序框架(全集 2019pdf版) - 第461页
case 3: if(1==RO W_INPUT1&&1 ==ROW_INPU T2&&1==ROW_ INPUT3) { Su8KeySt ep++; //如果 没有按键按下 ,切换到下一 个运行 步骤 Su8KeyLo ck=0; //按键 自锁标志清零 Su16KeyC nt=0; //按键 去抖动延时计 数器清零 ,此行非常 巧妙 } else i f(0==Su8KeyL ock) //有按 键…

void main()
{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
KeyTask(); //按键的任务函数
}
}
/* 注释一:
* 矩阵按键扫描的详细过程:
* 先输出某 1 列低电平,其它 2 列输出高电平,延时等待 2ms 后(等此 3 列输出同步稳定),
* 再分别判断 3 行的输入 IO 口, 如果发现哪一行是低电平,就说明对应的某个按键被触发。
* 依次循环切换输出的 3 种状态,并且分别判断输入的 3 行,就可以检测完 9 个按键。矩阵按键的
* 去抖动处理方法跟我前面讲的独立按键去抖动方法是一样的,不再重复多讲。
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock=0;
static unsigned int Su16KeyCnt=0;
static unsigned char Su8KeyStep=1;
switch(Su8KeyStep)
{
case 1: //按键扫描输出第一列低电平
COLUMN_OUTPUT1=0;
COLUMN_OUTPUT2=1;
COLUMN_OUTPUT3=1;
Su16KeyCnt=0; //延时计数器清零
Su8KeyStep++; //切换到下一个运行步骤
break;
case 2: //延时等待 2ms 后(等此 3 列输出同步稳定)。不是按键的去抖动延时。
Su16KeyCnt++;
if(Su16KeyCnt>=2)
{
Su16KeyCnt=0;
Su8KeyStep++; //切换到下一个运行步骤
}
break;

case 3:
if(1==ROW_INPUT1&&1==ROW_INPUT2&&1==ROW_INPUT3)
{
Su8KeyStep++; //如果没有按键按下,切换到下一个运行步骤
Su8KeyLock=0; //按键自锁标志清零
Su16KeyCnt=0; //按键去抖动延时计数器清零,此行非常巧妙
}
else if(0==Su8KeyLock) //有按键按下,且是第一次触发
{
if(0==ROW_INPUT1&&1==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su16KeyCnt=0;
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
vGu8KeySec=1; //触发 1 号键 对应 S1 键
}
}
else if(1==ROW_INPUT1&&0==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su16KeyCnt=0;
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
vGu8KeySec=2; //触发 2 号键 对应 S2 键
}
}
else if(1==ROW_INPUT1&&1==ROW_INPUT2&&0==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su16KeyCnt=0;
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
vGu8KeySec=3; //触发 3 号键 对应 S3 键
}
}
}
break;

case 4: //按键扫描输出第二列低电平
COLUMN_OUTPUT1=1;
COLUMN_OUTPUT2=0;
COLUMN_OUTPUT3=1;
Su16KeyCnt=0; //延时计数器清零
Su8KeyStep++; //切换到下一个运行步骤
break;
case 5: //延时等待 2ms 后(等此 3 列输出同步稳定)。不是按键的去抖动延时。
Su16KeyCnt++;
if(Su16KeyCnt>=2)
{
Su16KeyCnt=0;
Su8KeyStep++; //切换到下一个运行步骤
}
break;
case 6:
if(1==ROW_INPUT1&&1==ROW_INPUT2&&1==ROW_INPUT3)
{
Su8KeyStep++; //如果没有按键按下,切换到下一个运行步骤
Su8KeyLock=0; //按键自锁标志清零
Su16KeyCnt=0; //按键去抖动延时计数器清零,此行非常巧妙
}
else if(0==Su8KeyLock) //有按键按下,且是第一次触发
{
if(0==ROW_INPUT1&&1==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su16KeyCnt=0;
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
vGu8KeySec=4; //触发 4 号键 对应 S4 键
}
}
else if(1==ROW_INPUT1&&0==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su16KeyCnt=0;