【51单片机】矩阵按键快速上手

news2024/12/16 16:09:28

51单片机矩阵按键是一种在单片机应用系统中广泛使用的按键排列方式,特别适用于需要多个按键但I/O口资源有限的情况。以下是对51单片机矩阵按键的详细介绍:

一、矩阵按键的基本概念

  • 定义‌:矩阵按键,又称行列键盘,是用多条行线和列线交叉组成的键盘。在行线和列线的每个交叉点上设置一个按键,从而实现用较少的I/O口控制多个按键。
  • 优势‌:矩阵按键能够有效地提高单片机系统中I/O口的利用率。例如,一个4x4的矩阵键盘只需8个I/O口就可以实现16个按键的功能。

二、矩阵按键的工作原理

  • 行列扫描法‌:这是最常用的矩阵按键检测方法。首先,单片机通过程序控制将某一列线置为低电平,其余列线置为高电平,然后检测各行线是否有低电平信号。如果有,说明该行线与置为低电平的列线交叉点上的按键被按下。接着,轮流将各列线置为低电平,并检测各行线,直到找出被按下的按键。
  • 线翻转法‌:另一种检测方法是线翻转法。首先,将所有行线置为低电平,检测所有列线是否有低电平信号。如果有,记录列线值。然后,将所有列线置为低电平,检测所有行线的值。由于有按键按下,行线的值也会有变化,记录行线的值。通过这种方法,可以检测到所有被按下的按键。

三、矩阵按键的编程实现

  • 初始化‌:在程序中,首先需要初始化与矩阵键盘连接的I/O口,设置它们的初始状态。
  • 扫描与检测‌:然后,通过循环或中断的方式不断扫描矩阵键盘。在扫描过程中,根据行列扫描法或线翻转法的原理,检测按键是否被按下。
  • 消抖处理‌:由于机械按键在按下和松开时会产生抖动,因此需要在程序中加入消抖处理。常用的消抖方法有软件消抖和硬件消抖。在单片机应用中,软件消抖更为常见。
  • 按键功能实现‌:当检测到按键被按下时,根据按键的位置执行相应的功能。例如,在计算器程序中,按键的位置可能对应不同的数字或运算符。

四、矩阵按键的应用实例

  • 计算器‌:矩阵按键常用于计算器的键盘设计。通过4x4或更大规模的矩阵键盘,可以实现数字输入、运算符选择和功能键等操作。
  • 电子密码锁‌:在电子密码锁中,矩阵按键用于输入密码。用户可以通过按下矩阵键盘上的按键来输入数字或字母密码。
  • 游戏控制器‌:在一些简单的游戏控制器中,矩阵按键也常被用于实现方向键、功能键等操作。

 

 当我们按下某一个按键时,该按键对应的那一行和那一列的引脚为0,其他的引脚为1

硬件原理图

代码实现

 分别检测

#include "Int_MatrixKey.h"
#include <STC89C5xRC.H>

u8 Int_MatrixKey_CheckKey()
{

    //    P24 P25 P26 P27
    // P20 +---+---+---+
    // P21 +---+---+---+
    // P22 +---+---+---+
    // P23 +---+---+---+

    // 扫描第一行,将P20置0,其余置1;P27-P20依次为:1111 1110
    P2 = 0xFE;

    // 检测第SW5是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1110
    if (P2 == 0xEE) {
        Delay1ms(10);
        if (P2 == 0xEE) {
            while (P2 == 0xEE);
            return 5;
        }
    }

    // 检测第SW6是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1110
    if (P2 == 0xDE) {
        Delay1ms(10);
        if (P2 == 0xDE) {
            while (P2 == 0xDE);
            return 6;
        }
    }

    // 检测第SW7是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1110
    if (P2 == 0xBE) {
        Delay1ms(10);
        if (P2 == 0xBE) {
            while (P2 == 0xBE);
            return 7;
        }
    }

    // 检测第SW8是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1110
    if (P2 == 0x7E) {
        Delay1ms(10);
        if (P2 == 0x7E) {
            while (P2 == 0x7E);
            return 8;
        }
    }

    // 扫描第二行,将P22置0,其余置1;P27-P20依次为:1111 1101
    P2 = 0xFD;
    // 检测第SW9是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1101
    if (P2 == 0xED) {
        Delay1ms(10);
        if (P2 == 0xED) {
            while (P2 == 0xED);
            return 9;
        }
    }

    // 检测第SW10是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1101
    if (P2 == 0xDD) {
        Delay1ms(10);
        if (P2 == 0xDD) {
            while (P2 == 0xDD);
            return 10;
        }
    }

    // 检测第SW11是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1101
    if (P2 == 0xBD) {
        Delay1ms(10);
        if (P2 == 0xBD) {
            while (P2 == 0xBD);
            return 11;
        }
    }

    // 检测第SW12是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1101
    if (P2 == 0x7D) {
        Delay1ms(10);
        if (P2 == 0x7D) {
            while (P2 == 0x7D);
            return 12;
        }
    }

    // 扫描第三行,将P22置0,其余置1;P27-P20依次为:1111 1011
    P2 = 0xFB;
    // 检测第SW13是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1011
    if (P2 == 0xEB) {
        Delay1ms(10);
        if (P2 == 0xEB) {
            while (P2 == 0xEB);
            return 13;
        }
    }

    // 检测第SW14是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1011
    if (P2 == 0xDB) {
        Delay1ms(10);
        if (P2 == 0xDB) {
            while (P2 == 0xDB);
            return 14;
        }
    }

    // 检测第SW15是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1011
    if (P2 == 0xBB) {
        Delay1ms(10);
        if (P2 == 0xBB) {
            while (P2 == 0xBB);
            return 15;
        }
    }

    // 检测第SW16是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1011
    if (P2 == 0x7B) {
        Delay1ms(10);
        if (P2 == 0x7B) {
            while (P2 == 0x7B);
            return 16;
        }
    }

    // 扫描第四行,将P23置0,其余置1;P27-P20依次为:1111 0111
    P2 = 0xF7;
    // 检测第SW17是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 0111
    if (P2 == 0xE7) {
        Delay1ms(10);
        if (P2 == 0xE7) {
            while (P2 == 0xE7);
            return 17;
        }
    }

    // 检测第SW18是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 0111
    if (P2 == 0xD7) {
        Delay1ms(10);
        if (P2 == 0xD7) {
            while (P2 == 0xD7);
            return 18;
        }
    }

    // 检测第SW19是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 0111
    if (P2 == 0xB7) {
        Delay1ms(10);
        if (P2 == 0xB7) {
            while (P2 == 0xB7);
            return 18;
        }
    }

    // 检测第SW20是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 0111
    if (P2 == 0x77) {
        Delay1ms(10);
        if (P2 == 0x77) {
            while (P2 == 0x77);
            return 20;
        }
    }

    return 0;
}

循环方式

u8 Int_KeyMatrix_CheckKey()
{
    u8 i, j;
    u8 lines[4]   = {0xFE, 0xFD, 0xFB, 0xF7};
    u8 columns[4] = {0x10, 0x20, 0x40, 0x80};
    for (i = 0; i < 4; i++) {
        P2 = lines[i];
        for (j = 0; j < 4; j++) {
            if ((P2 & columns[j]) == 0x00) {
                Com_Util_Delay1ms(10);
                if ((P2 & columns[j]) == 0x00) {
                    while ((P2 & columns[j]) == 0x00);
                    return 5 + j + 4 * i;
                }
            }
        }
    }
    return 0;
}

通过这个函数就可以获取到每个矩阵对应的数字了

int main(){
    u8 key;
    while(1){
        key = Int_KeyMatrix_CheckKey();
        if(key){
            //对应逻辑
        }
    }
}

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

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

相关文章

clearvoice 语音降噪、语音分离库

参看: https://github.com/modelscope/ClearerVoice-Studio/tree/main ClearVoice 提供了一个统一的推理平台,用于语音增强、语音分离以及视听目标说话人提取。 代码参看: https://github.com/modelscope/ClearerVoice-Studio/tree/main/clearvoice https://github.com/mode…

外观模式的理解和实践

外观模式&#xff08;Facade Pattern&#xff09;是一种常用的软件设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。该模式定义了一个高层的接口&#xff0c;使得子系统更容易使用。简单来说&#xff0c;外观模式就是通过引入一个外观角色…

【Email】基于SpringBoot3.4.x集成发送邮件功能

【Email】基于SpringBoot3.4.x集成发送邮件功能 摘要本地开发环境说明pom.xml启动类application.yaml写一个邮件模板定义模板引擎工具类定义一个邮件发送对象封装一个邮件发送器单元测试邮件模板单元测试发送邮件单元测试 邮件效果参考资料 摘要 在业务系统开发过程中&#xf…

Type-C接口电热毯的创新之旅

在科技日新月异的今天&#xff0c;智能家居产品正逐步渗透到我们生活的每一个角落&#xff0c;从智能灯光到温控系统&#xff0c;无一不展现着科技带来的便捷与舒适。而在这个追求高效与智能化的浪潮中&#xff0c;一款结合了最新科技元素的电热毯——Type-C接口电热毯&#xf…

【从零开始入门unity游戏开发之——C#篇09】if-else条件表达式、三元运算符、switch-case的使用

文章目录 一、if条件表达式1、if 语句基本结构示例输出&#xff1a; 2、else语句示例输出&#xff1a; 3、else if 语句示例输出&#xff1a; 4、组合逻辑运算符示例输出&#xff1a; 5、嵌套 if 语句示例输出&#xff1a;总结 二、三元运算符1、语法&#xff1a;2、示例&#…

CIFAR10 数据集介绍并转化为图片

CIFAR10数据集 CIFAR-10数据集是一个广泛使用的机器学习数据集&#xff0c;它包含10个类别的 60000 张32x32的彩色图像。每个类别有6000张图像&#xff0c;其中50000张用于训练&#xff0c;1000 张用于测试。这些类别包括&#xff1a; 飞机&#xff08;airplane&#xff09;汽车…

我们需要什么样的运维:以业务目标为导向的运维体系建设

在数字化转型的浪潮中&#xff0c;运维作为信息技术基础设施的重要支撑&#xff0c;其重要性日益凸显。然而&#xff0c;传统的运维模式往往局限于网络稳定、设备监控和系统可用等基础目标&#xff0c;难以满足现代企业对业务支持的更高要求。那么&#xff0c;我们究竟需要什么…

12.5【计算机网络】【Study】

如果使用 LACP 协议&#xff0c;设备之间会通过发送 LACP 数据包进行协商&#xff0c;确保双方都支持链路聚合&#xff0c;并且配置一致。LACP 会自动检测和管理链路的状态&#xff0c;确保只有活动的链路参与聚合。 负载均衡&#xff1a;链路聚合组中的多个物理链路可以同时传…

Python学习(三)—— 基础语法(下)

目录 一&#xff0c;函数 二&#xff0c;列表和元组 2.1 列表基础操作 2.2 切片 2.3 列表的增删查改 2.4 连接链表 2.5 元组 三&#xff0c;字典 3.1 关于字典 3.2 字典的增删查改操作 3.3 遍历字典元素 3.4 合法的key类型 四&#xff0c;文件操作 4.1 打开关闭…

QTreeView 与 QTreeWidget 例子

1. 先举个例子 1班有3个学生&#xff1a;张三、李四、王五 4个学生属性&#xff1a;语文 数学 英语 性别。 语文 数学 英语使用QDoubleSpinBox* 编辑&#xff0c;范围为0到100,1位小数 性别使用QComboBox* 编辑&#xff0c;选项为&#xff1a;男、女 实现效果&#xff1a; 2…

基于SpringBoot的疫苗在线预约功能实现十

一、前言介绍&#xff1a; 1.1 项目摘要 随着全球公共卫生事件的频发&#xff0c;如新冠疫情的爆发&#xff0c;疫苗成为了预防和控制传染病的重要手段。传统的疫苗预约方式&#xff0c;如人工挂号或电话预约&#xff0c;存在效率低、易出错、手续繁琐等问题&#xff0c;无法…

.NET 9 已发布,您可以这样升级或更新

.NET 9 已经发布&#xff0c;您可能正在考虑更新您的 ASP.NET Core 应用程序。 我们将介绍更新应用程序所需的内容。从更新 Visual Studio 和下载 .NET SDK 到找出可能破坏应用程序的任何重大更改。 下载 .NET 9 SDK 这些是下载 .NET 9 SDK 所需的步骤。 更新 Visual Studi…

IMX6ULL开发板基础实验:Framebuffer驱动程序的简单应用实例代码详细分析

前言 这个代码之所以可以写得这么短&#xff0c;写得这么方便&#xff0c;原因在于LCD的驱动程序已经写好了&#xff0c;并且这个驱动程序符号Framebuffer的标准&#xff0c;这才使得我们在实现上层应用时变得很方便。 源代码&#xff1a; #include <sys/mman.h> #inc…

Jenkins:持续集成与持续部署的利器

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是Jenkins 2、Jenkins的起源 二、Jenkins的核心…

C语言基础14(动态内存控制后续)

文章目录 野指针、空指针、空悬指针野指针空指针空悬指针 void与void*的区别内存操作常用内存操作函数内存填充内存拷贝内存比较内存查找 野指针、空指针、空悬指针 野指针 定义&#xff1a;指向一块未知区域(已经销毁或者访问受限的内存区域外的已存在或不存在的内存区域)&a…

CSS在线格式化 - 加菲工具

CSS在线格式化 打开网站 加菲工具 选择“CSS在线格式化” 或者直接访问 https://www.orcc.online/tools/css 输入CSS代码&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果

分布式事物XA、BASE、TCC、SAGA、AT

分布式事务——Seata 一、Seata的架构&#xff1a; 1、什么是Seata&#xff1a; 它是一款分布式事务解决方案。官网查看&#xff1a;Seata 2.执行过程 在分布式事务中&#xff0c;会有一个入口方法去调用各个微服务&#xff0c;每一个微服务都有一个分支事务&#xff0c;因…

Serdes技术与Xilinx GT概览

目录 一、前言 二、Serdes技术 2.1 芯片间信号传输 2.2 Serdes技术 三、 Xilinx GT 3.1 7系列器件GT 3.2 Ultrascale GT 3.3 Ultrascale GT 四、参考资料 一、前言 对于芯片间高速信号传输技术&#xff0c;不得不提serdes以及在Xilinx在此基础上的高速收发器GT系列&…

HarmonyOS Next 元服务新建到上架全流程

HarmonyOS Next 元服务新建到上架全流程 接上篇 这篇文章的主要目的是介绍元服务从新建到上家的完整流程 在AGC平台上新建一个项目 链接 一个项目可以多个应用 AGC新建一个元服务应用 新建一个本地元服务项目 如果成功在AGC平台上新建过元服务&#xff0c;那么这里会自动显…

【Spark】Spark的两种核心Shuffle工作原理详解

如果觉得这篇文章对您有帮助&#xff0c;别忘了点赞、分享或关注哦&#xff01;您的一点小小支持&#xff0c;不仅能帮助更多人找到有价值的内容&#xff0c;还能鼓励我持续分享更多精彩的技术文章。感谢您的支持&#xff0c;让我们一起在技术的世界中不断进步&#xff01; Sp…