从单片机基础到程序框架(全集 2019pdf版).pdf - 第482页
} break; case 3: if(1==RO W_INPUT1&&1 ==ROW_INPU T2&&1==ROW_ INPUT3) { Su8KeySt ep=1; //如果 没有按键按下 ,返回到第一 个运行 步骤重新开始 扫描!!!!! ! Su8KeyLo ck=0; //按键 自锁标志清零 Su16KeyC nt=0; //按键 去抖动延时计 数器清零,此 行非常 巧妙 if(Su8KeyT…

*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock=0;
static unsigned int Su16KeyCnt=0;
static unsigned char Su8KeyStep=1;
static unsigned char Su8ColumnRecord=0; //用来切换当前列的输出
static unsigned char Su8KeyTouchCnt1; //S1 按键的次数记录
static unsigned int Su16KeyIntervalCnt1; //S1 按键的间隔时间计数器
switch(Su8KeyStep)
{
case 1:
if(0==Su8ColumnRecord) //按键扫描输出第一列低电平
{
COLUMN_OUTPUT1=0;
COLUMN_OUTPUT2=1;
COLUMN_OUTPUT3=1;
}
else if(1==Su8ColumnRecord) //按键扫描输出第二列低电平
{
COLUMN_OUTPUT1=1;
COLUMN_OUTPUT2=0;
COLUMN_OUTPUT3=1;
}
else //按键扫描输出第三列低电平
{
COLUMN_OUTPUT1=1;
COLUMN_OUTPUT2=1;
COLUMN_OUTPUT3=0;
}
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=1; //如果没有按键按下,返回到第一个运行步骤重新开始扫描!!!!!!
Su8KeyLock=0; //按键自锁标志清零
Su16KeyCnt=0; //按键去抖动延时计数器清零,此行非常巧妙
if(Su8KeyTouchCnt1>=1) //之前已经有按键触发过一次,启动间隔时间的计数器
{
Su16KeyIntervalCnt1++; //按键间隔的时间计数器累加
if(Su16KeyIntervalCnt1>=KEY_INTERVAL_TIME) //达到最大允许的间隔时间,溢出无效
{
Su16KeyIntervalCnt1=0; //时间计数器清零
Su8KeyTouchCnt1=0; //清零按键的按下的次数,因为间隔时间溢出无效
}
}
Su8ColumnRecord++; //输出下一列
if(Su8ColumnRecord>=3)
{
Su8ColumnRecord=0; //依次输出完第 3 列之后,继续从第 1 列开始输出低电平
}
}
else if(0==Su8KeyLock) //有按键按下,且是第一次触发
{
if(0==ROW_INPUT1&&1==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
if(0==Su8ColumnRecord) //第 1 列输出低电平
{
Su16KeyIntervalCnt1=0; //按键有效间隔的时间计数器清零
Su8KeyTouchCnt1++; //记录当前单击的次数
if(1==Su8KeyTouchCnt1) //只按了 1 次
{
vGu8SingleKeySec=1; //单击任务,触发 1 号键 对应 S1 键
}
else if(Su8KeyTouchCnt1>=2) //连续按了两次以上

{
Su8KeyTouchCnt1=0; //统计按键次数清零
vGu8SingleKeySec=1; //单击任务,触发 1 号键 对应 S1 键
vGu8DoubleKeySec=1; //双击任务,触发 1 号键 对应 S1 键
}
}
else if(1==Su8ColumnRecord) //第 2 列输出低电平
{
vGu8SingleKeySec=2; //触发 2 号键 对应 S2 键
}
else if(2==Su8ColumnRecord) //第 3 列输出低电平
{
vGu8SingleKeySec=3; //触发 3 号键 对应 S3 键
}
}
}
else if(1==ROW_INPUT1&&0==ROW_INPUT2&&1==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零
if(0==Su8ColumnRecord) //第 1 列输出低电平
{
vGu8SingleKeySec=4; //触发 4 号键 对应 S4 键
}
else if(1==Su8ColumnRecord) //第 2 列输出低电平
{
vGu8SingleKeySec=5; //触发 5 号键 对应 S5 键
}
else if(2==Su8ColumnRecord) //第 3 列输出低电平
{
vGu8SingleKeySec=6; //触发 6 号键 对应 S6 键
}
}
}
else if(1==ROW_INPUT1&&1==ROW_INPUT2&&0==ROW_INPUT3)
{
Su16KeyCnt++; //去抖动延时计数器
if(Su16KeyCnt>=KEY_SHORT_TIME)
{
Su8KeyLock=1;//自锁置 1,避免一直触发,只有松开按键,此标志位才会被清零