51单片机-6-矩阵键盘

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1、矩阵键盘的介绍

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

扫描的概念

  • 数码管扫描输出扫描原理显示第1位→显示第2位→显示第3位→……然后快速循环这个过程最终实现所有数码管同时显示的效果
  • 矩阵键盘扫描输入扫描     原理读取第1行(列)→读取第2行(列) →读取第3行(列) → ……然后快速循环这个过程最终实现所有按键同时检测的效果
  • 以上两种扫描方式的共性节省I/O口 

 比如这里的矩阵键盘

若采用逐行扫描模式先令P17、P16、P15、P14分别为0111代表扫描第一行即按键S1、S2、S3、S4若能检测到P13、P12、P11、P10有0或低电平则表示某按键被按下检测完第一行后令P17、P16、P15、P14分别为1011即检测第二行再检测P13、P12、P11、P10令P17、P16、P15、P14分别为1101即检测第三行再检测P13、P12、P11、P10令P17、P16、P15、P14分别为1110即检测第四行再检测P13、P12、P11、P10。

若采用逐列扫描模式令P13、P12、P11、P10分别为0111即检测第一列再检测P17、P16、P15、P14以此类推。

2、弱上拉概念理解

如下如所示单片机内部某个引脚结构简图若外部也是接入的高电平则单片机读入高电平若外部读入的是低电平则强低电平把内部电源Vcc拉成低电平单片机读入低电平。

P1、P2、P3都是弱上拉P0是开漏输出但外接上拉电阻因此和其他几个端口都是同样的模式。

3、Debug本节汇总

  • 若添加了LCD1602.c函数后转到相关子函数报错可以保存程序退出重新打开工程文件。
  • 写法问题在main函数里面定义变量要放在开头放在中间系统会报错变量没有定义。

4、代码按下按键松开后在第二行显示按下按键的键号

1主函数

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

void main()
{
	unsigned char Keynum=0;
	LCD_Init();
	LCD_ShowString(1,1,"HelloWorld");
	
	while(1)
	{
		Keynum=MatrixKey();
		if(Keynum)
		{
			LCD_ShowNum(2,1,Keynum,2);
		}		
	}
}

2矩阵键盘函数Matrixkey.c:按行检索。

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

unsigned char MatrixKey()
{
	unsigned char keynumber=0;
	
	P1=0xFF;
	P1_7=0;
	if(P1_3==0){Delay(20);while(P1_3==0);Delay(20);keynumber=1;}
	if(P1_2==0){Delay(20);while(P1_2==0);Delay(20);keynumber=2;}
	if(P1_1==0){Delay(20);while(P1_1==0);Delay(20);keynumber=3;}
	if(P1_0==0){Delay(20);while(P1_0==0);Delay(20);keynumber=4;}
	
	P1=0xFF;
	P1_6=0;
	if(P1_3==0){Delay(20);while(P1_3==0);Delay(20);keynumber=5;}
	if(P1_2==0){Delay(20);while(P1_2==0);Delay(20);keynumber=6;}
	if(P1_1==0){Delay(20);while(P1_1==0);Delay(20);keynumber=7;}
	if(P1_0==0){Delay(20);while(P1_0==0);Delay(20);keynumber=8;}
	
	P1=0xFF;
	P1_5=0;
	if(P1_3==0){Delay(20);while(P1_3==0);Delay(20);keynumber=9;}
	if(P1_2==0){Delay(20);while(P1_2==0);Delay(20);keynumber=10;}
	if(P1_1==0){Delay(20);while(P1_1==0);Delay(20);keynumber=11;}
	if(P1_0==0){Delay(20);while(P1_0==0);Delay(20);keynumber=12;}
	
	P1=0xFF;
	P1_4=0;
	if(P1_3==0){Delay(20);while(P1_3==0);Delay(20);keynumber=13;}
	if(P1_2==0){Delay(20);while(P1_2==0);Delay(20);keynumber=14;}
	if(P1_1==0){Delay(20);while(P1_1==0);Delay(20);keynumber=15;}
	if(P1_0==0){Delay(20);while(P1_0==0);Delay(20);keynumber=16;}

	return keynumber;
	
}

5、本节补充

1函数注释说明

/**
  * @brief : 
  * @param :
  * @retval: 
  */

例如对矩阵键盘函数进行说明如下所示

/**
  * @brief :	矩阵键盘读取键码
  * @param :	无参数
  * @retval:	Keynumber按下按键的键码值
	如果按下按键不动则程序停留在此函数处松开后的一瞬间返回按键键码值
  */

2部分问题分析

<1>起初代码为

void main()
{
	unsigned char Keynum=0;
	LCD_Init();
	LCD_ShowString(1,1,"HelloWorld");
	
	while(1)
	{
		Keynum=MatrixKey();
		LCD_ShowNum(2,1,Keynum,2);	
	}
}

故障描述无论如何按下按键按何种按键数码管显示始终为00 

 分析原因数码管闪烁太快无法观察显示的键码因此加入if判断语句当接收到矩阵键盘函数返回的非0值时则进入数码管显示函数显示具体键码值返回值很快重置为0但进入不到if语句里面的显示函数因此数码管不显示重置后的值也就是00。除非再次有按键按下才会更改数码管的显示数值。

void main()
{
	unsigned char Keynum=0;
	LCD_Init();
	LCD_ShowString(1,1,"HelloWorld");
	
	while(1)
	{
		Keynum=MatrixKey();
		if(Keynum)
		{
			LCD_ShowNum(2,1,Keynum,2);
		}		
	}
}

 3省时小技巧

对于编程中的一些相似语句可以通过封装来节省时间提高效率。

具体操作为Templates——>右击并选择Configure Templates——>添加范例名和范例具体内容

若想让光标显示在某处可以用“|”来指定光标位置。

 

 

小项目矩阵键盘密码锁

S1~S10分别对应数字1~9和0S11代表确认键S12代表取消键

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

void main()
{
	unsigned char Keynum=0;
	unsigned int password=0;
	unsigned char Count=0;
	LCD_Init();
	LCD_ShowString(1,1,"Password:");
	
	while(1)
	{
		Keynum=MatrixKey();
		if(Keynum)
		{
			if(Keynum<=10)	//如果S1~S10按键被按下,即为输入密码
			{
				if(Count<4)
				{
					password=password*10;		//密码左移一位
					password+=Keynum%10;		//获取一位密码
					Count++;		//计次加一
				}		
				LCD_ShowNum(2,1,password,4);	//更新显示这里的函数值显示范围为0-65535输入不能超过65535否则会溢出
			}
			if(Keynum==11)		//S11设置为确认键
			{
				if(password==2345)		//如果密码等于正确密码
				{
					LCD_ShowString(1,14,"OK ");		//显示OKOK后面细节加了一个空格主要是为了在输错密码显示ERR后能覆盖之前的ERR。
					password=0;		//密码清0
					Count=0;			//计次清0
					LCD_ShowNum(2,1,password,4);	//更新显示此举是为了输入密码确认后将屏幕清零
				}
				else
				{
					LCD_ShowString(1,14,"ERR");		//显示ERR
					password=0;		//密码清0
					Count=0;			//计次清0
					LCD_ShowNum(2,1,password,4);	//更新显示
				}
			}
			if(Keynum==12)		//S12设置为取消键
			{
				password=0;		//密码清0
				Count=0;			//计次清0
				LCD_ShowNum(2,1,password,4);	//更新显示		
			}
			
		}		
	}
}

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6