控制/MCU
单片机检测按键原理
首先说一下独立键盘检测,在单片机外围电路中 ,通常用到的按键都是机械弹性开关,当开关闭合时,线路导通,开关断开时,线路断开。单片机检测按键的原理:按键的一端接地,另一端与单片机的某个I/O口相连,开始先给I/O赋一高电平,然后让单片机不断检测该I/O口是否变为低电平,当按键闭合时,相当于I/O口与地相连,就会变为低电平。在单片机检测按键是否被按下时,电压的实际波形与理想波形时有一点=定差别的,波形在按下和释放瞬间都有抖动现象,抖动时间的长短和按键的机械特性有关 。所以单片机在检测键盘是否被按下都要加上去抖操作,所以在编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时。独立键盘与单片机连接时每一个按键都需要一个I/O口,会过多占用I/O口资源。所以就引出了矩阵键盘。
矩阵键盘的连接方式,每一行将每个按键的一端连接在一起构成行线,每一列将按键的另一端连接在一起构成列线。这样的话,16个按键排成4行4列就只要8根线。它的按键检测,简单点说,就是先送一列低电平,其余均为高电平,然后轮流检测,确认行列。
这里就要提到另外一个东西,switch-case语句又称开关语句,它是一个专门用于处理多分支结构的条件选择语句。使用switch语句可直接处理多个分支。
按键检测是初学单片机的同学玩的前几个例程,按键的种类有许多(普通按钮,矩阵键盘等等),按键检测的方法也有许多。对于普通按钮当然你会说设计一个外围电路通过GPIO口读一下还不简单,或许你说通过外部中断做边沿检测,对于矩阵键盘来说,往往你会通过行列分别扫描的方法做按键检测,通常我们会加一个按键防抖(经典的方法是通过延时二次确认的方法进行按键防抖,还有就是按键释放的时候你可能会通过while语句去防抖,也就是按键如果一直按下,让程序一直死在while里),这些都是初学者常用的方法,但是如果是一个大的程序,往往是不允许你有这么多延时和死循环的。
中断是一个经常使用的按键检测方法,中断之间的时间就可以作为防抖的处理,而且这种方法适用于程序融合,因为其他传感器的数据读取通常也是通过中断的手段去做的(如摄像头)。我这里给出一个问题和一个解决办法。
问题:设计一个按键检测程序(多按键),通过中断去读取,要求只有在按键更新的时候才会在主程序里做出响应,否则不理睬,要求设计防抖动,只有两次检测为真时,才进行键值的更新,真值表如下。
IN_old_stable为旧的确定值。
IN_new_stable为新的确定值。
IN_old为上次读取的按键值。
IN_new为最新读取的按键值。
当然每次中断后都需要做一次迭代:
IN_old=IN_new;
IN_old_stable=IN_new_stable;
只有新的确定值是我们值得信赖的。
由真值表的计算规则:
IN_new_stable: D
IN_old_stable: A
IN_old: B
IN_new: C
有:
所以有:
解决:我以STM32F103为例,需要读取GPIO,B口的低四位。
我们首先在中断里最如下处理:
IN_old=IN_new;
IN_old_stable=IN_new_stable; //前面两行先做迭代。
IN_new=(GPIO_ReadInputData(GPIOB))&0x00001111;//读取GPIOB的低四位。
IN_temp=(IN_old^IN_new)&IN_old_stable; //中间变量
IN_temp|=IN_old&IN_new;
IN_new_stable=IN_temp;这就得到了我们最新的键值,它是由过去旧的确定值,按键前后两次的值所决定的,所以您看,是不是至少得经历三次中断才能把一个键值更新。
好了,到了这里我们把按键的值检测出来了,我们还有一步,如何告知主函数有没有键值更新呢。
我们分析一下可以知道:如果我们比较IN_new_stable和IN_old_stable两次确定值是不是就知道了
定义temp=IN_new_stable^IN_old_stable;如果低四位上有键值更新,则IN_new_stable和IN_old_stable前后两次确定值是不是就不一样了,通过异或计算就反映在了相应的位上。
好了我们假设低四位在硬件设计时是拉高的,我们初始化一个中间变量sthchange=0x00001111;
我们把sthchange和temp进行异或就知道哪一位被置低了。
sthchange^=temp.
则把sthchange给主程序判断就行了,当没有键值更新的时候sthchange=0,有键值更新的时候sthchange》1,通过位运算不就知道哪个键值发生改变了。
全部0条评论
快来发表一下你的评论吧 !