今天敲了按键检测的一个进阶方案 --用定时器来辅助检测按键是否被按下
其中一个核心思想就是每隔20ms检测一次按键的状态 然后直接对比按键的状态是否改变 对改变的逻辑进行处理就可以得到
1.哪个按键被按下了
2.是按下的瞬间还是抬手的瞬间
用硬件的方法来对按键的状态进行检测 可以做到不会让程序一直卡在长时间的Delay中
每二十毫秒只会检测一次按键的状态
在这个检测函数组中有三个函数 二号哦是用于检测和标记按键状态的 把按键状态转换为一个临时键码值 临时键码值到后面的逻辑判断函数中有用到
临时键码值在三号函数中被拆分成现在的状态(Now)和上一个状态(Last)
如果现在的状态是0 而上一个状态是x(x是非0的整数) 则表示第x号按键被按下了(抬手瞬间)
如果现在状态是x上一个状态是0则表明x被按下了(按下瞬间)
如果现在状态和上一个状态都是0则表示没有按键按下 可以根据这三条来做逻辑判断 实现想要的功能
在三号函数中 需要调用二号函数 二号函数会在进入函数的时候对返回值清零 所以如果没有按键按下 40ms后 现在状态和上一个状态就都会被清零(二号函数和三号函数形成一个闭环 刚好做到不hi有遗漏的情况出现)
在三号函数中 经过逻辑判断后改变全局变量的值 再后面将全局变量的值在一号函数中使用 从一号函数中返回到主函数中调用获取键码函数 这里需要有一个中间值返回 还需要顺便将全局变量给清零 保证不影响下一次的逻辑判断(若不清零 可能会造成上一个状态是x这一个状态是0 导致误判断)
还有一个需要注意的点就是 在对现在状态和上一个状态进行判断的时候 这个变量是使用关键字static定义为静态局部变量的 不会随着三号函数的结束而被清除 达到可以联动多个函数的效果
大概差不多了
接下来上代码:
按键检测部分函数:
include <STC15F2K60S2.H>
sbit ROW1=P3^0;
sbit ROW2=P3^1;
sbit ROW3=P3^2;
sbit ROW4=P3^3;
//写一个按键检测函数 一个按键检测调用函数 还有一个返回值函数
unsigned char KeyNumber=0;
/**
- @brief 按键键码返回及初始化函数
- @param 无
- @retval 返回按键键码
*/
unsigned char KeyInit()
{
unsigned char Temp=0;
Temp = KeyNumber;
KeyNumber=0;//将按键变量KeyNumber初始化并返回Temp的值
return Temp;
}
/**
- @brief 按键键码检测函数
- @param 无
- @retval 检测到某个瞬间的按键键码值(判断键码值)
*/
unsigned char KeyNumber_Find()
{
unsigned char KEYN=0;
P34=1;
P42=1;
P35=1;
if(ROW10){KEYN=7;}//直接检测哪个按键被按下
if(ROW20){KEYN=6;}//作为一个判断键码值到后级程序做判断
if(ROW30){KEYN=5;}
if(ROW40){KEYN=4;}
return KEYN;
}
/**
- @brief 按键逻辑判断函数
- @param 无
- @retval 无
*/
void KeyLoop()
{ //这个函数用来检测松手瞬间
static unsigned char Nowstate,Laststate;
//如果上一个状态是7 现在的状态是0 则是按键7的松手瞬间
Laststate=Nowstate;
Nowstate=KeyNumber_Find();
//因为在这里调用了KeyNumber_Find函数 所以Nowstate会变化 0或者是有效键码
//由于KeyLoop被每隔20ms执行一次 所以KeyNumber_Find也是每隔20ms执行一次
//如果没有按键按下 20ms以后Nowstate就会被清0 再过个几毫秒Laststate也会被清零
if(Laststate0&&Nowstate7){KeyNumber=7;}//判断按键按下 按下执行
if(Laststate6&&Nowstate0){KeyNumber=6;}//判断按键被按下 抬手执行
if(Laststate5&&Nowstate0){KeyNumber=5;}
if(Laststate4&&Nowstate0){KeyNumber=4;}
}
/*
三种状态:一直没有按键按下的状态 按下瞬间 抬手瞬间
如果一直没有按键按下 则Nowstate=0 Laststate=0 不满足逻辑判断的条件 则KeyNumber没有被赋值一直为0
按下瞬间情况:前一个状态是:0 现在的状态是x(x=7、6、5、4) 不满足逻辑判断 所以也没有把KeyNumber赋值
抬手瞬间:前一个状态是x(x=7、6、5、4)现在的状态是:0 满足逻辑判断 所以KeyNumber被赋值
*/
定时器定时扫描函数:
void Timer0_Routine() interrupt 1
{
Timer1++;
if(Timer1>20)
{
KeyLoop();
}
}
浙公网安备 33010602011771号