今天分享的是GPIO输入——按键检测。
按键检测部分还是比较简单的,与51单片机类似,采用扫描的方法,循环地判断哪个按键按下,然后执行相应的操作。
流程图大致如下:
这里有两种扫描方式,一种是单次扫描,一种是连续扫描。这两种扫描方式的区别在于,单次扫描的状态下,按住按键不放不会有什么影响,而连续扫描状态下,按住按键不放会持续产生作用。举个例子,家里的遥控器调节音量时,如果一直按住不放,音量越来越大,就是连续扫描,如果一直按住不放和按一次的效果一样,那么就属于单次扫描。
具体是如何实现的呢?首先定义一个静态变量flag,初始值为1,只有当flag==1且有按键按下时,才会进入到相应的处理程序中(返回值),同时,改变flag的值令其等于0。当第二次扫描的时候,如果mode=0(单次扫描),那么flag的值因为保持原来为0,所以不会进入按键处理函数中,而是走向右边第二次判断语句,假设已经松手了,那么也就是此时没有按键按下,flag=1,这为下次的按键检测做好准备,而如果没有松手,程序执行右边部分,flag的值没有改变依然为0,下次扫描依然进入不了按键处理函数。而如果mode=1(连续扫描),那么flag的值会改为1,这样只要有按键按下,就能进入到左边的按键处理函数当中,虽然flag在里面又置为了0,但是由于mode=1,可以重新让flag=1,因此,可以起到连续扫描的效果。
实现程序:
代码语言:javascript复制u8 KEY_Scan(u8 mode)
{
static flag=1;
if(mode=1)
flag=1;
if(flag==1&&(KEY_UP==1||KEY_DOWN==0||KEY_LEFT==0||KEY_RIGHT==0))
{
delay_ms(10);
flag=0;
if(KEY_UP==1)
return K_UP ;
if(KEY_DOWN==0)
return K_DOWN;
if(KEY_LEFT==0)
return K_LEFT;
if(KEY_RIGHT==0)
return K_RIGHT;
}
else if(~(KEY_UP==1||KEY_DOWN==0||KEY_LEFT==0||KEY_RIGHT==0))
flag=1;
return 0;
}
有朋友可能会有疑问,就是每次进入这个按键扫描函数的时候,flag不是被初始化了为1吗?那么这就涉及到关键字static 了,具体用法可以参考:
https://blog.csdn.net/guotianqing/article/details/79828100
总结:按键检测就是获取IO口的状态,通过对各个按键的IO口不断进行扫描,获取是哪个按键按下并且返回值,根据返回值的不同执行相应的处理函数。获取IO口状态的方法可以使用位带操作,也可以直接调用库函数。扫描方式有单次扫描和连续扫描,其实也就是有选择性地进入按键处理函数。