目录
引言
在前面,我们学习了矩阵键盘的单、双击(http://t.csdnimg.cn/S0fGu)和矩阵键盘的长、短按(http://t.csdnimg.cn/BAuZM),至此,应对蓝桥杯省赛的按键部分已是绰绰有余。此篇,我们来了解一下在蓝桥杯国赛中会出现矩阵键盘的双按键问题(国赛备赛中)。
一、原理图
-
按键排列成矩阵形式:按键按行列排列成矩阵,每个按键对应矩阵中的一个元素。例如,4x4 的矩阵可以支持最多 16 个按键。
-
行列扫描:按键矩阵通过单片机的 GPIO 引脚连接。在读取按键输入之前,单片机首先将矩阵的每一行(或每一列)依次设置为输出,而其他行(列)则设置为输入。然后,单片机逐行(或逐列)地扫描,检测是否有按键被按下。
-
按键状态检测:当某一行(或列)被设置为输出时,如果此行(或列)上有按键按下,那么对应的输入引脚将被拉低(或拉高),单片机可以通过读取输入引脚的状态来检测按键是否被按下。
-
消除冲突:由于按键矩阵的扫描方式,可能会出现多个按键同时被按下的情况,称为按键冲突。为了解决这个问题,通常采用软件或硬件的方式进行消抖和冲突解析。
-
按键编码:一旦检测到有按键被按下,单片机就可以根据按键所在的行列位置来编码按键的唯一标识,以便后续的处理和响应。
老规矩,开局还是先放原理图 。
二、定义图
(此图来源于B站小蜜蜂老师)
关于此图具体的理解请见我的作品 2.1矩阵键盘的单击、双击 http://t.csdnimg.cn/41Dd9
三、双按键
1.分析
双按键部分与长短按有异曲同工之处,都是通过小范围的延时后,判断后续是否还有对应的操作来确定的,因此并不难理解,不同的点在于:我们此处并不需要使用定时器。
2.示例
(1)按键选择
此处我们以S7和S6同时按下为例(该图为第十五届蓝桥杯赛点资料包原理图,具体引脚可以参照第一张图片)。
(2)定义引脚
#include <STC15F2K60S2.H> //引入头文件
sbit R1=P3^0; //第一行
sbit R2=P3^1; //第二行
sbit R3=P3^2; //第三行
sbit R4=P3^3; //第四行
sbit C1=P4^4; //第一列
sbit C2=P4^2; //第二列
sbit C3=P3^5; //第三列
sbit C4=P3^4; //第四列
此处定义了符号R1~R4来代表行,C1~C4代表列(具体含义见我作品: 2.1矩阵键盘的单击、双击 http://t.csdnimg.cn/41Dd9http://t.csdnimg.cn/41Dd9http://t.csdnimg.cn/41Dd9)。
(3)消抖延时函数
通常,我们采用延时检测,跳过其反馈不稳定部分的检测。
void Delay(unsigned int t) //通常延时100us即可
{
while(t--);
}
除了自己写的延时代码外,也可以引入头函数,利用软件来生成延时函数。
#include "intrins.h"
(此处不作具体展示)
(4)按键
void ScanKeys()
{
R1=R2=R3=R4=1; //将所有行输出设置为高电平
C1=0;C2=C3=C4=1; //将第一列输出设置为低电平,其他列设置为高电平
//此为S7先按下后的检测:
if(R1==0) //若检测到第一行输出低电平(即S7)
{
Delay(100); //延时消抖
if(R1==0 && R2==0) //若同时检测到第一、二行同时输出低电平
{
##双按键代码
while(R1==0 && R2==0);
}
else if(R1==0 && R2==1) //若S7按下但S6未按下
{
##单按键代码
while(R1==0);
}
}
//此为S6先按下后的检测:
if(R2==0) //若检测到第二行输出低电平(即S6)
{
Delay(100); //延时消抖
if(R2==0 && R1==0) //若同时检测到第二、一行同时输出低电平
{
##双按键代码
while(R2==0 && R1==0);
}
else if(R2==0 && R1==1) //若S6按下但S7未按下
{
##单按键代码
while(R2==0);
}
}
}
显然,分开来写过于冗杂,我们只需在判断第一个按键按下判断是略施小计,采用或判断即可:
void ScanKeys()
{
R1=R2=R3=R4=1; //将所有行输出设置为高电平
C1=0;C2=C3=C4=1; //将第一列输出设置为低电平,其他列设置为高电平
//此为S7先按下后的检测:
if(R1==0 || R2==0) //若检测到第一行或第二行输出低电平(即S7或S6)
{
Delay(100); //延时消抖
if(R1==0 && R2==0) //若同时检测到第一、二行同时输出低电平
{
##双按键代码
while(R1==0 && R2==0);
}
else if(R1==0 && R2==1) //若S7按下但S6未按下
{
##S7按下代码
while(R1==0);
}
else if(R2==0 && R1==1) //若S6按下但S7未按下
{
##S6按下代码
}
}
}
如此,双按键的部分就完成了。
四、代码纯享版
#include <STC15F2K60S2.H> //引入头文件
sbit R1=P3^0; //第一行
sbit R2=P3^1; //第二行
sbit R3=P3^2; //第三行
sbit R4=P3^3; //第四行
sbit C1=P4^4; //第一列
sbit C2=P4^2; //第二列
sbit C3=P3^5; //第三列
sbit C4=P3^4; //第四列
void Delay(unsigned int t) //通常延时100us即可
{
while(t--);
}
void ScanKeys()
{
R1=R2=R3=R4=1; //将所有行输出设置为高电平
C1=0;C2=C3=C4=1; //将第一列输出设置为低电平,其他列设置为高电平
//此为S7先按下后的检测:
if(R1==0 || R2==0) //若检测到第一行或第二行输出低电平(即S7或S6)
{
Delay(100); //延时消抖
if(R1==0 && R2==0) //若同时检测到第一、二行同时输出低电平
{
##双按键代码
while(R1==0 && R2==0);
}
else if(R1==0 && R2==1) //若S7按下但S6未按下
{
##S7按下代码
while(R1==0);
}
else if(R2==0 && R1==1) //若S6按下但S7未按下
{
##S6按下代码
}
}
}
以上为个人的理解与代码,精彩内容持续呈现中~~~