51单片机从零开始入门教程 第六章(矩阵键盘篇)

参考教程:[6-1] 矩阵键盘_哔哩哔哩_bilibili

一、概述

1、矩阵键盘的作用

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

2、两种扫描

(1)数码管扫描(输出扫描)

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

(2)矩阵键盘扫描(输入扫描)

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

二、开发板上的矩阵按键模块

1、矩阵按键的组成

        矩阵按键模块中有16个按键,它们按照4×4的方式排列,与它们相对接的是P1寄存器的8个位,其中0-3位对应矩阵按键模块的每一列,4-7位对应矩阵按键的每一行。

2、矩阵键盘的扫描方式

(1)按行扫描:为了找到被按下的按键,可以选择按行扫描的方式,首先将P1的4-7位轮流配置为低电平(其它三位置为高电平),如果从第一行开始扫描,那么就先将P17配置为低电平,P16、P15、P14配置为高电平,然后检测P1的0-3位,其中哪一位是低电平,那么该位对应列的第一行那个按键就是处于被按下的状态,以此类推。

(2)按列扫描:为了找到被按下的按键,可以选择按列扫描的方式,首先将P1的0-3位轮流配置为低电平(其它三位置为高电平),如果从第一列开始扫描,那么就先将P13配置为低电平,P12、P11、P10配置为高电平,然后检测P1的4-7位,其中哪一位是低电平,那么该位对应行的第一列那个按键就是处于被按下的状态,以此类推。(建议采用按列扫描,若使用按行扫描,P15的电平会忽高忽低,而P15可能还会影响蜂鸣器,从而造成异常现象,这个具体看开发板的原理图,有些板子已经将这个引脚冲突改善,不会有此异常现象)

三、矩阵键盘应用实验

1、在液晶屏上显示被按下的矩阵按键序号实验

(1)项目包含的文件:其中Delay.c、Delay.h、LCD1602.c及LCD1602.h全部沿用上一例的代码,这里不再给出,INTRINS.H及REGX52.H在系统include目录中,不需要自己编写。

(2)将源文件及头文件添加到项目中,然后进行编译。

①MatrixKey.c文件:

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下按键的键码值
		   如果按键按下不放,程序会停留在该函数中,松手后才会返回键码值
		   没有按键按下,函数返回0
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber = 0;  //用该变量记录被按下的按键
	
	P1 = 0xFF;   //按列扫描,首先扫描第一列
	P1_3 = 0;    //P1_3对应第一列,置为低电平,其它三位置为高电平
	
	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;    //P1_2对应第二列,置为低电平,其它三位置为高电平
	
	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;    //P1_1对应第三列,置为低电平,其它三位置为高电平
	
	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;    //P1_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

③main.c文件:

#include <REGX52.H>
#include "LCD1602.h"
#include "MatrixKey.h"

unsigned char KeyNum = 0;

void main()
{
	LCD_Init();  //初始化
	while(1)
	{
		KeyNum = MatrixKey();
		if(KeyNum)  //如果有按键按下
		{
			LCD_ShowNum(1,1,KeyNum,2);  //屏幕显示按下的按键序号
		}
	}
}

(3)将生成的.hex文件下载到开发板中,按下矩阵按键,屏幕上会显示按键对应的键码值。

2、矩阵键盘密码锁实验

(1)项目包含的文件:其中MatrixKey.c、MatrixKey.h、Delay.c、Delay.h、LCD1602.c及LCD1602.h全部沿用上一例的代码,这里不再给出,INTRINS.H及REGX52.H在系统include目录中,不需要自己编写。

(2)将源文件及头文件添加到项目中,然后进行编译。

main.c文件:

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"

unsigned char KeyNum = 0;
unsigned int Password;  //4位密码(32位,4个字节)
unsigned char Count = 0;  //记录已输入密码位数

void main()
{
	LCD_Init();  //初始化
	LCD_ShowString(1,1,"Password:");
	LCD_ShowNum(2,1,Password,4);
	while(1)
	{
		KeyNum = MatrixKey();
		if(KeyNum)  //如果有按键按下
		{
			if(KeyNum <= 10)  //如果s1-s10按键按下,输入密码
			{
				if(Count < 4)
				{
					Password *= 10;  //把上一位密码左移(给下一位密码腾出位置)
					Password += KeyNum % 10;  //获取输入的1位密码
				}
				Count++;
			}
			if(KeyNum == 11)  //s11作为确认键
			{
				if(Password == 2345)
				{
					LCD_ShowString(1,14,"OK");  //密码正确显示OK
					Delay(5000);  //停留5秒
					Password = 0;  //密码清零
					Count = 0;  //计数清零
					LCD_ShowNum(2,1,Password,4);  //更新显示
					LCD_ShowString(1,14,"   ");
				}
				else
				{
					LCD_ShowString(1,14,"ERR");  //密码错误显示ERR
					Delay(5000);  //停留5秒
					Password = 0;  //密码清零
					Count = 0;  //计数清零
					LCD_ShowNum(2,1,Password,4);  //更新显示
					LCD_ShowString(1,14,"   ");
				}
			}
			if(KeyNum == 12)  //s12作为手动清空输入键
			{
				Password = 0;  //密码清零
				Count = 0;  //计数清零
				LCD_ShowNum(2,1,Password,4);  //更新显示
			}
			LCD_ShowNum(2,1,Password,4);  //显示当前输入的密码
		}
	}
}

(3)将生成的.hex文件下载到开发板中进行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值