【新手小白的嵌入式学习之路】-51单片机的学习_p6矩阵键盘


前言

上一篇我们学习了模块化编程的思想,并且还使用了LCD1602显示屏的功能,这一篇我们学习矩阵键盘模块,并利用矩阵键盘和LCD1602显示屏完成密码锁的项目。


6-1 矩阵键盘

这一小节,我们学习用LCD1602显示屏显示我们矩阵键盘的键码值。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

扫描的概念

在这里插入图片描述
我们的显示器都是矩阵连接扫描的。
在这里插入图片描述
按行扫描的时候,先检测P17-P14的中哪个为0,就是哪行的按键被按下,然后再检测P13-P10,即可判断这一行中哪个按键被按下。

  • 但是不推荐逐行扫描,因为按行扫描P15会时高时低,而P15连接到步进电机,右边连接BZ,经过驱动器驱动会增加输出电流能力,连接到蜂鸣器上,这个开发板上BZ以一定频率高低变换时蜂鸣器会响。

在这里插入图片描述

按列扫描同理,先检测P13-P10,确定列,再检测P17-P14,即可确定哪列的哪个按键被按下。

这里还提到了单片机的I/O口是一种弱上拉强下拉的工作模式,这也是为什么LED和按键都是低电平(0)有效。(具体可以参考手册)
在这里插入图片描述

完整演示

由于上一篇我们已经引入模块化编程的思想,往后我们都采用模块化编程。
Delay和LCD1602的.c和.h文件我们已经写过,直接放进6-1这一节的工程文件。
在这里插入图片描述
我们先写几行代码测试下LCD1602能否使用。

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Star");
	while(1)
	{
	}
}

正常使用√。
在这里插入图片描述
添加矩阵按键的模块化程序,编写Matrixkey.c和Matrixkey.h文件

.h文件的编写有固定的套路,我们可以编写好固定模板来方便我们编写代码。
在这里插入图片描述
在这里插入图片描述

Matrixkey.c代码

#include <REGX52.H>
#include "Delay.h"
/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下按键的键码值
			如果按键按下不放,程序会停留在此函数,松手的一瞬间返回按键键码,没有按键按下时返回零
  */

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;} //S1的检测
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;} //S5的检测
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;} //S9的检测
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;} //S13的检测

	P1=0xFF;
	P1_2=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;} //S2的检测
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;} //S6的检测
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;} //S10的检测
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;} //S14的检测

	P1=0xFF;
	P1_1=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;} //S3的检测
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;} //S7的检测
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;} //S11的检测
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;} //S15的检测

	P1=0xFF;
	P1_0=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;} //S4的检测
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;} //S8的检测
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;} //S12的检测
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;} //S16的检测
	
	return KeyNumber;
}

if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}

  1. 在扫描第一列时,如果P1_7==0,那么此时是判断开关1的状态
  2. 由于是机械按键,加入延时函数消除抖动,然后判断是否松手;如果松手,继续消除抖动
  3. 返回值KeyNumber

Matrixkey.h代码

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char Matrixkey();

#endif

主函数代码

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
/**
  * @brief 矩阵键盘读取按键键码
  * @param 无
  * @retval KeyNumber 按下按键的键码值
  如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下返回0.
  */

unsigned char KeyNum;

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

没加if(KeyNum)的时候,我们始终显示的是00,因为我们的代码运行速度很快,按下按键后其实显示数字了,但是很快又进入了新循环,所以一直显示初始的00。

6-2 矩阵键盘密码锁

这一小节,我们学习制作一个电子密码锁。

  1. 直接复制6-1的工程文件
  2. 首先定义按键的作用,S1-S9定义为数字的1-9,S10定义为0,S11为确认键,S12为取消键,S13-S16按键不用。
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
/**
  * @brief 矩阵键盘读取按键键码
  * @param 无
  * @retval KeyNumber 按下按键的键码值
  如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下返回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) //如果s1-s10按键按下,输入密码
			{
				if(Count<4) //输入次数小于4
				{
					Password*=10;         //密码左移1位
					Password+=KeyNum%10;  //获取1位密码
					Count++;    //计次加一
					LCD_ShowString(1,14,"   ");
				}
				LCD_ShowNum(2,1,Password,4);  //更新显示
			}
			if(KeyNum==11)  //如果s11按键按下,确认密码
			{
				if(Password==2468)  //如果密码等于正确密码,显示ok
				{
					LCD_ShowString(1,14,"ok ");
					P2=0xFE;//1111 1110
					Delay(500);
					P2=0xFD;//1111 1101
					Delay(500);
					P2=0xFB;//1111 1011
					Delay(500);
					P2=0xF7;//1111 0111
					Delay(500);
					P2=0xEF;//1110 1111
					Delay(500);
					P2=0xDF;//1101 1111
					Delay(500);
					P2=0xBF;//1011 1111
					Delay(500);
					P2=0x7F;//0111 1111
					Delay(500);
					Password=0;   //密码清零
					Count=0;   //计次清零
					LCD_ShowNum(2,1,Password,4);  //更新显示
				}
				else
				{
					LCD_ShowString(1,14,"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);  //更新显示				
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值