矩阵键盘的介绍
- 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
- 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态
扫描的概念
-
数码管扫描(输出扫描)
原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
-
矩阵键盘扫描(输入扫描)
原理1:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果(逐行(列)扫描)
原理2:将所有行置高电平,所有列置低电平,查看高电平有无被拉低,若有说明这一行有按键被按下。再重复这一操作判断是哪一列被按下。(行列扫描)
-
以上两种扫描方式的共性:节省I/O口
矩阵键盘逐行(列)扫描代码
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF;
P1_2=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
//当然也可以用
//if(P1_7==0){Delay(20);if(P1_7==0);KeyNumber=1;}但是这样就没有松手检测
矩阵键盘行列扫描代码
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber;
P0=0x0f;
if(P0!=0x0f)//读取按键是否按下
{
Delay(20);//延时20ms进行消抖
if(P0!=0x0f)//再次检测键盘是否按下
{
P0=0x0f;
switch(P0)
{
case(0X07): KeyNumber=4;break;
case(0X0b): KeyNumber=3;break;
case(0X0d): KeyNumber=2;break;
case(0X0e): KeyNumber=1;break;
}
P0=0XF0;
switch(GPIO_KEY)
{
case(0X70): KeyNumber=KeyNumber+12;break;
case(0Xb0): KeyNumber=KeyNumber+8;break;
case(0Xd0): KeyNumber=KeyNumber+4;break;
case(0Xe0): KeyNumber=KeyNumber;break;
}
}
练习可以写一下
1.矩阵键盘控制一位数码管静态现实键值
2.利用定时器扫描矩阵键盘,实现动态现实数码管两位键值
矩阵键盘密码锁代码
#include <REGX52.H>
#include "LCD1602.h"
#include "MatrixKey.h"
#include <stdio.h>
#include <string.h>
#define LEN 7 //LEN 为密码位数加一
unsigned char pass[LEN]="123ABC"; //预设密码
unsigned char KeyNum;
unsigned char key[LEN]=" ";
unsigned int a=0;
unsigned int i=0; //i记录输入次数
void main(){
LCD_Init();
LCD_ShowString(1,1,"PassWord:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum!=0&&KeyNum!='*'&&KeyNum!='#'&&a<6&&i<6)
{
{key[a]=KeyNum;
LCD_ShowString(2,1,key);
}a+=1;
}
if(KeyNum=='#'&&i<6)
{
if(strcmp(pass,key)==0)
{LCD_ShowString(1,12,"OK");for(a=0;a<6;a++)key[a]=' ';LCD_ShowString(2,1,key);a=0;LCD_ShowString(2,1,"Welcome!");i=7;}
else
{LCD_ShowString(1,12,"ERR");i+=1;for(a=0;a<6;a++)key[a]=' ';LCD_ShowString(2,1,key);a=0;}
}
if(KeyNum=='*'&&i<6)
{
a-=1;
key[a]=' ';
LCD_ShowString(2,1,key);
}
if(i==6)
LCD_ShowString(2,1,"LOCK ");
}
}