一、认识矩阵键盘

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态

51 单片机[6]:矩阵键盘及密码锁插图

扫描的概念

数码管扫描(输出扫描)
原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果

矩阵键盘扫描(输入扫描)
原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果

以上两种扫描方式的共性:节省I/O口

单片机的I/O口是弱上拉、强下拉

51 单片机[6]:矩阵键盘及密码锁插图(1)

当引脚输出为1时,驱动能力很弱,允许外部装置将其拉低。当引脚输出为低时,它的驱动能力很强,可吸收相当大的电流

二、简单的矩阵键盘实现

目标 :按下按键后,LCD屏显示键码。

把上节的Delay.c、Delay.h和LCD1602.c、LCD1602.h复制到项目中。

新建一个MatrixKey.c文件和MatrixKey.h

  1. 点击templates,在空白处右键,点击configure templates

51 单片机[6]:矩阵键盘及密码锁插图(2)

  1. 点击新建图标,输入#ifndef,在Text中输入模板内容,点击OK

51 单片机[6]:矩阵键盘及密码锁插图(3)

注意,要在下划线中间打一个竖杠,这样在点击模板后,光标会出现在该位置。

  1. 在MatrixKey.h文件中编辑,双击#ifndef,可以看到

51 单片机[6]:矩阵键盘及密码锁插图(4)

在光标处输入MATRIXKEY

完整的MatrixKey.h文件内容为:

#ifndef __MATRIXKEY__H__
#define __MATRIXKEY__H__

unsigned char MatrixKey();

#endif
  1. 矩阵键盘的输入扫描要先确定列,再确定行。完整的MatrixKey.c文件为:
#include 
#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;
}
  1. main.c文件:
#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "MatrixKey");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
LCD_ShowNum(2, 1, KeyNum, 2);
}
}
}

三、矩阵键盘密码锁

目标:S1 ~ S9为数字1 ~ 9,S10为0,S11为确认,S12为取消。

把刚刚的简单项目复制一份,在旧项目的基础上进行过更改。

  1. 先实现一位数字输出。main.c文件如下:
#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Passward;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "Passward:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)  //是否按下S1~S10
{
Passward = KeyNum%10;  //获取一位密码
}
LCD_ShowNum(2, 1, Passward, 2);
}
}
}

按下S1,LCD显示01,按下S2,LCD显示02……按下S10,LCD显示00.

  1. 实现输入一串数字
#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Passward;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "Passward:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)  //是否按下S1~S10
{
Passward *= 10;         //密码左移一位
Passward += KeyNum%10;  //获取一位密码
}
LCD_ShowNum(2, 1, Passward, 4);
}
}
}

这个程序好像可以实现密码输入。按下S1,显示0001,按下S3,显示0013。但是当数字很大超出数据范围时,密码就出现错误了,显示的数字就不按按下的按键显示了。

所以就需要计次。定义一个变量Count

#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Passward, Count;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "Passward:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)  //是否按下S1~S10
{
if(Count<4)
{
Passward *= 10;         //密码左移一位
Passward += KeyNum%10;  //获取一位密码
}
Count++;
}
LCD_ShowNum(2, 1, Passward, 4);
}
}
}
  1. 验证密码,若正确则OK,否则ERR
#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Passward, Count;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "Passward:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)  //是否按下S1~S10
{
if(Count<4)  //次数判断
{
Passward *= 10;         //密码左移一位
Passward += KeyNum%10;  //获取一位密码
Count++;  //计次加一
}
LCD_ShowNum(2, 1, Passward, 4);
}
if(KeyNum == 11)  //是否按下S11确认
{
if(Passward == 4399)
{
LCD_ShowString(1, 14, "OK");
}
else
{
LCD_ShowString(1, 14, "ERR");
}
}
}
}
}

再加上清零和更新显示

			if(KeyNum == 11)  //是否按下S11确认
{
if(Passward == 4399)
{
LCD_ShowString(1, 14, "OK ");
Passward = 0;  //密码清零
Count = 0;     //计次清零
LCD_ShowNum(2, 1, Passward, 4);  //更新显示
}
else
{
LCD_ShowString(1, 14, "ERR");
Passward = 0;  //密码清零
Count = 0;     //计次清零
LCD_ShowNum(2, 1, Passward, 4);  //更新显示
}
}
  1. 按下取消,清零
#include 
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Passward, Count;
void main()
{
LCD_Init();//上电初始化
LCD_ShowString(1, 1, "Passward:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)  //是否按下S1~S10
{
if(Count<4)  //次数判断
{
Passward *= 10;         //密码左移一位
Passward += KeyNum%10;  //获取一位密码
Count++;  //计次加一
}
LCD_ShowNum(2, 1, Passward, 4);
}
if(KeyNum == 11)  //是否按下S11确认
{
if(Passward == 4399)
{
LCD_ShowString(1, 14, "OK ");
Passward = 0;  //密码清零
Count = 0;     //计次清零
LCD_ShowNum(2, 1, Passward, 4);  //更新显示
}
else
{
LCD_ShowString(1, 14, "ERR");
Passward = 0;  //密码清零
Count = 0;     //计次清零
LCD_ShowNum(2, 1, Passward, 4);  //更新显示
}
}
if(KeyNum == 12)  //是否按下S12取消
{
Passward = 0;  //密码清零
Count = 0;     //计次清零
LCD_ShowNum(2, 1, Passward, 4);  //更新显示
}
}
}
}
本站无任何商业行为
个人在线分享 » 51 单片机[6]:矩阵键盘及密码锁
E-->