51单片机 --独立按键

前言

前几章介绍的都是IO 口输出的使用,这一教程我们通过独立按键实验来介绍IO 口作为输入的使用。开发板上板载8 个独立按键。本教程所要实现的功能是:通过开发板上的独立按键K1 控制D1 指示灯亮灭。大家可以参考前面的实验内容。


一、按键介绍

按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。开发板上使用的按键及内部简易图如下图所示:

51单片机 --独立按键_第1张图片

按键管脚两端距离长的表示默认是导通状态,距离短的默认是断开状态, 如果按键按下,初始导通状态变为断开,初始断开状态变为导通。

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号如下图所示:

51单片机 --独立按键_第2张图片

由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为5ms 到10ms。按键稳定闭合时间的长短则由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起按键被误读多次。为了确保CPU 对按键的一次闭合仅作一次处理,必须进行消抖。

按键消抖有两种方式,一种是硬件消抖,另一种是软件消抖。为了使电路更加简单,通常采用软件消抖。我们开发板也是采用软件消抖,一般来说一个简单的按键消抖就是先读取按键的状态,如果得到按键按下之后,延时10ms,再次读取按键的状态,如果按键还是按下状态,那么说明按键已经按下。其中延时10ms 就是软件消抖处理,至于硬件消抖,大家可以百度了解下,网上都有非常详细的介绍。这里给大家列出单片机常用的软件去抖动方法:

1,先设置IO 口为高电平(由于开发板IO 都有上拉电阻,所以默认IO 为高电平)。

2,读取IO 口电平确认是否有按键按下。

3,如有IO 电平为低电平后,延时几个毫秒。

4,再读取该IO 电平,如果仍然为低电平,说明按键按下。

5,执行按键控制程序。

独立按键电路构成是由各个按键的一个管脚连接在一起接地,按键其他引脚

分别接到单片机IO 口。我们知道单片机的IO 口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能,独立按键的一端接地, 另一端与单片机的I/O 口相连,开始时先给该IO 口赋一高电平,然后让单片机不断地检测该I/O 口是否变为低电平,当按键闭合时,即相当于该I/O 口通过按键与地相连,变成低电平,程序一旦检测到I/O 口变为低电平则说明按键被按下,然后执行相应的指令。

二、硬件设计

本实验使用到硬件资源如下:

(1)LED 模块中D1 指示灯

(2)K1 按键

LED 模块电路在前面章节都介绍过,这里就不多说,开发板上的独立按键模块电路如下图所示:

51单片机 --独立按键_第3张图片

从上图中可以看出,该电路是独立的,8 个独立按键的控制管脚并未直接连接到51 单片机的IO 上,而是连接到JP1 端子上。如果要想51 单片机能够检测按键是否按下,就必须将单片机管脚通过导线连接到JP1 端子上。因此需使用一根8Pin 排线将单片机的管脚与JP1 端子顺序连接。由于独立按键模块电路是独立的,所以使用任意单片机管脚都可以,为了与我们例程程序配套,这里使用P3.1 口来检测K1 按键,使用P2.0 管脚控制D1指示灯。

三、软件设计

本教程所要实现的功能是:通过开发板上的独立按键K1 控制D1 指示灯亮灭。

​​​​​​​

#includetypedef unsigned int u16;typedef unsigned char u8;sbit KEY1=P3^1;sbit KEY2=P3^2;sbit KEY3=P3^3;sbit KEY4=P3^4;sbit LED1=P2^0;#define KEY1_PRESS 1#define KEY2_PRESS 2#define KEY3_PRESS 3#define KEY4_PRESS 4#define KEY1_UNPRESS 0
void delay_10us(u16 time_us)//延时函数{    while(time_us--);}
u8 key_scan(u8 mode){    static u8 key=1;    if(mode==1)    {        key=1;//连续扫描按键    }    if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下    {        delay_10us(1000);//消抖        key=0;             if(KEY1==0)            return KEY1_PRESS;        else if(KEY2==0)            return KEY2_PRESS;        else if(KEY3==0)            return KEY3_PRESS;        else if(KEY4==0)            return KEY4_PRESS;    }else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)//无按键按下    {        key=1;        return KEY1_UNPRESS;    }}
void main(){    u8 key=0;    while(1)    {        key=key_scan(0);            if(key==KEY1_PRESS)//检测按键K1是否按下        {            LED1=!LED1;//LED1状态翻转          }    }}

key_scan 函数带一个形参mode,该参数用来设定是否连续扫描按键,如果mode 为0,只能操作一次按键,只有当按键松开后才能触发下次的扫描,这样做的好处是可以防止按下一次出现多次触发的情况。如果mode 为1,函数是支持连续扫描的,即使按键未松开,在函数内部有if(mode==1)这条判断语句,因此key 始终是等于1 的,所以可以连续扫描按键,当按下某个按键,会一直返回这个按键的键值,这样做的好处是可以很方便实现连按操作。函数内的delay_10us(1000)即为软件消抖处理,通常延时10ms 即可。

key_scan 函数还带有一个返回值,如果未有按键按下,返回值即KEY_UNPRESS,否则返回值即为对应按键的键值,如KEY1_PRESS、KEY2_PRESS、KEY3_PRESS、KEY4_PRESS,这都是程序开头定义好的宏,方便大家理解和使用。函数内定义了一个static 变量key,相当于全局变量,所以该函数不是一个可重入函数。还有一点要注意的就是该函数按键的扫描是有优先级的,因为函数内用了if...else if...else 格式,所以最先扫描处理的按键是KEY1,其次是KEY2,然后是KEY3,最后是KEY4。如果需要将其优先级设置一样,那么可以全部用if 语句。

main 函数中主要就是调用key_scan 函数用于检测按键,此时传入的mode值为0,表示单次扫描按键,然后将扫描按键的值保存在变量key 中,最后通过if 判断语句控制LED1 状态。


你可能感兴趣的:(单片机,嵌入式硬件,独立按键)