51单片机矩阵按键

目录

1.实现功能

一共有16个按键,分别控制数码管0-15,在数码管显示0-F,每一个按键都会单独控制显示数码管一个数字,数码管采用共阴极

2.矩阵按键介绍

P17,P16,,P15,P14 连接的是行

P13,P12,P11,P10 连接的是列

3.矩阵按键两种方法实现原理

实现矩阵扫描有两种方法,行列式扫描,线翻转法

3.1行列式扫描原理理解

P17,P16,,P15,P14连接的是行

P13,P12,P11,P10连接的是列

当P13是0(第一列为0) 那么P1接口 1111 0111,当第一列中的某一个按钮按下得到

0111 0111 -------->0X77 第一行第一列 key1

1011 0111 -------->0XB7 第二行第一列 key5

1101 0111 --------->0XD7 第三行第一列 key9

1110 0111---------->0XE7 第四行第一列 key13

当P12是0(第二列为0) 那么P1接口 1111 1011,当第二列中的某一个按钮按下得到

0111 1011 -------->0X7B 第一行第二列 key2

1011 1011 -------->0XBB 第二行第二列 key6

1101 1011 --------->0XDB 第三行第二列 key10

1110 1011---------->0XEB 第四行第二列 key14

当P11是0(第三列为0) 那么P1接口 1111 1101,当第三列中的某一个按钮按下得到

0111 1101 -------->0X7D 第一行第三列 key3

1011 1101 -------->0XBD 第二行第三列 key7

1101 1101 --------->0XDD 第三行第三列 key11

1110 1101---------->0XED 第四行第三列 key15

当P10是0(第四列为0) 那么P1接口 1111 1110,当第四列中的某一个按钮按下得到

0111 1110 -------->0X7E 第一行第四列 key4

1011 1110 -------->0XBE 第二行第四列 key8

1101 1110 --------->0XDE 第三行第四列 key12

1110 1110---------->0XEE 第四行第四列 key16

最后可以定义一个保存键值的变量key_value保存第key值,通过定义的数码管数组,用key充当数组的下标得到要输出的数字,赋值给数码管段选。

这种行列式需要重复四次的操作

3.2 线翻转法

P17,P16,,P15,P14连接的是行

P13,P12,P11,P10连接的是列

当P17,P16,,P15,P14都是0,行为0,那么P1接口 0000 1111,当四列中某一列的按钮按下得到

0000 0111 -------->0X07 第一列

0000 1011 -------->0X0B 第二列

0000 1101 -------->0X0D 第三列

0000 1110 -------->0X0E 第四列

用一个变量保存第几列,key_value

当P13,P12,P11,P10都是0,列为0,那么P1接口 1111 0000,当四行中某一行的按钮按下得到

0111 0000 -------->0X70 第一行 key = key_value

1011 0000 -------->0XB0 第二行 key = key_value + 4

1101 0000 -------->0XD0 第三行 key = key_value + 8

1110 0000 -------->0XE0 第四行 key = key_value + 12

最后返回的key值,充当数码管数组下标,输出显示出来对应的数码管的值。

4.行列式扫描代码

c 复制代码
#include <reg51.h>

typedef unsigned int u16;
typedef unsigned char u8;


#define KEY_MATRIX_POST P1
#define SMG_A_DP_POST P0 

u8 gsmg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共阴数码管0-F

void delay_50ms(u16 us) {
	while(us--);
}
u8 key_matrix_ranks_scan(void) {   //行列式扫描
	u8 key_value = 0;

	KEY_MATRIX_POST = 0XF7; //第一列为低电平 1111 0111
	if (KEY_MATRIX_POST != 0XF7) {

	    delay_50ms(1000); 
		switch(KEY_MATRIX_POST) {
			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_POST != 0XF7);//等待按键松开
	}
	

	KEY_MATRIX_POST = 0XFB; //第二列为低电平
	if (KEY_MATRIX_POST != 0XFB) {

	    delay_50ms(1000); 
		switch(KEY_MATRIX_POST) {
			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_POST != 0XFB);//等待按键松开
	}
	

	KEY_MATRIX_POST = 0XFD; //第三列为低电平
	if (KEY_MATRIX_POST != 0XFD) {

	    delay_50ms(1000); 
		switch(KEY_MATRIX_POST) {
			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_POST != 0XFD);//等待按键松开
	}
	

	KEY_MATRIX_POST = 0XFE; //第四列为低电平
	if (KEY_MATRIX_POST != 0XFE) {

	    delay_50ms(1000); 
		switch(KEY_MATRIX_POST) {
			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_POST != 0XFE);//等待按键松开
	}
	
	return key_value;
}

void main() {
	u8 key = 0;
	while(1) {
		key = key_matrix_ranks_scan();
		if (key !=0)
			SMG_A_DP_POST = gsmg_code[key - 1]; 	
	}		   
}

main函数里面的 if 作用,当没有这个if限制条件,由于在while循环里面执行的,当16个按键什么都不操作,无限返回0,一直输出数码管数组下标是-1,所以数码管最终显示不出来数字。当按下其中一个按键,返回一个键值,在数码管输出该键值的数字,由于程序一直在while执行的,程序会不停的执行,不停的返回键值,每次返回0,输出数组下标-1的值,由于用户按了按键,会输出键值,但是很短暂,因为没有在数码管输出数字后进行暂停,最终会在数码管输出按键键值会一闪而过。

当有了if限制条件,当用户按下按键后,得到一个键值输出在数码管后,当之后什么都不操作,会一直返回0,那么就不会对数码管显示的数字赋予新的值

5.线翻转代码

c 复制代码
#include <reg51.h>

typedef unsigned int u16;
typedef unsigned char u8;


#define KEY_MATRIX_POST P1
#define SMG_A_DP_POST P0 

u8 gsmg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共阴数码管0-F

void delay_50ms(u16 us) {
	while(us--);
}

u8 key_matrix_flip_scan(void) {		//线翻转
    u8 key_value = 0;

    KEY_MATRIX_POST = 0X0F;
    if (KEY_MATRIX_POST != 0X0F) {
   		delay_50ms(1000); 
		if (KEY_MATRIX_POST != 0X0F) {
			switch(KEY_MATRIX_POST) {		       //找列
				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_POST = 0XF0;
			switch(KEY_MATRIX_POST) {		       //找行
				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_POST != 0XF0); //松手检测
		} 			
   }
   return key_value;
}
void main() {
	u8 key = 0;
	while(1) {
		//key = key_matrix_ranks_scan();
		key = key_matrix_flip_scan();
		if (key !=0)
			SMG_A_DP_POST = gsmg_code[key - 1]; 	
	}		   
}

6.原理图

相关推荐
叶子2024222 小时前
电力系统分析---对称分量法
算法
代码游侠2 小时前
学习笔记——51单片机学习
笔记·stm32·单片机·嵌入式硬件·51单片机
千金裘换酒3 小时前
LeetCode 二叉树的最大深度 递归+层序遍历
算法·leetcode·职场和发展
爱敲代码的TOM3 小时前
详解一致性哈希算法
算法·哈希算法
松涛和鸣3 小时前
DAY52 7-Segment Display/GPIO/Buttons/Interrupts/Timers/PWM
c语言·数据库·单片机·sqlite·html
lzllzz233 小时前
递归的理解
算法·深度优先·图论
Echo缘3 小时前
关于在.cpp文件中包含c的头文件,编译报错问题
c语言·开发语言
小O的算法实验室3 小时前
2024年IEEE TITS SCI2区TOP,考虑无人机能耗与时间窗的卡车–无人机协同路径规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
派森先生3 小时前
排序算法-选择排序
算法·排序算法