JackCin's blog JackCin's blog
首页
  • 页面

    • Html
    • CSS
  • 核心

    • JavaScript基础
    • JavaScript高级
  • 框架

    • Vue
  • jQuery
  • Node
  • Ajax
Linux
  • 操作系统
  • 数据结构与算法
  • 51单片机
  • CC2530
  • 网站
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

JackCin

前端小菜鸡(✪ω✪)
首页
  • 页面

    • Html
    • CSS
  • 核心

    • JavaScript基础
    • JavaScript高级
  • 框架

    • Vue
  • jQuery
  • Node
  • Ajax
Linux
  • 操作系统
  • 数据结构与算法
  • 51单片机
  • CC2530
  • 网站
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 51单片机

    • 51单片机及补充知识
    • LED
    • 独立按键
    • 数码管
    • LCD1602液晶显示器
    • 矩阵按键
      • 定时器
      • 串口
      • LED点阵屏
      • 蜂鸣器
      • AT24C02存储器
      • AD与DA
      • DS18B20温度传感器
      • DS1302时钟
      • LCD1602液晶显示屏
      • 红外遥控
      • 呼吸灯与直流电机调速(PWM)
    • 单片机
    • 51单片机
    JackCin
    2023-09-13
    目录

    矩阵按键

    # 矩阵按键

    # 1、矩阵按键的介绍

    • 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
    • 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态

    # 2、扫描的概念

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

      • 原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
    • 矩阵键盘扫描(输入扫描)

      • 原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果
    • 以上两种扫描方式的共性:节省I/O口

    # 3、原理图

    矩阵按键

    • 这里可以有两种扫描的方法
    • 原理:给P17置为0(相当于单片机主动给予了P17低电平,按下按键后线路连通,自然会把按下按键对应的另一个口的电平拉低),判断其他对应引脚的电平
      1. 按行扫描:给P17置为0(相当于单片机主动基于了P17低电平,按下按键后线路连通,自然会把按下按键对应的另一个口的电平拉低),然后判断怕P13—P10是否有哪个为0,有就说明对应的哪个按键被按下,之后再给P16置为0,然后重复上面的步骤。。。(即按行来一行一行的扫描)
      2. 按列扫描:给P13置为0,然后判断P17—P104是否有哪个为0,有就说明对应的那个按键被按下,之后再给P12置为0,然后重复上面的步骤。。。(即按列来一行一行的扫描)
      3. (个人看法,应该不用按顺序扫描,就拿按列扫描来说,应该不用强制要求先P13,再P12,再P11,再P10)
    • 本次学习我们使用按列扫描,因为如果按行扫描,P15口可能会一会给高一会给低,而P15口和蜂鸣器有关联,要是以一定的频率高低变化的话,会导致无源蜂鸣器启动(普中A2的开发板将与蜂鸣器联系的P15口改成了P25)

    # 4、案例:矩阵案件密码锁🔒

    • 要求:
      • 输入4位数字,判断是否为正确密码
      • 按S11判断密码是否正确
      • 按S12重置密码

    # 4.1 MatrixKey.c

    #include <REGX52.H>
    #include "Delay.h"
     
    /**
      * @brief  矩阵键盘读取按键键码
      * @param  无
      * @retval KeyNumber 按下按键的键码值
    	如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0 ! 
      */
    unsigned char MatrixKey()
    {
    	unsigned char KeyNumber=0;
    	
    	P1=0xFF;// 1111 1111 全部置高电平默认
    	P1_3=0; // 矩阵按键第一行扫描
    	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
    	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
    	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
    	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
    	
    	P1=0xFF;
    	P1_2=0; // 矩阵按键第二行扫描
    	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
    	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
    	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
    	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
    	
    	P1=0xFF;
    	P1_1=0; // 矩阵按键第三行扫描
    	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
    	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
    	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
    	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
    	
    	P1=0xFF;
    	P1_0=0; // 矩阵按键第四行扫描
    	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
    	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
    	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
    	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
    	
    	return KeyNumber;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43

    # 4.2 main.c

    #include <REGX52.H>
    #include "Delay.h"
    #include "LCD1602.h"
    #include "MatrixKey.h"
    // 按键作用: S1~S9 设置数字为 1~9, S10定义为数字0, S11用作于是确认按键, S12用作于是取消按键 《《《 S13~S16,我们不去进行使用
    unsigned char KeyNum;        // 全局变量初始化默认为:0
    unsigned int Password,Count; // 如果用6位数字的密码就会超出这个 unsigned int 的一个数值的范围了 0~65535, Count作用:计次,防止输入过多的密码
     
    int main(void)
    {
    	LCD_Init();
    	LCD_ShowString(1,1,"Password:");
    	while(1)
    	{
    		KeyNum=MatrixKey();
    		if(KeyNum)
    		{
    			if(KeyNum<=10)	//如果S1~S10按键按下,输入密码
    			{  
    				if(Count<4)	  //如果输入次数小于4
    				{
    					Password*=10;				        //密码左移一位 : Password = Password * 10
                        //获取一位密码 : Password = password + KeyNum % 10, 1~9取模10还是为原来的数字~ 获取密码用取模%运算符然后进行赋值
    					Password+=KeyNum%10;		    
    					Count++;	 //计次加一
    				} 
                    //更新显示   0000 0000 输入第一次(1) 显示0001 》》》 0001 0010 输入第二次(2) 显示0012
    				LCD_ShowNum(2,1,Password,4);	
    			}
    			if(KeyNum==11)	//如果S11按键按下,确认 ----注意:这里不进行消抖的原因是:模块化编程的时候已经进行消抖了
    			{
    				if(Password==2345)	//如果密码等于正确密码 --------------------------- 定义密码
    				{
    					LCD_ShowString(1,14,"OK ");	// 显示OK
    					Password=0;		// 密码清零
    					Count=0;		  // 计次清零
    					LCD_ShowNum(2,1,Password,4);	// 更新显示
    				}
    				else				//否则
    				{
    					LCD_ShowString(1,14,"ERR");	//显示ERR
    					Password=0;		// 密码清零
    					Count=0;		  // 计次清零
    					LCD_ShowNum(2,1,Password,4);	//更新显示
    				}
    			}
    			if(KeyNum==12)	//如果S12按键按下,取消
    			{
    				Password=0;		// 密码清零
    				Count=0;		 // 计次清零
    				LCD_ShowNum(2,1,Password,4);	//更新显示
    			}
    		}
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    编辑 (opens new window)
    上次更新: 2023/09/13, 12:29:52
    LCD1602液晶显示器
    定时器

    ← LCD1602液晶显示器 定时器→

    最近更新
    01
    51单片机及补充知识
    09-13
    02
    独立按键
    09-13
    03
    LCD1602液晶显示器
    09-13
    更多文章>
    Theme by Vdoing | Copyright © 2019-2023 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式