C51_矩阵按键

文章目录

  • 一、矩阵按建
  • 二、原理图
  • 三、代码实例
    • [   1、按键检测](#   1、按键检测)
    • [   2、密码锁](#   2、密码锁)
      • [     1)、MatrixKey.h](#     1)、MatrixKey.h)
      • [     2)、MatrixKey.c](#     2)、MatrixKey.c)
      • [     3)、main.c](#     3)、main.c)

一、矩阵按建

独立按键与单片机连接时,每一个按键都需要单片机的一个 I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的 I/O 口资源。

单片机系统中 I/O 口资源往往比较宝贵,当用到多个按键时为了减少 I/O 口引脚,引入了矩阵按键。

矩阵按键原理:

1)、将 16 个按键排成 4 行 4 列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,这样便一共有4行4列共8根线,我们将这 8 根线连接到单片机的 8 个 I/O 口上,通过程序扫描键盘就可检测 16 个键。

2)、用这种方法我们也可实现 3 行 3 列 9 个键、 5 行 5 列 25个键、 6 行6 列 36 个键甚至更多。

3)、单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的 I/O 口是否为低电平。

4)、行列扫描:

行列扫描法检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。

5)、线翻转法:

使所有行线为低电平时,检测所有列线是否有低电平,如果有,就记录列线值;然后再翻转,使所有列线都为低电平,检测所有行线的值,由于有按键按下,行线的值也会有变化,记录行线的值。从而就可以检测到全部按键。

二、原理图

4*4矩阵按键引出的8根控制线直接连接到51单片机的P1口上。

电路中的P17连接矩阵键盘的第1行,P13连接矩阵键盘第1列。

三、代码实例

1、按键检测

通过数码管显示矩阵按键S1-S16按下后键值0-F。

c 复制代码
		#include <REGX52.H>
		
		typedef unsigned int u16;        //对系统默认数据类型进行重定义
		typedef unsigned char u8;
		
		#define KEY_MATRIX_PORT        P1        //使用宏定义矩阵按键控制口                
		
		#define SMG_A_DP_PORT        P0        //使用宏定义数码管段码口
		
		//共阴极数码管显示0~F的段码数据
		u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};        
		
		/*******************************************************************************
		* 函 数 名       : delay_10us
		* 函数功能                 : 延时函数,ten_us=1时,大约延时10us
		* 输    入       : ten_us
		* 输    出             : 无
		*******************************************************************************/
		void delay_10us(u16 ten_us)
		{
		        while(ten_us--);        
		}
		
		/*******************************************************************************
		* 函 数 名       : key_matrix_ranks_scan
		* 函数功能                 : 使用行列式扫描方法,检测矩阵按键是否按下,按下则返回对应键值
		* 输    入       : 无
		* 输    出             : key_value:1-16,对应S1-S16键,
		           0:按键未按下
		*******************************************************************************/
		u8 key_matrix_ranks_scan(void)
		{
		        u8 key_value=0;
		
		        KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1
		        if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下
		        {
		                delay_10us(1000);//消抖
		                switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值        
		                {
		                        case 0x77: key_value=1;break;
		                        case 0xb7: key_value=5;break;
		                        case 0xd7: key_value=9;break;
		                        case 0xe7: key_value=13;break;
		                }
		        }
		        while(KEY_MATRIX_PORT!=0xf7);//等待按键松开        
		        
		        KEY_MATRIX_PORT=0xfb;//给第二列赋值0,其余全为1
		        if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下
		        {
		                delay_10us(1000);//消抖
		                switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值        
		                {
		                        case 0x7b: key_value=2;break;
		                        case 0xbb: key_value=6;break;
		                        case 0xdb: key_value=10;break;
		                        case 0xeb: key_value=14;break;
		                }
		        }
		        while(KEY_MATRIX_PORT!=0xfb);//等待按键松开        
		        
		        KEY_MATRIX_PORT=0xfd;//给第三列赋值0,其余全为1
		        if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下
		        {
		                delay_10us(1000);//消抖
		                switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值        
		                {
		                        case 0x7d: key_value=3;break;
		                        case 0xbd: key_value=7;break;
		                        case 0xdd: key_value=11;break;
		                        case 0xed: key_value=15;break;
		                }
		        }
		        while(KEY_MATRIX_PORT!=0xfd);//等待按键松开        
		        
		        KEY_MATRIX_PORT=0xfe;//给第四列赋值0,其余全为1
		        if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下
		        {
		                delay_10us(1000);//消抖
		                switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值        
		                {
		                        case 0x7e: key_value=4;break;
		                        case 0xbe: key_value=8;break;
		                        case 0xde: key_value=12;break;
		                        case 0xee: key_value=16;break;
		                }
		        }
		        while(KEY_MATRIX_PORT!=0xfe);//等待按键松开
		        
		        return key_value;                
		}
		
		/*******************************************************************************
		* 函 数 名       : key_matrix_flip_scan
		* 函数功能                 : 使用线翻转扫描方法,检测矩阵按键是否按下,按下则返回对应键值
		* 输    入       : 无
		* 输    出             : key_value:1-16,对应S1-S16键,
		           0:按键未按下
		*******************************************************************************/
		u8 key_matrix_flip_scan(void)
		{
		        static u8 key_value=0;
		
		        KEY_MATRIX_PORT=0x0f;//给所有行赋值0,列全为1
		        if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下
		        {
		                delay_10us(1000);//消抖
		                if(KEY_MATRIX_PORT!=0x0f)
		                {
		                        //测试列
		                        KEY_MATRIX_PORT=0x0f;
		                        switch(KEY_MATRIX_PORT)//保存行为0,按键按下后的列值        
		                        {
		                                case 0x07: key_value=1;break;
		                                case 0x0b: key_value=2;break;
		                                case 0x0d: key_value=3;break;
		                                case 0x0e: key_value=4;break;
		                        }
		                        //测试行
		                        KEY_MATRIX_PORT=0xf0;
		                        switch(KEY_MATRIX_PORT)//保存列为0,按键按下后的键值        
		                        {
		                                case 0x70: key_value=key_value;break;
		                                case 0xb0: key_value=key_value+4;break;
		                                case 0xd0: key_value=key_value+8;break;
		                                case 0xe0: key_value=key_value+12;break;
		                        }
		                        while(KEY_MATRIX_PORT!=0xf0);//等待按键松开        
		                }
		        }
		        else
		                key_value=0;                
		        
		        return key_value;                
		}
		
		/*******************************************************************************
		* 函 数 名       : main
		* 函数功能                 : 主函数
		* 输    入       : 无
		* 输    出             : 无
		*******************************************************************************/
		void main()
		{        
		        u8 key=0;
		
		        while(1)
		        {
		                   key=key_matrix_ranks_scan();
		                if(key!=0)
		                        SMG_A_DP_PORT=gsmg_code[key-1];//得到的按键值减1换算成数组下标对应0-F段码                
		        }                
		}

2、密码锁

1)、MatrixKey.h

c 复制代码
			#ifndef __MATRIXKEY_H__
			#define __MATRIXKEY_H__
			 
			unsigned char MatrixKey();
			        
			#endif

2)、MatrixKey.c

c 复制代码
			#include <REGX52.H>
			#include "Delay.h"
			 
			unsigned char MatrixKey()
			{
			        unsigned char KeyNumber=0;
			        
			        P1=0xFF;
			        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;
			}

3)、main.c

c 复制代码
			#include <REGX52.H>
			#include "LCD1602.h"
			#include "Delay.h"
			#include "MatrixKey.h"
			 
			unsigned char KeyNum;
			unsigned int Password, Count;
			 
			void main()
			{
			        LCD_Init();
			        LCD_ShowString(1,1,"Password:");
			        Password = 0;
			        Count = 0;
			        LCD_ShowNum(2,1,Password,4);
			        while(1)
			        {
			                KeyNum=MatrixKey();
			                if(KeyNum)
			                {
			                        if(KeyNum<=10)  // 如果S1~S10按键按下,输入密码
			                        {
			                                if(Count<4)  // 密码四位数
			                                {
			                                Password*=10;  //  密码左移一位,这样就可以依次输入密码
			                                Password+=KeyNum%10;  // 获取一位密码,加入到原密码,此时10为0
			                                Count++;
			                                }
			                        }
			                        LCD_ShowNum(2,1,Password,4);
			                        if(KeyNum==11)  // 确认
			                        {
			                                if(Password==1234)
			                                {
			                                        LCD_ShowString(1,14,"OK ");
			                                        Password=0;
			                                        Count=0;
			                                        LCD_ShowNum(2,1,Password,4);
			                                }
			                                else
			                                {
			                                        LCD_ShowString(1,14,"ERR");
			                                        Password=0;
			                                        Count=0;
			                                        LCD_ShowNum(2,1,Password,4);
			                                }
			                        }
			                        if(KeyNum==12)  //取消
			                        {
			                                Password=0;
			                                Count=0;
			                                LCD_ShowString(1,14,"   ");
			                                LCD_ShowNum(2,1,Password,4);
			                        }
			                }
			        }
			}
相关推荐
mastercoder--12 小时前
速通51单片机————矩阵键盘及其应用
嵌入式硬件·计算机外设·51单片机
普中科技12 小时前
【普中51单片机开发攻略--基于普中-2&普中-3&普中-4】-- 第 14 章 矩阵按键实验
单片机·嵌入式硬件·51单片机·开发板·按键检测·矩阵按键·普中科技
搞机械的假程序猿12 小时前
普中51单片机学习笔记-LCD1602液晶显示
笔记·学习·51单片机
Q_219327645513 小时前
基于51单片机的智能家居防火防盗报警系统设计
嵌入式硬件·51单片机·智能家居
恶魔泡泡糖1 天前
51单片机动态数码管应用2
单片机·嵌入式硬件·51单片机
mastercoder--1 天前
速通51单片机————数码管显示与模块化编程
单片机·嵌入式硬件·51单片机
v先v关v住v获v取2 天前
番茄收获机切割与分离装置结构设计cad5张 +三维图+设计说明书
科技·单片机·51单片机
电子工程师-C512 天前
基于51单片机的交通灯远程控制系统
单片机·嵌入式硬件·51单片机
v先v关v住v获v取2 天前
圆形通风管道灰尘清理机器人设计14张cad+三维图+设计说明书
科技·单片机·51单片机
v先v关v住v获v取3 天前
番茄打浆机结构设计cad13+三维图+设计说明说
科技·单片机·51单片机