矩阵键盘原理
参考文献:点击前往
扫描模式
数码管扫描:输出扫描的一种,以人类肉眼无法分辨的速度进行扫描,呈现出同时显示的假象
矩阵键盘扫描:输入扫描的一种,高速逐行扫描,获取按键按下位置;目前的电脑显示器也是使用此方法检测,可以极大地压缩引脚数量(譬如 1920x1080,仅需引脚:1920+1080=3000)
实例展示
检测单点按键
首先我们来看一下检测按键的核心代码
代码清单 MatrixKey.c
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
// 当前点击的按键
unsigned char KeyNumber=0;
// 第一步:全局置1,即全部上拉
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;
}
别忘了头文件 MatrixKey.h
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
之后总结我们之前的 Delay 和 LCD1602 模块,不难得出以下代码
代码清单 main.c
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main(){
LCD_Init(); //LCD初始化
LCD_ShowString(1,1,"MatrixKey:"); //LCD显示字符串
while(1)
{
KeyNum=MatrixKey(); //获取矩阵键盘键码
if(KeyNum) //如果有按键按下
{
LCD_ShowNum(2,1,KeyNum,2); //LCD显示键码
}
}
}
密码锁
仅需修改源文件即可
代码清单 main.c
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
// 按键作用: S1~S9 设置数字为 1~9, S10定义为数字0, S11用作于是确认按键, S12用作于是取消按键 《《《 S13~S16,我们不去进行使用
unsigned char KeyNum; // 全局变量初始化默认为:0
unsigned int Password,Count; // 如果用6位数字的密码就会超出这个 unsigned int 的一个数值的范围了 0~65535, Count作用:计次,防止输入过多的密码
int main(void)
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10) //如果S1~S10按键按下,输入密码
{
if(Count<4) //如果输入次数小于4
{
Password*=10; //密码左移一位 : Password = Password * 10
Password+=KeyNum%10; //获取一位密码 : Password = password + KeyNum % 10, 1~9取模10还是为原来的数字~ 获取密码用取模%运算符然后进行赋值
Count++; //计次加一
}
LCD_ShowNum(2,1,Password,4); //更新显示 0000 0000 输入第一次(1) 显示0001 》》》 0001 0010 输入第二次(2) 显示0012
}
if(KeyNum==11) //如果S11按键按下,确认 ----注意:这里不进行消抖的原因是:模块化编程的时候已经进行消抖了
{
if(Password==2345) //如果密码等于正确密码 --------------------------- 定义密码
{
LCD_ShowString(1,14,"OK "); // 显示OK
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); // 更新显示
}
else //否则
{
LCD_ShowString(1,14,"ERR"); //显示ERR
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); //更新显示
}
}
if(KeyNum==12) //如果S12按键按下,取消
{
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); //更新显示
}
}
}
}