键盘扫描法

  cheney

    键盘扫描是嵌入式开发的入门玩意,几乎人人都要写一个这样的程序,或许不是为了使用,只是熟悉IO口操作的一种方法。看似普遍又普通,殊不知这人人都会的键盘扫描法,也是大有可研究的地方。一般的研究方向有:1.怎样高速稳定识别;2.怎样少用IO口;3.怎样识别多个键。

    ##1. 最简单的扫描法

    REST键

    其实这个都不能称为是扫描,最简单的键盘只要每个IO口对应一个键,使用软件检对应IO的电平变化就能知道该键是否按下。硬件上可以增加一个小电容去抖动,软件上也可以去抖动。 这种方法适用于键较少,特别是单个独立的按键,如,复位键。缺点很明显,如果键很多,那就太占IO口了。

    ##2. 行、列、反转扫描法

    有很多情况下,在组成单片机系统的过程中,由于通用的I/O口有限,而又需要大量的按键输入,这就要求一种新的键盘结构,即用尽量少的I/O口实现尽可能多的键盘输入。根据扫描方法的不同,可以分为行扫描法、列扫描法和反转法三种。

    矩阵键盘

    行列扫描顾名思义就是逐行逐列的把按键扫描出来,如上图,P1.0、P1.1、P1.2、P1.3为列,P1.4、P1.5、P1.6、P1.7为行,先把P1.0置高,其他列置低,然后检测每行的电平,如果有被拉高的,那么该行该列交叉的地方就是按键的地方。如果没有接着设置第二列,以此类推。

    程序可以直接检测行所组成的编码,也可以类似这样写:

    	uchar scan(void)
    	{
    	       uchar scan_byte = 0xf;          //稍有不同 不过类似
    	       uchar i;
    	       uchar kv = 0;
    	       P2 = scan_byte;
    	       COL9 = 1;
    	       for (i = 0; i < 4; i++)
    	          {
    	                if (!ROW1)
    	                 {
    	                        return kv;
    	                 }
    	                 ++kv;
    	                 if (!ROW2)
    	                 {
    	                       return kv;
    	                 }
    	
    	                 ++kv;
    	
    	                 if (!ROW3)
    	                 {
    	                        return kv;
    	                 }
    	
    	                 ++kv;
    	
    	                 if (!ROW4)
    	                 {
    	                        return kv;
    	                 }
    	                 ++kv;
    	
    	     scan_byte =_crol_(scan_byte,1);
    	
    	     P2 = scan_byte;
    	
    	    }
    	
    	    return 0;
    	
    	}
    

    这样每个键都返回一个固定的编码器,用软件的方法定义每个编码的含义就可以了。

    反转扫描法原理也很简单,直接把所有的列全部置高,然后检测行被拉高的,确定按键的行。然后把行全部置高,检测列被置高的,确定按键的列。这样就能确定这个键了。

    ##3. 识别多个键

    为了识别多个按键或组合键,需要硬件上一些支持。

    多按键

    比如增加一些二极管,行列扫描法(反转的不行)就可以,设置正确的软件,可以识别任意多个键。

    ##4.异型的键盘扫描法

    为了特别节约IO口而设计的扫描键盘电路,配合软件可以可以识别的按键数量让你膛目结舌!

    按键举例

    上图为这种设计的基本单元(右边的LED为了显示按键状态,可以忽略),理解这个就能理解整个设计。仅用一个IO口,识别两个按键。软件上,需要先把IO口配置为高电平输出,然后上拉输入,检测电平是否为低,如果为低,说明S2按下,否则S2断开;同理,IO口配置为低电平,然后切换为下拉输入,如果为高,说明S1按下,否则S1断开。

    以此类推,我们得出:

    两个IO口识别8个键

    • 两个IO口识别8个键。

    三个IO口识别23个键

    • 三个IO口识别23个键。

    任何收获都有代价的,虽然可以识别这么多键,但软件无疑极大地复杂化了,而且速度也做不到很快。

    软件的设计对按键识别有很大的影响,建议看看某位前辈写的《新型的按键扫描程序》,百度可以搜到,或许有些启示。