51单片机(六)矩阵键盘和矩阵键盘密码锁

news2024/12/22 14:30:07

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf

本节主要介绍LCD1602调试工具,用于对调试代码进行输出显示,方便我们对开发过程中代码的调试工作。本文会提供LCD1602的使用方法、驱动代码、以及演示LCD1602调试过程。

文章目录

  • 一、矩阵键盘介绍和本节目标
    • 1.1 矩阵键盘介绍
      • 1.1.1 矩阵键盘概念
      • 1.1.2 矩阵键盘原理
        • 1.1.2.1扫描过程:
        • 1.1.2.2 单片机i/o口弱上拉模式
    • 1.2 本节目标
  • 二、读取并显示矩阵键盘按键
  • 三、矩阵键盘密码锁

一、矩阵键盘介绍和本节目标

1.1 矩阵键盘介绍

1.1.1 矩阵键盘概念

在这里插入图片描述

相较于独立按键,矩阵键盘可以减少i/o口的占用。

独立按键是每个按键都占用一个i/o口;而矩阵键盘是利用四行四列达到16个键盘占用8个i/o口的目的;减少了i/o口的占用。有点类似于利用坐标系,用行号和列号来定位具体的键盘。即采用逐行或逐列的“扫描”,就可以独处任何位置按键的状态。

什么是扫描呢?

在这里插入图片描述

1.1.2 矩阵键盘原理

矩阵键盘的原理图有下图所示,左边是独立按键的原理图,右边是矩阵键盘的原理图,放在一起比较更容易理解。
在这里插入图片描述

1.1.2.1扫描过程:

独立按键是将四个按键公共的一端都接在GND即低电平上,另一端连接在i/o口上;而独立按键呢,是每一行连接到一个公共的i/o上,每一列也连接到一个公共的i/o口上;
我们可以假设,矩阵按键第一行的一端都接在GND上,另一端接四列的i/o口,那么此时就变成和独立按键一模一样,如下图所示:
在这里插入图片描述
此时就成了按行扫描的过程,因为一端已经接了GND即低电平,那么此时如果检测到P13=0,说明是S1按下了;如果是P12=0,说明是S2按下了;如果是P11=0,说明是S3按下了;如果是P10=0,说明是S4按下了;此时第一行就扫描结束了,同时也得到了S1-S4 4个按键的状态。

如果想知道为什么公共端设置为0,然后检测另一端是否为0,来判断是否按下按键,请看第1.1.2.2节的介绍。

然后就可以判断第二行了,判断第二行时,将第一行的公共端(也就是P17口)设置为1;第二行的公共端(也就是P16口)设置为0;第三行的公共端(也就是P15)设置为1;第四行的公共端(也就是P14)设置为1;总结一下就是扫描哪一行,哪一行的公共端给0,其他行的公共端给1;然后判断P13-P10的值,如果P13=0,说明是S5按下了;如果是P12=0,说明是S6按下了;如果是P11=0,说明是S7按下了;如果是P10=0,说明是S8按下了;此时第二行就扫描结束了,同时也得到了S5-S8 4个按键的状态。如下图:
在这里插入图片描述
同理,如果扫描第三行时,将第一行的公共端(也就是P17口)设置为1;第二行的公共端(也就是P16口)设置为1;第三行的公共端(也就是P15)设置为0;第四行的公共端(也就是P14)设置为1;总结一下就是扫描哪一行,哪一行的公共端给0,其他行的公共端给1;然后判断P13-P10的值,如果P13=0,说明是S9按下了;如果是P12=0,说明是S10按下了;如果是P11=0,说明是S11按下了;如果是P10=0,说明是S12按下了;此时第三行就扫描结束了,同时也得到了S9-S11 4个按键的状态。如下图:
在这里插入图片描述

第四行同理,这四行全都扫描完一遍后,16个按键的状态也就都得到了。

按列扫描也是同样的道理,即将P13-P12口赋值0和1,然后分别读取P17-P14,从而获得16个按键的状态。

由于按行扫描时,P15口会反复的给0和给1,而P15口又连接着蜂鸣器,所以如果按行扫描,就会导致蜂鸣器一直响,且无法关掉,这是由引脚和外设的冲突引起的,无法避免;所以建议使用按列臊面来获得矩阵键盘的状态。

补充一个知识点,为什么在扫描具体的某一行时,要使其公共端赋值为低电平0,另外的三个行的公共端赋值为高电平1呢?这就涉及到了单片机i/o口的弱上拉模式。

1.1.2.2 单片机i/o口弱上拉模式

i/o口的弱上拉模式又叫准双向口(可以去看51单片机入门教程资料\课件及程序源码\相关资料\STC89C52.pdf中的第4.1.1节:准双向口输出配置);i/o口即iniput/output,既可以输入又可以输出。那i/o是如何达到输出和输入呢?

举个例子,如果现在有两个i/o口,A口是高电平1,B口是低电平0,将A和B直接连接在一起,有同学说这不就短路了嘛,确实像是短路,但是没有问题;就是因为单片机是弱上拉模式,即单片机的上拉能力是弱的;也就是说高电平的驱动能力是有限的,而低电平0的驱动能力是很强的,也可以称为弱上拉,强下拉

更加详细的原理解释,请参考视频(https://www.bilibili.com/video/BV1Mb411e7re?p=15&vd_source=e2638d12685eef84cda913d9d67be0a9)的17分30秒

总结下来一句话,弱上拉强下拉就是1弱0强;也就是当低电平0和高电平1同时出现时,表现的是低电平0

在这里插入图片描述
所以这里再解释一遍扫描的原理:
当第一行的公共端(P17)接了低电平0,那么S1的另一端(P13)在上电时默认是高电平1,所以当S1按键未按下时,读取P13的状态得到的是高电平1
;当S1按下时,P17和P13连接在了一起,P17是低电平,而P13在连接的一瞬间,由于弱上拉强下拉原理(1弱0强),P13也就瞬间从高电平1变成了低电平0;所以,当检测到P13是0时,也就说明S1按下了(因为S1不按下,P13检测到的值会是1)。

1.2 本节目标

目标1:读取矩阵键盘每次按下的数值,并将该数值显示在LCD1602上;
例如,当按下第一个矩阵按键S1时,LCD1602显示01;当按下第二个矩阵按键S2时,LCD1602显示02;依次类推,如下图所示:
当按下S1时:
在这里插入图片描述
当按下S2时:
在这里插入图片描述
依次类推。

目标2:利用矩阵键盘实现密码锁

密码锁具体的过程如下,当上电后,该密码锁在LCD1602上显示初始值Password:0000,
在这里插入图片描述

然后当我们按下S1按键时,显示数字1,如下:
在这里插入图片描述
接着我们按下S2时,显示数字2,如下:
在这里插入图片描述
接着我们按下S3,显示数字3,如下:
在这里插入图片描述
最后我们按下S4,显示数字4,如下:
在这里插入图片描述
最终的结果是我们输入了密码1234,(说明:S1-S9对应着数字1-9,S10表示数字0,S11表示“确认”,S12表示取消),然后按下S11确认,结果显示ERR,表示密码错误,并将数字清零,如下:
在这里插入图片描述
因为我们设置的正确密码是2345,所以输入2345后,结果显示OK,表示密码正确,如下:

在这里插入图片描述

二、读取并显示矩阵键盘按键

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\6-1 矩阵键盘
具体代码:

#include <REGX52.H>
#include "Delay.h"		//包含Delay头文件
#include "LCD1602.h"	//包含LCD1602头文件
#include "MatrixKey.h"	//包含矩阵键盘头文件

unsigned char KeyNum;

void main()
{
	LCD_Init();							//LCD初始化
	LCD_ShowString(1,1,"MatrixKey:");	//LCD显示字符串
	while(1)
	{
		KeyNum=MatrixKey();				//获取矩阵键盘键码
		if(KeyNum)						//如果有按键按下
		{
			LCD_ShowNum(2,1,KeyNum,2);	//LCD显示键码
		}
	}
}

代码解释:

该代码中包含的Delay.hLCD1602.h分别用于延时以及LCD1602的显示,在前面已经进行详细的介绍。

MatrixKey.h是矩阵键盘头文件,里面包含了MatrixKey接口,具体代码如下:

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif

MatrixKey接口的实现在MatrixKey.c文件中,如下:

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

/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下按键的键码值
			如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
			整个函数实现的过程就是对16个矩阵按键扫描了一遍
  */
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;
}

该接口其实现的功能就是将矩阵键盘的16个按键扫描了一遍,返回按下的按键的键码;

最终实现的结果就是按下某个按键,其表示的键码会显示在LCD1602上,即本节的目标1.

三、矩阵键盘密码锁

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\6-2 矩阵键盘密码锁

具体代码:

#include <REGX52.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==2345)	//如果密码等于正确密码
				{
					LCD_ShowString(1,14,"OK ");	//显示OK
					Password=0;		//密码清零
					Count=0;		//计次清零
					LCD_ShowNum(2,1,Password,4);	//更新显示
				}
				else				//否则
				{
					LCD_ShowString(1,14,"ERR");	//显示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);	//更新显示
			}
		}
	}
}

最终实现的结果就是本节的目标2。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/484315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

几种常见时间复杂度实例分析

多项式量级 常量阶 O(1) 对数阶 O(logn) 线性阶 O(n) 线性对数阶 O(nlogn) 平方阶O(n2 ),立方阶O(n3 )...k次方阶O(nk) 非多项式量级&#xff08;NP&#xff08;Non-Deterministic Polynomial&#xff0c;非确定多项式&#xff09;问题&#xff09; 指数阶O(2n) 阶乘阶…

离线数据同步Sqoop与DataX

文章目录 一、Sqoop安装与使用1、简介2、Sqoop安装3、Sqoop实例3.1 Mysql导入Hadoop3.2 Hadoop导出到Mysql 二、DataX概述与入门1、DataX概述1.1 简介1.2 框架设计1.3 运行原理 2、DataX与 Sqoop 的对比3、快速入门 三、DataX常用入门案例1、从stream 流读取数据并打印到控制台…

前端web3入门脚本六:套利夹子机器人,羊毛党必备

一、前言 DEX上有很多零风险套利的机会&#xff0c;包括三角套利&#xff0c;夹子机器人… 今天主要介绍一下架子机器人的思路和简易实现。 二、实现思路 套利原理&#xff1a; 夹子机器人的核心&#xff1a;在韭菜买入前以更低价格买入&#xff0c;并再韭菜买入后卖出&#…

Curator中的分布式锁解读

目录 基本介绍 基本配置 可重入锁InterProcessMutex 不可重入锁InterProcessSemaphoreMutex 可重入读写锁InterProcessReadWriteLock 联锁InterProcessMultiLock 信号量InterProcessSemaphoreV2 栅栏barrier 倒计数器 基本介绍 Curator是netflix公司开源的一套zookeeper…

C语言力扣简单题-无重复字符的最长子串

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 无重复字符的最长子串 题目&#xff1a; 代码思路&#xff1a; 代码表示&#xff1a; 无重复字符的最长子…

【C++】lambda表达式

文章目录 lambda表达式lambda概念lambda表达式的格式关于捕获列表常见问题: 使用lambda表达式交换两个数lambda表达式底层原理 lambda表达式 lambda概念 lambda表达式本质是一个匿名函数(因为它没有名字),恰当使用lambda表达式可以让代码变得简洁.并且可以提高代码的可读性 例…

ChatGPT实现HTML网页文本提取

网页自动化工具 既然ChatGPT对于编程语言有非常强大的理解能力&#xff0c;那么它是否可以用来自动化地处理网页呢&#xff1f;答案是肯定的。ChatGPT可以使用机器学习算法来识别网页元素中的文本&#xff0c;并抽取出有用的信息。 例如我们提供一段层数比较多的相对来说较为…

【五一创作】|【C++】AVL树的实现

文章目录 1.AVL树概念2. AVL树性质3.AVL树的实现insert插入情况分析更新平衡因子旋转处理左单旋右单旋在insert中判断左右单旋的条件双旋转左右双旋 整体代码 1.AVL树概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#…

PCIe数据链路层图文详细总结-PCIe专题知识(二)

目录 前言一、简介1.1 接收部件组成1.2 发送部件组成 二、数据链路层功能详细介绍2.1 DLLP介绍2.2 ACK/NAK协议2.3 发送端逻辑2.3.1 发送端TLP包处理总流程2.3.2 使用ACK/NAK协议详解 2.4 接收端逻辑2.4.1 接收端TLP包处理流程2.4.2 如何使用ACK/NAK协议 2.5 数据链路层发送报文…

Java每日一练(20230503)

1. 外观数列 给定一个正整数 n &#xff0c;输出外观数列的第 n 项。 「外观数列」是一个整数序列&#xff0c;从数字 1 开始&#xff0c;序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列&#xff1a; countAndSay(1) "1"c…

[AION]我眼中的《永恒之塔私服》

当我第一次看到《永恒之塔私服》我被它那华丽的画面吸引了。      三维做的很逼真&#xff0c;他的三维技术&#xff0c;华丽的三维景象&#xff0c;从maya设计者专业的角度上说&#xff0c;他是一部做工完美的游戏&#xff0c;不管是他的背景还是他的人物。都比以前很多游…

Python每日一练(20230503)

目录 1. 外观数列 &#x1f31f;&#x1f31f; 2. 找出素数对 ※ 3. 子集 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 外观数列 给定一个正整数 n…

Dockercompose编排

目录 一、Dockercompose简介 1、compose概述 2、YAML简介 1、概述 2、YAML支持的数据结构 二、compose部署 1、Docker compose环境安装 Docker compose常用字段 Docker compose常用命令 Docker Compose文件结构 2、准备依赖文件 3、编写配置文件docker-compose.yml…

fps枪械案例

文章目录 一、 介绍二、 知识点三、 鼠标移动控制视角四、 人物行走、奔跑、跳跃、下蹲、音效五、 射击、射速、瞄准、弹痕、枪火、弹壳、文本六、 手臂摇摆七、 步枪切换到手枪八、 切枪效果九、 添加各种动画 一、 介绍 经典fps案例 行走、奔跑、跳跃、切枪、换弹、武器展示…

gitlab搭建以及自动化部署

一、安装gitlab 首先下载gitlab的安装包&#xff0c;地址如下&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/bionic/main/g/gitlab-ce/ 然后安装下载的包即可&#xff0c;一般还需要安装openssh-server等依赖包&#xff0c;在安装gitlab包之前可以…

正则表达式-基本元字符和语法规则

© Ptw-cwl 文章目录 字符匹配元字符.元字符[]元字符[^]元字符*元字符元字符?元字符{}元字符|元字符()元字符^元字符$元字符\元字符\d元字符\w元字符\s元字符\b元字符\B元字符*?、?、??、{n,m}?元字符(?)、(?!)元字符(?:)元字符\1、\2等元字符^、$元字符&#x…

【刷题之路Ⅱ】LeetCode 274275. H指数ⅠⅡ

【刷题之路Ⅱ】LeetCode 274&275. H指数Ⅰ&Ⅱ 一、题目描述二、解题1、方法1——排序1.1、思路分析1.2、代码实现1.3、升级到275题的二分法1.3.1、思路分析1.3.2、代码实现 2、方法2——计数排序2.1、思路分析2.2、代码实现 一、题目描述 原题连接&#xff1a; 274. H…

C语言专升本编程题复习

1.求100以内的素数 int main( ) { int i,j,count0;for(i1;i<100;i){for(j2;j<i;j){if(i%j0)break;}if(ij){count; printf("%d ",i);if(count%50)printf("\n");}} }2.求1000以内的完数 * 完数&#xff1a;等于其因子&#xff08;不含本身&…

【五一创作】SAP入门到放弃系列之批次确定配置

概念&#xff1a; 在后勤涉及物料移动或消耗流程中&#xff0c;从采购到生产到销售&#xff0c;涉及启用批次的物料&#xff0c;需要一次又一次地为出入库业务中的库存指定批次。如果企业的出库库批次管理有一定的管理要求&#xff0c;比如先进先出&#xff0c;就可以针对货物…

基于Java语言开发B/S架构实现的云HIS

一、云HIS系统框架简介 1、技术框架 &#xff08;1&#xff09;总体框架&#xff1a; SaaS应用&#xff0c;全浏览器访问 前后端分离&#xff0c;多服务协同 服务可拆分&#xff0c;功能易扩展 &#xff08;2&#xff09;技术细节&#xff1a; 前端&#xff1a;AngularNg…