【51 单片机】矩阵键盘
Hello,大家好我是泽 En,一起共同学习,多多指教(●'◡'●)
矩阵键盘介绍
在键盘中按键数量较多时,为了减少 I/O 口的占用,通常将按键排列成矩阵形式。
采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。
结构:在键盘中按键数量较多时,为了减少 I/O 口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如 P1 口)就可以构成 4*4=16 个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成 20 键的键盘,而直接用端口线则只能多出一键(⑨键) 由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。
扫描的概念
管扫描(输出扫描)
原理:显示第 1 位→显示第 2 位→显示第 3 位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果。因为它的扫描速度是非常快的,根据人的肉眼现象,你所看到的扫描都是同时进行显示的。这就是少量 IO 口,连接到矩阵减少 IO 口的一个目的。
矩阵键盘扫描(输入扫描)
原理:读取第 1 行(列)→读取第 2 行(列) →读取第 3 行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果。原理:跟数码管是极其相像的,扫描的过程其实是由电脑的显卡来进行扫描的这个是一个其它的一个知识点。其实对于显示器来说这个扫描的概念是非常广泛的,因为这个像素点是非常多的几乎所有的显示器都会采用矩阵来进行扫描的。
以上两种扫描方式的共性:节省 I/O 口😶
矩阵键盘原理图
如何用单片机去扫描这个按键从而去获取键码🤔
独立按键和矩阵按键的相同之处
独立按键它是把按键的公共的一端全部连接在了低电平上,然后另一端连接到了 IO 口上。
矩阵按键它是我们把①行④个单独的去拿出来看一下(S1、S2、S3、S4)这一行它的公共端它如果说把它连接到 GND (P17~P14) 如果不要了的话。会发现这个矩阵键盘其实就是和我们说的独立按键是一模一样的!
扫描矩阵键盘的第一步:如果说是按行那么就把第一个接到 GND 上,然后用④个 if 分别进行判断 (P13~P10) if(P13==0) 那么就证明 S1 是按下的。同理:if(P12==0)的话那么就是 S2 是按下的!那么后面两个也是同样的!第一行就可以完美的解决了。
判断第二行的话,我们只需要把第一行给 1,第二行给 0,第三行给 1,第四行给 1。就可以了。因为如果给 1 的话,你的另一端无论按不按下它都是 1 。这个时候 if(P13==0) 的话那么就是 S5 按下了,同理。如果 if(P12==0)的话就是 S6 按下了。
那么判断第三行以及第四行的话都是跟上面所讲述一样,这里不多描述了!
以上是 逐行扫描 的内容!!!但是这个开发板 这样会 出现问题: 说明一下这个开发板!不是这个矩阵键盘和知识点的一个问题。这是它内部电路的连接问题 按行扫描的话这个 P15 口的话可能会一会给高电平或者低电平。(会连接到五线四相步进电机然后 BZ 连接到蜂鸣器上,因为我们这个蜂鸣器它是无源蜂鸣器,所以当你按行扫描的时候它有可能就会发出声音)
所以建议采用 逐列扫描!
同理!给下面④(P13、P12、P11、P10)个进行赋值。读取上面的④个(P17~P14)
比如说我们要扫描 第一列的话:把 P13 赋值为 (0 低电平) 其它全部给 (1 高电平)那么这一行都可以进行按键扫描了,如果要按 S1 的话 if(P17 == 0) 的话就是 S1 按下了,那么如果 if(P16 == 0) 的话那么就是 S2 按下了,同理~ 。那么第二列也是一样只需要给:P12 赋值为低电平,其它给上高点平~~~
单片机 IO 口的模式
机的 io 口是一种弱上拉的模式~!又被称作是准双向口(input,output) 既可以输入又可以输出,这种就叫做是双向口。但是这种双向口有点问题:这么样才可以达到输入或者是输出呢 ?像我们这种矩阵键盘的话是不是给上,一端是 0,然后读取另一头。但是另一头你怎么知道它是一种输入(高电平)呢?它其实也是作为一种输出端(低电平)它既是输出(低电平)也是输入(高电平),那么为什么单片机它的 io 口是默认为高电平呢?是因为它里面拥有一个上拉电阻把低电平变成高电平了 !所以才导致单片机是高电平,还有一个是当口线输出为 1 的时候驱动能力很弱,允许外部装置将其拉低。当引脚的输出为低电平的时候,它的驱动能力很强,可以吸收相当大的电流。 单片机中 P1、P2、P3 都是一种弱上拉的一种模式。
准双向口输出如下所示:
提高代码的效率
这样可以固定代码,可以提高自己打代码的一个效率!
代码实现矩阵按键显示对应数字
main.c
我们需要运用到这个矩阵键盘,所以要在 MatrixKey.h 当中去进行声明,记得在那个文件加上分号去进行声明,然后在 main.c 的头文件去进行引用!
再把返回值接到我们所创建的全局变量赋值到 KeyNum 当中去。
这里 if 语句当中表达式其实就是如果 KeyNum 不是为 0 的话就执行非 0 即为真执行下面内容。
Delay.c
Delay.h
LCD1602.c
LCD1602.h
MatrixKey.c
注意:在上次的代码当中是没有返回值,但是有参数的。而这次是有返回值且无参数的自定义函数。我们在 main 函数当中也要定义一个变量来去接收这个返回值💬,我们这里定义的返回值变量是在局部变量所定义的,然后进行 return 返回到自定义函数当中,要不然它就可能不是初始值了!
P1 这些东西都是在 REGX52.H 这个头文件里面,这是在头文件当中定义之中才可以去使用的,不然是不能进行使用的。
MatrixKey.h
矩阵按键密码
其它的和上面的一样就是源文件进行改变!
main.c
版权声明: 本文为 InfoQ 作者【泽En】的原创文章。
原文链接:【http://xie.infoq.cn/article/f0925af067e5e7706a3c7157a】。文章转载请联系作者。
评论