单片机编辑库四之矩阵按键

article/2025/1/17 6:16:25

单片机编辑库一之延时与led灯
单片机编辑库二之按键
单片机编辑库三之蜂鸣器

单片机编辑库四之矩阵按键

之前为大家介绍了独立按键的原理和使用方法,这一章给大家带来一个升级体验——矩阵按键,话不多说,直接开始今天的内容。

一、矩阵按键的原理

大家常见的矩阵键盘一般是4x4的矩阵键盘,这种资料网上非常多,大家可不懂的可自行查阅,我给大家以较为通俗的语言介绍一下矩阵键盘的使用,我在这次的例程中采用了两种方式的矩阵键盘,一种是常见的4x4,一种是2x3的键盘:
4x4矩阵键盘:
在这里插入图片描述
2x3矩阵键盘:
在这里插入图片描述
对于矩阵键盘中按下按键的检验通常是采用行扫描和列扫描的方式,检测方法与独立按键类似;

行检测:

令每一列的按键引脚为低电平,即使对应的引脚为0,每一行的按键引脚为高电平,即使对应的引脚为1,,这样当有按键被按下时,就可以通过检验每一行按键引脚的电平是否为低电平即可。
例如,对于2x3的矩阵键盘,令p2.2,p2.3,p2.4为低电平(0),令p2.0,p2.1为高电平(1),当第一排任意一个按键被按下,p2.0都会为0,此时系统就能检测到第一排的按键被按下;想通的,若是第二排任意一个按键被按下,p2.1都会为0,此时系统就能检测到第二排的按键被按下。

列检测:

列检测与行检测相似,即令每一行的按键引脚为低电平,即使对应的引脚为0,每一列的按键引脚为高电平,即使对应的引脚为1,,这样当有按键被按下时,就可以通过检验每一列按键引脚的电平是否为低电平即可。
例如,对于2x3的矩阵键盘,令p2.0,p2.1为低电平(0),令p2.2,p2.3,p2.4为高电平(1),当第一列任意一个按键被按下,p2.2都会为0,此时系统就能检测到第一列的按键被按下;想同的,若是第二排任意一个按键被按下,p2.3都会为0,此时系统就能检测到第二列的按键被按下;第三列依旧如此获取。

当行检测与列检测都完成之后,我们就可以获取按键的坐标,通过按键的坐标系统就能完成相应按键的功能,我的坐标方法是 获取坐标值=获取行*10+获取列,这样获取的坐标十位就是按键按下的行,个位就是按键按下的列,代码如下:

void rank_key_scan()
{Rank_KeyValue=0;//每次进入重新赋值为0,防止按键值停留在上一次按下的情况row1=row2=1;						list1=list2=list3=0;		//先令行为1,确定行号if(row1!=1||row2!=1)//如果电位不是高电平了,则说明有按键按下了{delay_ms(10);//延时10ms进行消抖if(row1==0)//如果是第一行的按键被按下{Rank_KeyValue=1;}else if(row2==0)//如果是第二行的按键被按下{Rank_KeyValue=2;}else{Rank_KeyValue=0;}}row1=row2=0;						list1=list2=list3=1;		//先令列为1,确定列号if(list1!=1||list2!=1||list3!=1)//如果电位不是高电平了,则说明有按键按下了{delay_ms(10);//延时10ms进行消抖if(list1==0)//如果是第一行被按下{Rank_KeyValue=Rank_KeyValue*10+1;}else if(list2==0){Rank_KeyValue=Rank_KeyValue*10+2;}else if(list3==0){Rank_KeyValue=Rank_KeyValue*10+3;}}while(list1!=1||list2!=1||list3!=1);//等待按键被松开
}

这是对于2x3的键盘而言,而对于4x4的矩阵键盘则要方便的多,4x4的按键正好用到8个引脚,可以对应51单片机的一个端口,因此,至于要代码就会简介很多:

void rank_key_scan()
{Rank_KeyValue=0;//每次进入重新赋值为0,防止按键值停留在上一次按下的情况GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//读取按键是否按下{delay_ms(10);//延时10ms进行消抖if(GPIO_KEY!=0x0f)//再次检测键盘是否按下{	//测试行GPIO_KEY=0X0F;switch(GPIO_KEY){case(0X0e):	Rank_KeyValue=1;break;case(0X0d):	Rank_KeyValue=2;break;case(0X0b): Rank_KeyValue=3;break;case(0X07):	Rank_KeyValue=4;break;}//测试列GPIO_KEY=0XF0;switch(GPIO_KEY){case(0Xe0):	Rank_KeyValue=Rank_KeyValue*10+1;break;case(0Xd0):	Rank_KeyValue=Rank_KeyValue*10+2;break;case(0Xb0): Rank_KeyValue=Rank_KeyValue*10+3;break;case(0X70):	Rank_KeyValue=Rank_KeyValue*10+4;break;}while(GPIO_KEY!=0xf0);	 //检测按键松手检测}}
}

二、功能设定

对于举证按键所实现的功能,为了方便观察,我还是采用控制 led灯的方法,系统检测我所按下的按键坐标,然后点亮相应的 led灯,比如,我按下的按键坐标是(1,1),系统就点亮p0.0上的led灯,坐标是(2,2)则点亮p0.1上的 led灯,示例中我只用到了4个按键,即对角线上的4个按键,大家使用时可自行添加功能。

仿真图

在这里插入图片描述
处理函数:

void handele_rank_key()//按键处理函数
{rank_key_scan();//按键扫描函数在此处调用if(Rank_KeyValue!=0)//如果有按键按下{switch(Rank_KeyValue){case 11://第一行第一列P0=0x01;break;case 22://第二行第二列P0=0x02;break;case 23://第二行第三列P0=0x03;break;case 33://第三行第三列P0=0x04;break;case 32://第三行第二列P0=0x05;break;case 44://第四行第四列P0=0x00;break;default:break;}}
}

例程四:矩阵按键

完整的相应功能代码如下:
rankkey.h:

#ifndef _RANKEY_H
#define _RANKEY_H#include "reg52.h"#define GPIO_KEY P1  	//定义整个P1(从P1.0到P1.7)端口作为矩阵按键口/**单独定义行*****/
sbit row1=P2^0;				//定义P2.0为矩阵按键的第一行
sbit row2=P2^1;				//定义P2.1为矩阵按键的第二行
/****************//**单独定义行*****/
sbit list1=P2^2;			//定义P2.2为矩阵按键的第一列
sbit list2=P2^3;			//定义P2.3为矩阵按键的第二列
sbit list3=P2^4;			//定义P2.4为矩阵按键的第三列
/****************/extern unsigned int Rank_KeyValue;//定义全局变量,在这里不能进行赋值,需要在其他C文件中重新定义赋值void rank_key_scan();//矩阵按键扫描函数#endif

rankey.c:

#include "rankey.h"
#include "delay.h"//延时函数头文件unsigned int Rank_KeyValue=0;//重新定义全局变量并赋值void rank_key_scan()
{Rank_KeyValue=0;//每次进入重新赋值为0,防止按键值停留在上一次按下的情况/********采用整个对端口定义的方式:			*/GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//读取按键是否按下{delay_ms(10);//延时10ms进行消抖if(GPIO_KEY!=0x0f)//再次检测键盘是否按下{	//测试行GPIO_KEY=0X0F;switch(GPIO_KEY){case(0X0e):	Rank_KeyValue=1;break;case(0X0d):	Rank_KeyValue=2;break;case(0X0b): Rank_KeyValue=3;break;case(0X07):	Rank_KeyValue=4;break;}//测试列GPIO_KEY=0XF0;switch(GPIO_KEY){case(0Xe0):	Rank_KeyValue=Rank_KeyValue*10+1;break;case(0Xd0):	Rank_KeyValue=Rank_KeyValue*10+2;break;case(0Xb0): Rank_KeyValue=Rank_KeyValue*10+3;break;case(0X70):	Rank_KeyValue=Rank_KeyValue*10+4;break;}while(GPIO_KEY!=0xf0);	 //检测按键松手检测}}/************************************//********采用单个端口号定义的方式:			*/row1=row2=1;						list1=list2=list3=0;		//先令行为1,确定行号if(row1!=1||row2!=1)//如果电位不是高电平了,则说明有按键按下了{delay_ms(10);//延时10ms进行消抖if(row1==0)//如果是第一行的按键被按下{Rank_KeyValue=1;}else if(row2==0)//如果是第二行的按键被按下{Rank_KeyValue=2;}else{Rank_KeyValue=0;}}row1=row2=0;						list1=list2=list3=1;		//先令列为1,确定列号if(list1!=1||list2!=1||list3!=1)//如果电位不是高电平了,则说明有按键按下了{delay_ms(10);//延时10ms进行消抖if(list1==0)//如果是第一行被按下{Rank_KeyValue=Rank_KeyValue*10+1;}else if(list2==0){Rank_KeyValue=Rank_KeyValue*10+2;}else if(list3==0){Rank_KeyValue=Rank_KeyValue*10+3;}}while(list1!=1||list2!=1||list3!=1);//等待按键被松开/************************************/}

handle.h:

#ifndef _HANDLE_H
#define _HANDLE_H//为了方便起见,可以把主函数里面包含的头文件全部包含在这里,除了"handle.h"
#include "reg52.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "beep.h"
#include "rankey.h"void handle_Init();//初始化处理函数void handele_led();//led处理函数
void handele_key();//按键处理函数
void handele_rank_key();//矩阵按键处理函数
void handele_beep();//蜂鸣器处理函数#endif

handle.c:

/*该函数用于处理所有需要实现的功能函数,目的是减少在主函数中程序显得杂乱
*/
#include "handle.h"void handle_Init()//初始化处理函数
{P1=0x00;led_init();//初始化LED系统beep_init();//蜂鸣器初始化
}void handele_led()//led处理函数
{water_Lamp();
}void handele_beep()//蜂鸣器处理函数
{beep_work();
}void handele_key()//按键处理函数
{key_scan();//按键扫描函数在此处调用if(KeyValue!=0)//如果有按键按下{switch(KeyValue){case 1://如果按下的是按键1,点亮ledlamp_flag=1;led_on();delay_ms(100);break;case 2://如果按下的是按键2,熄灭ledled_off();break;case 3://如果按下的是按键3,熄灭蜂鸣器鸣叫handele_beep();break;default:break;}}
}void handele_rank_key()//按键处理函数
{rank_key_scan();//按键扫描函数在此处调用if(Rank_KeyValue!=0)//如果有按键按下{switch(Rank_KeyValue){case 11://第一行第一列P0=0x01;break;case 22://第二行第二列P0=0x02;break;case 23://第二行第三列P0=0x03;break;case 33://第三行第三列P0=0x04;break;case 32://第三行第二列P0=0x05;break;case 44://第四行第四列P0=0x00;break;default:break;}}
}

主程序:
main.c:

#include "reg52.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "beep.h"
#include "rankey.h"#include "handle.h"void main()
{handle_Init();//调用初始化处理函数while(1){handele_led();//调用led处理函数handele_key();//调用按键处理函数handele_rank_key();//矩阵按键处理函数}
}

矩阵按键程序框架

在这里插入图片描述

仿真演示

在这里插入图片描述

程序下载

程序传送门


http://chatgpt.dhexx.cn/article/2tDsoSOx.shtml

相关文章

51单片机——矩阵按键实验,小白讲解,相互学习

矩阵按键介绍: 独立按键与单片机连接时,每一个按键都需要单片机的一个I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O 口资源.单片机系统中I/O 口资源往往比较宝贵,当用到多个按键时为了减少I/O 口…

STM32----矩阵按键

一、实物图 二、开发流程 分析:对于矩阵按键,我们一般采用行列扫描反转的方法进行开发,分别把每一个引脚连接一个GPIO口并设置一半成通用推挽输出模式,一半为上拉输入模式,行列扫描反转进行判断按击的按键来判断行列从…

(五)矩阵按键

本章我们主要是写矩阵键盘的内容,矩阵键盘的原理和独立按键的按键原理基本是类似的,只是关于整个的原理还是要有些介绍,本章我们通过矩阵按键的某个按键按下,然后在数码管上输出对应的按键值。 1.关于按键 可以看前面按键的内容…

【STM32 基础实验矩阵按键】

文章目录 一、元器件矩阵键盘说明二、基于stm32f10c8t6 基础实验矩阵按键(1)实验功能实现说明(2)矩阵键盘原理(3)代码部分(4)效果展示 三、总结与扩展附上参考文献链接与视频链接出处…

51单片机入门——矩阵按键

文章目录 1.按键1.1.独立按键1.2.矩阵按键 2.按键的扫描与抖动2.1.独立按键的扫描2.2.按键抖动与消抖2.3.矩阵按键的扫描 3.简易计算器 1.按键 1.1.独立按键 常用的按键电路有两种形式,独立式按键和矩阵式按键,独立式按键比较简单,它们各自…

mac怎么给移动硬盘分区

我们经常用Windows系统给移动硬盘分区,对于Windows系统的操作我们是非常熟悉的,但是现在很多人都在使用苹果电脑,那么如何用Mac给硬盘分区呢?这个可是需要技术的。如果我们不会用Mac系统给移动硬盘分区,当我们在Mac上插…

ntfs格式的移动硬盘如何在mac电脑写入?

随着照片视频等技术的进步,这类文件越发清晰的同时,占用内存也越来越大,人们逐渐将其中不常用到的存入移动硬盘中,以此减少电脑空间占用。目前国内大多数移动硬盘均为Windows自研的NTFS格式,对于这类NTFS格式的移动硬盘…

mac怎么删除硬盘里面的东西?为什么苹果电脑无法删除移动硬盘文件?

mac怎么删除硬盘里面的东西?由于移动硬盘的文件系统是NTFS格式的,而这种格式与Mac电脑是不兼容的,Mac电脑没有权限对移动硬盘上的数据进行操作,Mac上不能把移动硬盘的数据删除了,那么,有没有什么操作方法&a…

苹果电脑怎么用移动硬盘ntfs?快速读取和编辑Mac外置移动硬盘

苹果电脑怎么用移动硬盘ntfs?如果你对电脑比较熟悉的话,可能知道NTFS磁盘格式。该格式专门为Windows系统设计的,也称为Windows NT文件系统。从Windows系统迁移到Mac可能是一项相当困难的任务,因为NTFS格式的硬盘在Mac上不能正常工…

如何在Mac上给移动硬盘加密

随着人们的安全意识越来越强,手机加密、Wi-Fi加密,甚至平时工作的U盘、移动硬盘也要加密。在Mac上对移动硬盘加密并不是很难,通过磁盘工具对硬盘进行格式化处理,并重新选择磁盘格式便可实现加密。下面就让我们来看具体的操作吧&am…

mac无法在移动硬盘上新建文件夹 mac如何在移动硬盘新建文件夹

明明是新买的硬盘,为什么把移动硬盘插入Mac后,Mac无法在移动硬盘上新建文件夹呢?相信很多Mac用户都曾遇到过Mac无法在移动硬盘上新建文件夹的问题。为什么会出现这样的问题呢?用户应该怎么解决呢?本文就来为大家介绍ma…

Mac无法写入移动硬盘 这些软件帮你解决

疫情期间因工作需要,从淘宝上买了一个移动硬盘,将公司的文件拷贝到这个移动硬盘上,并没有发现什么问题,一拿回到家里就懵圈了,突然发现里面的文件都无法进行修改或剪切粘贴。 一番百度之后,我找到了原因&a…

Mac如何拷贝文件到移动硬盘

haha~ 看到这个标题不要以为博主这是傻了: “切, 往移动硬盘拷文件谁不会啊~”, “又在故弄玄虚, 就这也写博客~” … 确实, 我要把这个写成博客了. 因为今天要拷贝MacOS Sierra安装包到另外一台电脑上, 安装包有4.7个G, U盘果断不行, 于是换上移动硬盘, 连上电脑, 将安装包拖入…

Mac下如何把iphone资料备份到移动硬盘

一般的备份方法 首先新系统的iphone备份已经转到了访达 连接iphone后在访达左边栏会看到你的手机 在终端输入下面这段命令行 ln -s /Volumes/Data/ios_backup ~/Library/Application\ Support/MobileSync/Backup /Volumes/Data/ios_backup 这行是你想要指定的目…

怎样将iphone照片通过MAC导入移动硬盘?

iMazing是一款第三方的苹果iOS设备管理软件,大家使用数据线或Wi-Fi将苹果设备与电脑进行连接以后,就可以用它进行音乐传输、照片传输和数据备份等操作。 它支持Windows系统和Mac系统,下面通过一篇教程,教大家如何通过Mac系统的iM…

mac怎么用ntfs硬盘 NTFS移动硬盘怎么在mac上使用

品牌型号:MacBook Air 系统:macOS 10.13 软件版本:Tuxera Ntfs for mac 2020 初次接触到Mac电脑的用户,会发现自己的移动硬盘或U盘连接到电脑后仅有只读权限,并不能对其写入数据。这和移动硬盘格式有着密切的关系,NTFS格式在Mac电脑上并不…

mac不识别移动硬盘导致无法拷贝资源

背景 硬盘插入到Mac电脑上之后,mac不识别移动硬盘导致无法拷贝资源。 移动硬盘在Mac上无法被识别的原因可能有很多,多数情况下,是硬盘的格式与Mac电脑不兼容。 文件系统格式不兼容 macOS使用的文件系统是HFS或APFS,如果移动硬盘是…

Mac不能复制拷贝写入文件到移动硬盘/U盘解决办法

1.有的小伙伴把移动硬盘或 U 盘接入到 Mac 电脑上,当把文件拷贝到移动硬盘时,会发现不能复制文件到移动硬盘。这里因为移动硬盘或 U 盘是使用 Windows 系统下的 NTFS 分区格式,而 Mac 系统原生是不支持这种格式的,也就是为什么不能…

windows移动硬盘接到mac上使用(加载ntfs移动硬盘)

也就是将NTFS格式的移动硬盘,连接到mac上进行存储。 目录 步骤如下:1、接入硬盘,查看Device Node2、推出硬盘,一般桌面就有对应图标,右键推出就行3、建个目录,然后把硬盘挂上去就行4、解挂载硬盘 步骤如下…

ntfs硬盘如何在mac上读写移动硬盘文件?

在日常的工作中,总是避免不了跨平台的传输文件、文件共享等,例如一些用户使用Mac电脑修图或者剪辑视频之后需要拷贝到Windows电脑上查看。对于需要同时使用Mac和Windows的用户来说,系统之间不兼容是很大的阻碍,尤其是使用NTFS移动…