51单片机外设之——独立按键的检测(传统法一)

我刚开始学的单片机的时候,一直会热枕于一个操作——就是希望我自己能按一下键盘,让单片机去执行我想要的操作命令。但是就是被这种热枕所向往,以至于我一直没有去想它是怎么一个工作环境(一开始居然忘记联想到 C 语言的 if 条件语句!)。所以这里我以自身经历去奉劝大家,我们在憧憬于一件事的时候,不要忘记去力所能及的实现它!
接下来,我将分批次的把我对“按键”的理解记行分享。其中,按键的存在形式主要有两种:独立按键、矩阵按键。对于按键的扫描(用于让单片机知道我们是按下哪一个按键)主要与三种方法:传统的按键识别、带有标志位的按键识别、快速识别。
在此,我把传统的按键检测分为:延时消抖检测、外部中断检测。
这里,我首先来介绍延时消抖检测。

按键的原理图(我们先只看独立按键):
51单片机外设之——独立按键的检测(传统法一)_第1张图片
这里 J5 是一个排针, 用跳帽连接 J5 的2脚与3脚即可将键盘设置为独立按键(只有S4~S7有效)。此时,S4~S7一端分别与P3^3~P3^0相连,另一端连向GND。这样,我们先给P3^0~P3^3赋高电平(其实单片机上电时, I/O 口默认输出高电平。但是为了严谨,在扫描之前还是先用软件实现赋高电平)即可通过检测P3^0~P3^3处的电平是否出现低电平的状态,去查看哪个按键是否被按下。(当有按键按下时,则此按键连接的P3引脚的 I/O 口会从高电平变为低电平的状态)

再附上按键按下时,接触点实际的电压变化:
51单片机外设之——独立按键的检测(传统法一)_第2张图片
我上面所说,只要检测 I/O 口电压的变化,即可判断按键是否被按下,对于理想情况是可以检测准确的。但是从图所示,可以看到对于实际的波形,存在着按下时按键抖动以及松手时的按键抖动,这都会产生上上下下的不定向的电压值。所以不能完全只通过检测 I/O 口判断。
对于按下抖动,根据前人所给出的经验值,其时间一般不会超过10ms;过于释放抖动的过程,我们可以用while语句进行检测,检测按键是否松开,也是就是 I/O 口否恢复为高电平(因为程序在按键扫描之前,就将 I/O 口的值赋为高电平,虽然它被按键通过 GND 拉低到低电平状态,但是只要按键松开, I/O 口仍会变化原来的高电平状态)。

实例为:通过每按一次按键,使得数码管第一位的显示值每次加 1 ,满十则从零开始重新计数。
核心代码如下(其中,数码管显示函数以及段码的定义等,都引用上节的数码管博文):

sbit s4 = P3^3;                    //单独使用一个 I/O 口,则需要使用 sbit 进行位定义
void main()
{
    while(1)
    {
        if(s4 == 0)                //检测是否有键按下
        {
            delay10ms();           //经过10ms的延时函数进行消抖
            if(s4 == 0)            //若P3^3仍然为低电平,则确实有键(s4)按下
            {
                dspbuf[0]++;       //第一位数码管的段码值 +1
                while(!s4);        //等待按键松开,等价于while(s4 == 0)
            }   
        }
        display();                 //数码管显示函数
    }
}

其实在这里可以看到,当按键一直处于按下之后,程序会卡死在 while(!s4) 处。在这个时候,由于没有调用display()函数,数码管是不能显示的。解决方法有:
1、改变按键的扫描方式;
2、将display()函数放入中断,不停进行数码管显示。
怎么改变按键的扫描方式呢?什么又是中断?

未完待续……

你可能感兴趣的:(51单片机)