矩阵键盘


6-1矩阵键盘

矩阵按键

芯片引脚

前四根线(P17~P14)判断行,给0相当于接地(由上面这幅图我们知道P1的一端已经接在了VCC,所以要让P1_x运行,要给它低电平,即0),此时io口为低电平

后四根(P13~P10)判断该行对应的某一个按键

下面的代码主要是实现控制矩阵键盘,并把按下去的键位对应的数字在LCD1602上显示出来

ps:常见的Delay就不放出来了,懂得都懂

matrix矩阵

MatrixKey.h

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif

MatrixKey.c

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

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;
}

我们可以发现这个函数代码是由四组模板一样的小代码组成的,下面将拎一组出来解释

矩阵按键

P1=0xFF;//让所有的P1口都为1,就是不对他们进行操作,让他们处于standby状态
P1_3=0;//"唤醒"列,我们先控制P1_3,让他为0,处于运行状态--①
//然后逐个判断用户按下了哪个键位+按键消抖,检测松手,赋相应的值给KeyNumber
	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;}//--⑤

main.c

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

unsigned char KeyNum;

void main()
{
	LCD_Init();                       //初始化
	LCD_ShowString(1,1,"Martix:");    //从第一行第一列开始输入
	while(1)
	{
		KeyNum=MatrixKey();			  //把返回的KeyNumber赋值给KeyNum
		if(KeyNum)					  
		{
			LCD_ShowNum(2,1,KeyNum,2);//我们要在这句话中才能让灯亮起来,关键在于让KeyNum为0的时候根本读不到这句话
		}
	}
}

对于if的解释 iiiiiiimportant!!!!!!

while(1)
	{
		KeyNum=MatrixKey();			  //把返回的KeyNumber赋值给KeyNum
     	LCD_ShowNum(2,1,KeyNum.2);
	}

​ 如果没有if,先进入while(1)循环中,那么当用户按下S1的时候,Matrix函数返回KeyNumber的值给主函数的KeyNum,此时KeyNum为1,LCD1602迅速地显示“1”(很快啊!肉眼根本看不见的那种),随即跳出此次的while(1)循环并进入下一次while(1)循环,因为下一刻用户不可能速速按下某个键位,所以这时候Matrix函数中初始化的那句

unsigned char KeyNumber=0;

就会直接被返回到主函数的KeyNum中,即KeyNum为0,所以,我们看到的现象是,无论怎么按都只会显示0,其实有显示过1的,但是太快了,看不见。

​ 那么,我们加了if(KeyNum)后,当默认为0的时候,if判断为假,就不会出现0,因为为0的时候,根本不会进入到LCD_ShowNum中执行,所以一直显示的是按下去的键位的辣个数字。

强迫症+专业注释

/**
  * @brief  简介
  * @param  参数1
  * @param  参数2
  * @param  参数n
  * @retval 返回值
  */

6-2 矩阵键盘密码锁

以下代码是在6-1的基础上修改的,所以不再放出Matrix函数,直接上main.c

ps:注释不会改中文哈哈哈打出来全是”?”,因此以后的注释都是全(塑料/工地)英制

main.c

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

//初始定义未赋初值时默认赋值为0
unsigned char KeyNum;
unsigned int Password,Count;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Password:");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum)
		{
			if(KeyNum<=10)  //if S1~S10keys are pressed ,input password
			{
				if(Count<4) //if the time of inout < 4 
				{
					Password*=10;//password RL 
					Password+=KeyNum%10;//consider the situation of when user press s10 then output 0 ,and get one password
					Count++;  //metering +1
				}
				LCD_ShowNum(2,1,Password,6); //when finishe the enter,updata the display
			}
			if(KeyNum==11)//if press S11--->confirm
			{
				if(Password==2345)  //if the password == the correct password
				{								
					LCD_ShowString(1,14,"OK");
					Password=0;//the password zero clearing
					Count=0;   //metering zero clearing
					LCD_ShowNum(2,1,Password,6); //updata the display0
				}
				else
				{
					LCD_ShowSrting(1,14,"ERR");
					Password=0;//the password zero clearing
					Count=0;   //metering zero clearing
					LCD_ShowNum(2,1,Password,6); //updata the display
				}
			}
			if(KeyNum=12)//if press S12---> cancel
			{
				Password=0;//the password zero clearing
				Count=0;   //metering zero clearing
				LCD_ShowNum(2,1,Password,6); //updata the display				
			}
		}
	}
}

我们一节一节地看,以下从用户按下某个键位开始,即从if(KeyNum)开始往下看

输入Password

if(KeyNum<=10)  //if S1~S10keys are pressed ,input password
{
	if(Count<4) //if the time of inout < 4 
	{
		Password*=10;//password RL 
		Password+=KeyNum%10;//consider the situation of when user press s10 then ouput 0 ,and get one password
		Count++;  //metering +1
	}
	LCD_ShowNum(2,1,Password,6); //updata the display
}

这里的设定是,按下S1~S10时,对应1~0,这里用到的很妙的一招是

Password*=10;
Password+=KeyNum%10;

Password自×10,则相当于所有数字往左移动一位待输入的数字由0占据

再输入的数字一定是从个位开始,然后在按下下一个按键时,往左移动,就,很妙啊!

然后再设定只能输入4次,噢对了,我们在一开始设置了全局变量

unsigned int Password,Count;

所以Password和Count初始值都是0,因此Count<4输入四次

确认键

if(KeyNum==11)//if press S11--->confirm
{
	if(Password==2345)  //if the password == the correct password
	{								
		LCD_ShowString(1,14,"OK");
		Password=0;//the password zero clearing
		Count=0;   //metering zero clearing
		LCD_ShowNum(2,1,Password,6); //updata the display
	}
	else
	{
		LCD_ShowSrting(1,14,"ERR");
		Password=0;//the password zero clearing
		Count=0;   //metering zero clearing
		LCD_ShowNum(2,1,Password,6); //updata the display
	}
}

首先,我们约定了2345是正确密码,当输入了2345时按下S11会出现”OK”

然后,就是输入完毕后一切归零,即让用户再次输入(无论输入正确与否)

Password=0;//the password zero clearing
Count=0;   //metering zero clearing
LCD_ShowNum(2,1,Password,6); //updata the display

先让Password重置为0

然后计数Count也为0

一切都回到最开始的样子,即全局变量初始化的样子

取消键

if(KeyNum=12)//if press S12---> cancel
{
	Password=0;//the password zero clearing
	Count=0;   //metering zero clearing
	LCD_ShowNum(2,1,Password,6); //updata the display				
}

有了上面的解释,这个应该不难理解吧

关于LCD1602.c

LCD1602内部显示地址

举例说明


文章作者: WB
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WB !
  目录