51 矩阵按键

51 矩阵按键

在开发板的右下区域,我们可以看见一个4x4规格的按键矩阵,这就是矩阵按键

通过扫描的方式,可以读出任意按键的状态,即在按键数量较多时,通过矩阵方式进行组合可以减少IO的占用

STC89C52RC开发板上的矩阵按键模块(图源:普中科技开发手册)

在这里插入图片描述

矩阵键盘的扫描

数码管扫描(输出扫描)

​ 原理:按照一个顺序逐个显示数码管,然后循环这个过程,实现所有数码管同时显示的

有关数码管的扫描,详见51 20231117 数码管-CSDN博客

矩阵键盘扫描(输入扫描)

​ 原理:类似于数码管扫描,分为按行扫描和按列扫描


矩阵键盘的判断就是不断扫描

按行扫描:给需要判断的行给0,其它给1,当按下某一列对应的按键时,对应那列变成0,以此来确定按下的是哪个按键

(由于开发板电路问题,STC89C52的P15口在逐行扫描会出问题(P15接到步进电机,步进电机接到BZ,即蜂鸣器,这个开发板采用的是一种无源蜂鸣器,接收到一定频率高低变化的电压会响)

(但是STC89C52RC好像不会有这个问题,因为它的步进电机接的是P25)

STC89C52RC开发板上的步进电机模块(图源:普中科技开发手册)

在这里插入图片描述

这里使用按列扫描:即给P10~P13电平,判断P14~P17

(单片机的端口默认是高电平,只有给低电平才能判断)

//矩阵按键模块(列扫描)
#include<STC89C5xRC.H>
#include"Delay.h"

unsigned char MatrixKey()
{
    unsigned char KeyNumber = 0;

    P1 = 0xff;
    P13 = 0;
    //除了P13以外全部置1
    if(P17 == 0)
    {
        Delay(20);
        while(P17 == 0);
        KeyNumber = 1;
    }
      if(P16 == 0)
    {
        Delay(20);
        while(P16 == 0);
        KeyNumber = 5;
    }
      if(P15 == 0)
    {
        Delay(20);
        while(P15 == 0);
        KeyNumber = 9;
    }
      if(P14 == 0)
    {
        Delay(20);
        while(P14 == 0);
        KeyNumber = 13;
    }
    //扫描第一列

    P1 = 0xff;
    P12 = 0;
    if(P17 == 0)
    {
        Delay(20);
        while(P17 == 0);
        KeyNumber = 2;
    }
      if(P16 == 0)
    {
        Delay(20);
        while(P16 == 0);
        KeyNumber = 6;
    }
      if(P15 == 0)
    {
        Delay(20);
        while(P15 == 0);
        KeyNumber = 10;
    }
      if(P14 == 0)
    {
        Delay(20);
        while(P14 == 0);
        KeyNumber = 14;
    }

    P1 = 0xff;
    P11 = 0;
    if(P17 == 0)
    {
        Delay(20);
        while(P17 == 0);
        KeyNumber = 3;
    }
      if(P16 == 0)
    {
        Delay(20);
        while(P16 == 0);
        KeyNumber = 7;
    }
      if(P15 == 0)
    {
        Delay(20);
        while(P15 == 0);
        KeyNumber = 11;
    }
      if(P14 == 0)
    {
        Delay(20);
        while(P14 == 0);
        KeyNumber = 15;
    }

    P1 = 0xff;
    P10 = 0;
    if(P17 == 0)
    {
        Delay(20);
        while(P17 == 0);
        KeyNumber = 4;
    }
      if(P16 == 0)
    {
        Delay(20);
        while(P16 == 0);
        KeyNumber = 8;
    }
      if(P15 == 0)
    {
        Delay(20);
        while(P15 == 0);
        KeyNumber = 12;
    }
      if(P14 == 0)
    {
        Delay(20);
        while(P14 == 0);
        KeyNumber = 16;
    }

    return KeyNumber;
}

配合LCD1602的显示函数,我们可以实现按下哪个按键就显示对应数字

#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include"MatrixKey.h"

unsigned char Keynum = 0;

void main()
{
    LCD_Init();
    LCD_ShowString(1, 1, "Hello");
    while(1)
    {
        Keynum = MatrixKey();
        if(Keynum)
        {
            LCD_ShowNum(2, 1, Keynum, 2);
        }
    }
}

---
对于STC89C52RC,是可以采用逐行扫描的方式进行扫描的
#include<STC89C5xRC.H>
#include"Delay.h"

/**
  * @brief 矩阵键盘读取按键键码
  * @param 无
  * @retval KeyNumber 按下按键的键码值
  * 如果按下按键不放,程序会停留在此函数,松手的一瞬间返回按键键码
  * 没有按键时,返回0
**/

unsigned char MatrixKey()
{
    unsigned char Keynumber = 0;

    P1 = 0xff;
    P17 = 0;
    if(P13 == 0)
    {
        Keynumber = 1;
    }
    if(P12 == 0)
    {
        Keynumber = 2;
    }
    if(P11 == 0)
    {
        Keynumber = 3;
    }
    if(P10 == 0)
    {
        Keynumber = 4;
    }

    P1 = 0xff;
    P16 = 0;
    if(P13 == 0)
    {
        Keynumber = 5;
    }
    if(P12 == 0)
    {
        Keynumber = 6;
    }
    if(P11 == 0)
    {
        Keynumber = 7;
    }
    if(P10 == 0)
    {
        Keynumber = 8;
    }

    P1 = 0xff;
    P15 = 0;
    if(P13 == 0)
    {
        Keynumber = 9;
    }
    if(P12 == 0)
    {
        Keynumber = 10;
    }
    if(P11 == 0)
    {
        Keynumber = 11;
    }
    if(P10 == 0)
    {
        Keynumber = 12;
    }

    P1 = 0xff;
    P14 = 0;
    if(P13 == 0)
    {
        Keynumber = 13;
    }
    if(P12 == 0)
    {
        Keynumber = 14;
    }
    if(P11 == 0)
    {
        Keynumber = 15;
    }
    if(P10 == 0)
    {
        Keynumber = 16;
    }

    return Keynumber;
}

利用矩阵键盘实现密码锁

通过矩阵键盘的输入检测,我们可以实现一个包含密码判断、重复输入等功能的简易密码锁

不过这里有个缺陷,就是用于储存输入数据的类型是int,最多只能支持4位密码

#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include"MatrixKey.h"

unsigned char Keynum = 0;
unsigned int Password = 0;
//0~65535, 定义4位密码即可
unsigned char count = 0;

void main()
{
    LCD_Init();
    LCD_ShowString(1, 1, "Password:");
    while(1)
    {
        Keynum = MatrixKey();
        if(Keynum)
        {
            if(Keynum <= 10)
            //如果按下的按键为S1~S10,输入密码
            {
                count++;
                //计算输入次数

                if(count <= 4)
                {
                    Password *= 10;
                    //上一位密码左移
                    Password += Keynum % 10;
                    //1-9得到原来的数,10取0
                    //获取一位密码
                }
            }
            if(Keynum == 11)
            //S11被按下,表示确认
            {
                if(Password == 1234)
                {
                    LCD_ShowString(1, 13, "OK ");
                    //密码正确
                }
                else
                {
                    LCD_ShowString(1, 13, "err");
                    Password = 0;
                    //重置状态
                    count = 0;
                }               
            }

            if(Keynum == 12)
            //S12按下,取消,即清空
            {
                Password = 0;
                count = 0;
            }

            LCD_ShowNum(2, 1, Password, 4);
            //更新显示
        }
    }
}

利用字符串实现长密码锁

我们可以通过字符串实现支持更长密码的密码锁,这里需要用到字符串处理的相关知识

#include <STC89C5xRC.H>
#include<string.h>
#include<stdio.h>
#include"Delay.h"
#include"MatrixKey.h"
#include"LCD1602.h"

char password[8] = {0};
//注意\n需要占一个位置
int count = 0;
int Keynum = 0;


void main()
{
    LCD_Init();
    LCD_ShowString(1, 1, "Password:");
    while(1)
    {
        Keynum = MatrixKey();
        if(Keynum)
        {
            if(Keynum <= 10)
            //判断是否输入
            {
                count++;
                if(count <= 7)
                {
                    switch(Keynum)
                    //通过按键向字符串中加入对应数字
                    {
                        case 1:strcat(password, "1");break;
                        case 2:strcat(password, "2");break;
                        case 3:strcat(password, "3");break;
                        case 4:strcat(password, "4");break;
                        case 5:strcat(password, "5");break;
                        case 6:strcat(password, "6");break;
                        case 7:strcat(password, "7");break;
                        case 8:strcat(password, "8");break;
                        case 9:strcat(password, "8");break;
                        case 10:strcat(password, "0");break;
                    }
                }
                LCD_ShowString(2, 1, password);
            }

            if(Keynum == 11)
            {
                if(strcmp(password, "7355608") == 0)
                //判断密码是否正确
                //玩cs玩的
                {
                    LCD_ShowString(1, 1, "                ");
                    LCD_ShowString(2, 1, "                ");
                    LCD_ShowString(1, 1, "Bomb has been");
                    LCD_ShowString(2, 1, "planted!");
                }
                else
                {
                    count = 0;
                    strcpy(password, "");
                    //重置字符串
                    LCD_ShowString(1, 13, "ERR");
                    LCD_ShowString(2, 1, "        ");
                }
            }

            if(Keynum == 12)
            {
                strcpy(password, "");
                LCD_ShowString(2, 1, "        ");
                count = 0;
            }
            
        }
        //LCD_ShowString(2, 1, password);
        //由于要显示文字,实时显示密码就不能放在这里了,否则在最后还是显示密码
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值