按键介绍
按键种类繁多,功能有简有繁,极大的充斥着我们的生活。但是无论如何,所有的按键其实都有一个原型,来源于同一种原理,所有的按键无论多复杂,多华丽,都是从这样一个原型发展而成的。好比你就算长的再帅,你也是只猩猩变来的,呵呵。我们平日所见到的绝大部分的按键,其实都可以归类为一种,叫“接触式按键”。下图为一个典型的接触式按键(又称轻触开关)。
需要特别说明的是,这里说的“接触”,是指机械层面上的接触,而不是感光或者某些特殊涂层(比如触摸屏)一类的接触。所以,按键的工作特性其实是一种机械特性,下文会详细说明。
如上图,请对照图一想象,1、2、3、4 分别对应按键的四个引脚,其中蓝色的线表示按键未被按下之时的状态,我成为初始状态,它是不导通的;而绿色的线是却永久导通的。各位明白了么,其实是两个相同的结构连在一起了。我们只要将需要按键开关作用的线路分别接在1、3 和2、4 的任意取一组合,概括起来就是(1,2)、(1,4)、(3,2)、(3,4)四种组合,都可以起到我们预期的开关作用。
相信以上说明使大家对按键的工作原理有了个比较清晰的认识了,现在来说说一个小知识。先看下图(图4):
首先说明的是,上图的连法是不允许的,因为当按键按下之后,电源和地短接,会将导线直接烧毁。但是此处用作特例,假设导线不会烧毁。现在来提出一个问题,当按键按下以后,请问如果这时用万用表测量导线上任何一处的电压,得到的结果是VCC 还是GND 的电压?
答案是:GND,即表示测出的电压为0V。为什么呢,因为导线上,对于两端的电平是一种类似于程序语言逻辑运算里面的“与”,即对于导线两端:有零即为零,只有全为一是才为一。理解了这点,按键的工作前提就有了。
键盘分为编码键盘和非编码键盘。键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。而靠软件编程来识别的键盘称为非编码键盘,在单片机组成的各种系统中,用的较多的是非编码键盘。非编码键盘又分为独立键盘和行列式键盘(常说的矩阵键盘)。在这一讲中我们介绍一下单片机中键盘使用。
单片机的IO口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能,我们把按键的一端接地,另一端与单片机的某个I/O口相连,开始时先给该IO口赋一高电平,然后让单片机不断地检测该I/O口是杏变为低电平,当按键闭合时,即相当于该I/O口通过按键与地相连,变成低电平,程序一旦检测到I/O口变为低电平则说明按键被按下,然后执行相应的指令。
我们先来说一下,按键常常遇到的问题—抖动问题。
还以图4为例,按键未按下之前,图4按键左端的导线因为连在VCC 上而显示高电平,右端显示低电平,按键按下后,按键闭合,整个导线都显示低电平,然后按键松开,又回到按键按下之前的电平状态。如果只考察按键左端的电平变化,应该是上图中所显示的一个负脉冲波形。但是,实际上,正确的波形应该是下图。相比于上图,大家都看到了在高低电平直接有一段锯齿一样的波形,这就是所谓的按键抖动。
为什么会有按键抖动呢,原因很简单,接触式按键是靠机械的接触来实现开关作用的。这种接触方式就注定了它要经历一个“接触不稳定——正在稳定中——彻底稳定”的一种过程。就好比你用手抓紧一颗石头,即使你一开始就很用力的握紧,也不可能马上就达到最紧的状态,也要经历一个从握住到最紧握的过程。那么在这个过程里,接触式按键就处于一种徘徊在“闭合”与“断开”两者之间的状态。体现在电路中,就是在一小段时间内有非常多的“按下——抬起”动作。而这段抖动的时间,大概是10~20 毫秒,依不同的环境条件而定。
解决这个问题常见的方法有软件去抖动和硬件去抖动。
我们解释一下抖动:关于按键去抖动的解释,我们在手动按键的时候,由于机械抖动或是其它一些非人为的因素很有可能会造成误识别,一般手动按下一次键然后接着释放,按键两片金属膜接触的时间大约为50ms 左右,在按下瞬间到稳定的时间为5-10ms,在松开的瞬间到稳定的时间也为5-10ms,如果我们再首次检测到键被按下后延时10ms 左右再去检测,这时如果是干扰信号将不会被检测到,如果确实是有键被按下,则可确认,以上为按键识别去抖动的原理。
独立键盘
开发板独立按键电路图如下:
独立按键一共8个,有对应的插槽可以连接在单片机的任意IO口。去抖动的方式,我们采用软件延时的方法。过程如下:
先设置IO口为高电平(一般上电默认就为高)
读取IO口电平确认是否有按键按下
如有IO电平为低电平后,延时几个ms
再读取该IO电平,如果任然为低电平,说明对应按键按下
执行相应按键的程序
独立键盘程序示例:
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit led = P0^0; //设置灯的控制IO口
sbit k1 = P1^0; //设置按键的控制IO口
void delay(u16 i) //延时函数
{
while(i--);
}
void keyprocess()
{
if(k1 == 0) //判断按键是否按下
{
delay(1000); //延时消抖
if(k1 == 0) //再次判断按键是否按下
{
led = 1; //如果按键按下,则灯亮
}
else
{
led = 0; //如果按键没有按下,则灯灭
}
}
}
void main()
{
led = 0; //初始灯灭
while(1)
{
keyprocess(); //处理按键事件
}
}