草庐IT

51单片机-6-矩阵键盘

胜天半颗子 2024-02-08 原文

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和0,S11代表确认键,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 ");		//显示OK,OK后面细节加了一个空格,主要是为了在输错密码显示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);	//更新显示		
			}
			
		}		
	}
}

有关51单片机-6-矩阵键盘的更多相关文章

  1. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  2. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  3. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  4. 华为OD机试真题 C++ 实现【带传送阵的矩阵游离】【2023 Q2 | 200分】 - 2

            所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。

  5. 欧拉角表示的姿态矩阵(313和312转序) - 2

    一、习惯约定图片来自PSINS(高精度捷联惯导算法)PSINS工具箱入门与详解.pptx二、基本旋转矩阵绕x轴逆时钟旋转α\alphaα角度Rx(α)=[ 1000cos⁡αsin⁡α0−sin⁡αcos⁡α]R_x(\alpha)=\begin{bmatrix}\1&0&0\\0&\cos\alpha&\sin\alpha\\0&-\sin\alpha&\cos\alpha\end{bmatrix}Rx​(α)=​ 100​0cosα−sinα​0sinαcosα​​绕y轴逆时钟旋转α\alphaα角度Ry(α)=[ cos⁡α0−sin⁡α010sin⁡α0cos⁡α]R_y(\alpha

  6. 欧拉角、旋转矩阵及四元数 - 2

    欧拉角、旋转矩阵及四元数1.简介2.欧拉角2.1欧拉角定义2.2右手系和左手系2.3转换流程3.旋转矩阵4.四元数4.1四元数与欧拉角和旋转矩阵之间等效变换4.2测试Matlab代码5.总结1.简介常用姿态参数表达方式包括方向余弦矩阵、欧拉轴/角参数、欧拉角、四元数以及罗德里格参数等。高分辨率光学遥感卫星主要采用欧拉角与四元数对姿态参数进行描述。这里着重讲解欧拉角、旋转矩阵和四元数。2.欧拉角2.1欧拉角定义欧拉角是表征刚体旋转的一种方法之一,由莱昂哈德·欧拉引入的三个角度,用于描述刚体相对于固定坐标系的方向。在摄影测量、空间科学或其它技术领域,一般用一组(三个)欧拉角描述两个空间坐标之间的旋

  7. micropython复现经典单片机项目(二)可视化音频 频谱解析(基本搞定) - 2

    本人是音乐爱好者,从小就特别喜欢那个随着音乐跳动的方框效果,就是这个:arduino上一大把对,我忍你很久了,我就想用mpy做,全网没有,行我自己研究。果然兴趣是最好的老师,我之前有篇博客专门讲音频,有兴趣的可以回顾一下。提到可视化频谱,必然绕不开fft,大学学过这玩意,当时一心玩,老师讲的一个字都么听进去,网上教程简略扫了一下,大该就是把时域转频域的工具,我大mpy居然没有fft函数,奶奶的,先放着。音频信息如何收集?第一种傻瓜式的ADC,模拟转数字,原始粗暴,第二种,I2S库,我之前博客有讲过,数据是PCM编码。然后又去学PCM编码,一学豁然开朗,舒服,以代码为例:audio_in=I2S

  8. ruby - 如何修改矩阵(Ruby std-lib Matrix 类)? - 2

    我理解RubystdlibMatrix是不可修改的,也就是说,例如。m=Matrix.zero(3,4)不会写m[0,1]=7但我非常想做...我可以用笨拙的编程来做,比如defmodify_value_in_a_matrix(matrix,row,col,newval)ary=(0...m.row_size).map{|i|m.rowi}.map(&:to_a)ary[row][col]=newvalMatrix[*ary]end...或者作弊,比如Matrix.send:[]=,0,1,7但我想知道,这一定是人们一直遇到的问题。有没有一些标准的、习惯的方法可以做到这一点,而不必使用

  9. 线性代数让我想想:快速求三阶矩阵的逆矩阵 - 2

    快速求三阶矩阵的逆矩阵前言一般情况下,我们求解伴随矩阵是要注意符号问题和位置问题的(如下所示)A−1=1[  ][−[  ]−[  ]−[  ]  −[  ]]=A−1=1[  ][   M11−[M12]   M13−[M21]   M22−[M23]     M31−[M32]   M33]⊤\begin{aligned}&A^{-1}=\frac{1}{[\\]}\left[\begin{array}{cccccc}&-[\\]&\\-[\\]&&-[\\]\\\\&-[\\]&\\\end{array}\right]=\\\\&A^{-1}=\frac{1}{[\\]}\left[\b

  10. 相机校准—外参矩阵 - 2

    在本文中,我们将探讨摄影机的外参,并通过Python中的一个实践示例来加强我们的理解。相机外参摄像头可以位于世界任何地方,并且可以指向任何方向。我们想从摄像机的角度来观察世界上的物体,这种从世界坐标系到摄像机坐标系的转换被称为摄像机外参。那么,我们怎样才能找到相机外参呢?一旦我们弄清楚相机是如何变换的,我们就可以找到从世界坐标系到相机坐标系的基变换的变化。我们将详细探讨这个想法。具体来说,我们需要知道相机是如何定位的,以及它在世界空间中的位置,有两种转换可以帮助我们:有助于确定摄影机方向的旋转变换。有助于移动相机的平移变换。让我们详细看看每一个。旋转通过旋转改变坐标让我们看一下将点旋转一个角度

随机推荐