6-矩阵键盘

发布时间 2023-12-31 00:43:01作者: Jinx8823

1.矩阵键盘原理

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

数码管是输出扫描:

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

矩阵键盘是输入扫描:

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

image-20231230210545250

将矩阵按键进行按列扫描,例如,先设置P13,P12,P11,P10为0111,在此基础上,P17=0,说明S1按下,P16=0,说明S5按下,P15=0,说明S9按下,P14=0,说明S13按下。(因为按行进行扫描会出现冲突)这里的原理刚好与下面的函数代码相对应。

2.弱上拉

简单点说就是1的驱动力是有限的,0的驱动能力比较强,弱上拉,强下拉这就是这种单片机IO口的工作模式

简单模型

image-20230926104548473

在这种模型下,虽然VCC输出的是1电平,但由于中间有一个电阻,后面直接接地,所以检测点检测到的输出也是0

具体了解可以看STC89C52的官方手册

3.基础操作

先将原来的模块化文件copy过来

image-20231003165824184

测试LCD1602是否有效

#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"

void main()
{
	LCD_Init();//可以右键点击追踪到函数的声明为止
	LCD_ShowString(1,1,"HelloWorld");
	while(1)
	{
		
	}
}

由于每次生成这些.h文件,都要敲一些相同的代码,可以通keil自带的Templates来配置自己的模板

用到其他一些高重复性的代码时也可以生成相应的模板

image-20231003171126914

在2处空白处右键可以设置模板,4处的竖杆表明生成模板后的鼠标位置

4.代码实现

独立按键显示相应键值

Matrix.c

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

/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下的按键的键值
  如果按键按下不放,程序会留在此函数,松手时才返回相应的键码值,没有按键按下时
  返回0
  */
  
unsigned char MatrixKey()
{
	unsigned char KeyNumber=0;
	P1=0xFF;
	P13=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=1;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=5;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=9;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=13;}
	
	P1=0xFF;
	P12=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=2;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=6;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=10;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=14;}
	
	P1=0xFF;
	P11=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=3;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=7;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=11;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=15;}
	
	P1=0xFF;
	P10=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=4;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=8;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=12;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=16;}
	return KeyNumber;
}

Matrix.h

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif

main.c

#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Matrix.h"
unsigned char KeyNum;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"HelloWorld");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum)
		{
			LCD_ShowNum(2,1,KeyNum,2);
		}	
	}
}

5.矩阵键盘密码锁

#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
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)	//如果S1到S10按下,输入密码
			{
				if(Count<4)	//如果输入次数小于4
				{
					Password*=10;		//密码左移一位
					Password+=KeyNum%10;//获取一位密码
				}	
				Count++;
				LCD_ShowNum(2,1,Password,4);//更新显示
			}
			if(KeyNum==11)	//按下S11表示确认
			{
				if(Password==6666)//如果密码正确,显示OK
				{
					LCD_ShowString(1,14,"OK ");
					Count=0;//计数清0
					Password=0;//密码清0
					LCD_ShowNum(2,1,Password,4);//更新显示
				}
				else			//如果密码错误,显示ERR
				{
					LCD_ShowString(1,14,"ERR");
					Count=0;//计数清0
					Password=0;//密码清0
					LCD_ShowNum(2,1,Password,4);//更新显示
				}
			}
			if(KeyNum==12)		//S12为取消键,按下密码清0
			{
				Count=0;//计数清0
				Password=0;//密码清0
				LCD_ShowNum(2,1,Password,4);//更新显示
			}
			
		}	
	}
}

其他文件和上述文件一样