04 - 矩阵键盘

发布时间 2023-12-14 17:28:28作者: 逸聆君

04 - 矩阵键盘

前言

LCD1602液晶屏

在学习使用矩阵键盘之前,为了后续的调试和显示,有必要简单了解一下LCD1602液晶屏的使用方法。江协科技已经给我们提供了模块化的代码,所以我们只需要调用对应方法就可以了,常用方法如下:

至于LCD1602具体如何操作使用,后续会有,暂时就先放一边

扫描的概念

扫描的作用:节省I/O

  • 数码管的扫描(输出扫描)

    原理:显示第1位——>显示第2位——>显示第3位——>...,然后快速循环这个过程,最终实现所有数码管同时显示的效果

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

    原理:读取第1行(列)——>读取第2行(列)——>读取第3行(列)——>...,然后快速循环这个过程,最终实现所有按键同时检测的效果

矩阵键盘

  • 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式

  • 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态

注意:看江协科技视频,提到由于其开发板内部的电路连接问题,如果采用逐行扫描的话,P15端口的电平时高时低,而且蜂鸣器会一直响,无法关闭。所以为了避免这个问题,采用逐列扫描(但是我使用的开发板和其不一样,于是试了试逐行扫描,蜂鸣器并没有响。具体差异学完后面再回来看看)

一、读取矩阵键盘的键码值

#include <REGX52.H>
#include "LCD1602.H"

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;

    while(xms)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
        xms--;
    }
}


/**
  * @brief  矩阵键盘读取按键键码(逐列)
  * @param  无
  * @retval chKeyNum 按下按键的键码值
  *         如果按键按下不放,程序会停留在此函数,松手返回按键键码。若没有按键按下,返回0
  */
unsigned char MatrixKey()
{
    unsigned char chKeyNum = 0;
    
    P1 = 0xFF;
    P1_3 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=1;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=5;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=9;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=13;}
    
    P1 = 0xFF;
    P1_2 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=2;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=6;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=10;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=14;}
    
    P1 = 0xFF;
    P1_1 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=3;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=7;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=11;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=15;}
    
    P1 = 0xFF;
    P1_0 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=4;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=8;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=12;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=16;}
    
    return chKeyNum;
}


/**
  * @brief  矩阵键盘读取按键键码(逐行)
  * @param  无
  * @retval chKeyNum 按下按键的键码值
  *         如果按键按下不放,程序会停留在此函数,松手返回按键键码。若没有按键按下,返回0
  */
unsigned char MatrixKey_2()
{
    unsigned char chKeyNum = 0;
    
    P1 = 0xFF;
    P1_7 = 0;
    if(P1_3 == 0){Delay(20);while(P1_3 == 0);Delay(20);chKeyNum=1;}
    if(P1_2 == 0){Delay(20);while(P1_2 == 0);Delay(20);chKeyNum=2;}
    if(P1_1 == 0){Delay(20);while(P1_1 == 0);Delay(20);chKeyNum=3;}
    if(P1_0 == 0){Delay(20);while(P1_0 == 0);Delay(20);chKeyNum=4;}
    
    P1 = 0xFF;
    P1_6 = 0;
    if(P1_3 == 0){Delay(20);while(P1_3 == 0);Delay(20);chKeyNum=5;}
    if(P1_2 == 0){Delay(20);while(P1_2 == 0);Delay(20);chKeyNum=6;}
    if(P1_1 == 0){Delay(20);while(P1_1 == 0);Delay(20);chKeyNum=7;}
    if(P1_0 == 0){Delay(20);while(P1_0 == 0);Delay(20);chKeyNum=8;}
    
    P1 = 0xFF;
    P1_5 = 0;
    if(P1_3 == 0){Delay(20);while(P1_3 == 0);Delay(20);chKeyNum=9;}
    if(P1_2 == 0){Delay(20);while(P1_2 == 0);Delay(20);chKeyNum=10;}
    if(P1_1 == 0){Delay(20);while(P1_1 == 0);Delay(20);chKeyNum=11;}
    if(P1_0 == 0){Delay(20);while(P1_0 == 0);Delay(20);chKeyNum=12;}
    
    P1 = 0xFF;
    P1_4 = 0;
    if(P1_3 == 0){Delay(20);while(P1_3 == 0);Delay(20);chKeyNum=13;}
    if(P1_2 == 0){Delay(20);while(P1_2 == 0);Delay(20);chKeyNum=14;}
    if(P1_1 == 0){Delay(20);while(P1_1 == 0);Delay(20);chKeyNum=15;}
    if(P1_0 == 0){Delay(20);while(P1_0 == 0);Delay(20);chKeyNum=16;}
    
    return chKeyNum;
}

void main()
{   
    unsigned char chKeyNum = 0;
    LCD_Init();
    LCD_ShowString(1, 1, "MatrixKey: ");
    while(1)
    {
        chKeyNum = MatrixKey();
        if(chKeyNum)
        {
            LCD_ShowNum(2, 1, chKeyNum, 2);
        }  
    }
}

二、矩阵键盘密码锁

#include <REGX52.H>
#include "LCD1602.H"

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;

    while(xms)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
        xms--;
    }
}


/**
  * @brief  矩阵键盘读取按键键码(逐列)
  * @param  无
  * @retval chKeyNum 按下按键的键码值
  *         如果按键按下不放,程序会停留在此函数,松手返回按键键码。若没有按键按下,返回0
  */
unsigned char MatrixKey()
{
    unsigned char chKeyNum = 0;
    
    P1 = 0xFF;
    P1_3 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=1;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=5;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=9;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=13;}
    
    P1 = 0xFF;
    P1_2 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=2;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=6;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=10;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=14;}
    
    P1 = 0xFF;
    P1_1 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=3;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=7;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=11;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=15;}
    
    P1 = 0xFF;
    P1_0 = 0;
    if(P1_7 == 0){Delay(20);while(P1_7 == 0);Delay(20);chKeyNum=4;}
    if(P1_6 == 0){Delay(20);while(P1_6 == 0);Delay(20);chKeyNum=8;}
    if(P1_5 == 0){Delay(20);while(P1_5 == 0);Delay(20);chKeyNum=12;}
    if(P1_4 == 0){Delay(20);while(P1_4 == 0);Delay(20);chKeyNum=16;}
    
    return chKeyNum;
}

void main()
{   
    unsigned char chKeyNum = 0;
    unsigned int nPassword = 0;
    unsigned int nCnt = 0;
    
    LCD_Init();
    LCD_ShowString(1, 1, "Password: ");
    while(1)
    {
        chKeyNum = MatrixKey();
        if(chKeyNum > 0 && chKeyNum < 11)   // 密码输入
        {
            if(nCnt < 4)
            {
                nPassword *= 10;
                nPassword += chKeyNum;
                LCD_ShowNum(2, 1, nPassword, 4);
            }
            
            nCnt++;
        }
        else if(chKeyNum == 11)             // 清零键
        {
            nCnt = 0;
            nPassword = 0;
            LCD_ShowNum(2, 1, nPassword, 4);
        }
        else if(chKeyNum == 12)             // 确定键
        {
            if(nPassword == 1234)
            {
                LCD_ShowString(1, 14, "OK ");
            }
            else
            {
                LCD_ShowString(1, 14, "ERR");
            }
            
            nCnt = 0;
            nPassword = 0;
            LCD_ShowNum(2, 1, nPassword, 4);
        }
    }
}