物协寒假培训Day12—键盘-创新互联

一、认识开发板上的键盘

开发板上的键盘主要分为独立键盘和矩阵键盘两种,通过J5跳线帽切换这两种键盘。开发板上面分别标有KBD和BTN,其中KBD就是key board,键盘的意思(矩阵键盘),BTN表示button,独立按键,知道了这个我们就能很好的记忆。下面为开发板的实物图:

创新互联公司专注于企业成都全网营销、网站重做改版、河池网站定制设计、自适应品牌网站建设、HTML5商城网站建设、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为河池等各大城市提供网站开发制作服务。 1.独立键盘

当J5跳线帽接2,3的时候为独立键盘,接1,2的时候为矩阵键盘。下图为独立键盘的示意图:

此处的S4,S5,S6,S7四个按键组成了独立键盘,当我们按下S4时,P33与GND接通,此时单片机的P33口读取到的电压为0,那么其它三个端口的电压为多少呢?我们看下面的图片:

我们现在使用的STC15F2K60S2系列的P3口默认都为准双向口,通过上面的图片可以看到,如果端口引脚没有输入的时候,其输入数据会被上拉电阻强行置为高电平。再看最后一句,准双向口读取外部状态前,要先锁存为"1"才可读到外部正确的状态,我们使用的15系列单片机在上电的时候就会把引脚置为高电平,已经默认锁存为1,可以直接读取外部状态。

2.矩阵键盘

当J5跳线帽接1,2的时候,此部分就会由独立键盘变为矩阵键盘。

对于按键状态的识别,我们常用的方法有两种:线翻转法和行扫描法。

下面是官方书籍中的介绍(采用行扫描法)
矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,列线通过电阻接正电源,并将行线所接的单片机的 I/O 口作为输出端,而列线所接的 I/O 口则作为输入端。这样,当按键没有按下时,所有的输入端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。 矩阵键盘中按键的识别有行扫描和线翻转两种方法,其中 行扫描法是一种最常用的按键识别方法,过程如下:
(1)逐行输出 0,检查列线是否非全高;
(2)如果某行输出 0 时,查到列线非全高,则该行有按键按下;
(3)根据输出 0 的行线和读入 0 的列线,即可判断按下按键的位置。
行扫描法的工作原理

P30,P31,P32,P33作为单片机输入引脚,P34,P35,P42,P44作为单片机的输出引脚。当开始工作时,我们把单片机四个输出引脚分别置0,然后在输入引脚处读取数值从而判断到底是哪个按键被按下。

举个栗子:我们假设S9按键被按下。首先,我们将单片机的P44引脚置0,由于S4~S7未有按键按下,因此单片机由于上拉电阻的作用,在输入端读取的数值都为1。然后我们把P44重新置为1,把P42置为0,由于S9被按下,此线路导通,因此P32引脚被置为0,其它为1,由此我们可以得知S9按键被按下了,往后以此类推。

代码原理分析
unsigned int Key_New; //16位无符号整数

P44 = 0; P42 = 1; P35 = 1; P34 = 1; // 第 1 列
//此时若有按键按下,则P30~P33对应的引脚置零
Key_New = P3 & 0x0f; //只保留末四位的数据

P44 = 1; P42 = 0; // 第 2 列 切换扫描的行
Key_New = (Key_New<< 4) | (P3 & 0x0f); //先把先前的数据往高四位移动,然后保留末四位数据

P42 = 1; P35 = 0; // 第 3 列
Key_New = (Key_New<< 4) | (P3 & 0x0f); 

P35 = 1; P34 = 0; // 第 4 列
Key_New = (Key_New<< 4) | (P3 & 0x0f);

以上为代码的工作原理,按照4位一组,最终的结果为0x0400,对应S9按键被按下。

二、代码编写 1.独立键盘
#include "key.h"

unsigned char Key_Read_BTN(void){
    unsigned char Key_Value;
    
    if(P30 == 0) Key_Value = 7;
    else if(P31 == 0) Key_Value = 6;
    else if(P32 == 0) Key_Value = 5;
    else if(P33 == 0) Key_Value = 4;
    else Key_Value = 0;
    
    return Key_Value;
}
2. 矩阵键盘

😋此处代码的switch()里面非常有规律。

// 运行程序时,将 J5 调整为 KBD 模式(1、2 脚短接)
#include "key.h"

unsigned char Key_Read(void){
    unsigned int  Key_New;
    unsigned char Key_Val;

    P44 = 0; P42 = 1; P35 = 1; P34 = 1;
    Key_New = P3;
    P44 = 1; P42 = 0;					
    Key_New = (Key_New<< 4) | (P3 & 0x0f);
    P42 = 1; P35 = 0;					
    Key_New = (Key_New<< 4) | (P3 & 0x0f);
	P35 = 1; P34 = 0;				
    Key_New = (Key_New<< 4) | (P3 & 0x0f);

    switch(~Key_New) {
        
        case 0x8000: Key_Val = 4; break;	// S4
        case 0x4000: Key_Val = 5; break;	// S5
        case 0x2000: Key_Val = 6; break;	// S6
        case 0x1000: Key_Val = 7; break;	// S7
        
        case 0x0800: Key_Val = 8; break;	// S8
        case 0x0400: Key_Val = 9; break;	// S9
        case 0x0200: Key_Val = 10; break;	// S10
        case 0x0100: Key_Val = 11; break;	// S11
        
        case 0x0080: Key_Val = 12; break;	// S12
        case 0x0040: Key_Val = 13; break;	// S13
        case 0x0020: Key_Val = 14; break;	// S14
        case 0x0010: Key_Val = 15; break;	// S15
        
        case 0x0008: Key_Val = 16; break;	// S16
        case 0x0004: Key_Val = 17; break;	// S17
        case 0x0002: Key_Val = 18; break;	// S18
        case 0x0001: Key_Val = 19; break;	// S19
        default: Key_Val = 0;
    }
    return Key_Val;
}
三、按键消抖

(纯手画,比例不是很对,按下和松手的抖动时间<10ms,稳定期>数百ms)

1.按键抖动原理

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

2.按键消抖的方法 1)普通软件延时

软件延时和松手检测都会占用CPU资源(delay)

while(1) {
    if(key==0) {
	Delay10ms();
	    if(key==0) {
              //按键按下执行相关功能代码                   
                while(!key);
	    }
    }
}
2)标志位软件延时

通过引入按下标志位,省去了while(!KEY)的松手检测,将按下时稳定期的数百ms释放出来,只占用了按下和松手时的共20ms的消抖时间。

3)标志位定时器延时

使用定时器进行延时消抖,使用标志位代替松手检测(不会对主函数进行明显干扰)

4)状态机

算法成熟但代码量大(设置三种状态)

5)三行代码(位运算)
unsigned char Key_Value,Key_Down,Key_Old;//定义全局变量

Key_Value = Key_Read(); //读取10ms更新一次的I/O电平状态,并储存于变量Key_Value
Key_Down = Key_Value & (Key_Old ^ Key_Value);   //按下为按键值,其它为0
Key_Old = Key_Value;//把读取到的临时按键值Key_Value更新到Key_Old中,作为下一次旧的按键值

假设S4被按下了:

Key_Old

Key_Value

对应的按键过程

Key_Old ^ Key_Value

Key_Down

0

0

未按下

0

0

0

4

按下过程中

4

4

4

4

按下稳定期间

0

0

4

0

抬起过程中

4

0

拓展:Key_Up = ~Key_Value & (Key_Old ^ Key_Value);

Key_Old

Key_Value

对应的按键过程

Key_Old ^ Key_Value

Key_Up

0

4

未按下

0

0

0

0

按下过程中

4

0

4

0

按下稳定期间

0

0

4

4

抬起过程中

4

4

长按:if(Key_Old == 4 {(......)}
双击:设置一个标志位,每次加一

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻标题:物协寒假培训Day12—键盘-创新互联
本文URL:http://scyanting.com/article/ccshco.html