51单片机 -矩阵键盘

1> 硬件设计


1.1> 实物(4X4矩阵)

1


1.2> 原理图

1.2


1.3> PCB

1.3

轻触按键内部结构:
1



2> 行列反转扫描原理

2.1> 目的

4X4键盘中按下任意按键,都能识别;


2.2> 步骤1: 确定按键X(坐标)坐标

写端口:P2 = 0x 0F,
读端口P2值, 假如【K00】按下, 则P2.0电平拉低,读取值为 0x0E(0b 0000 1110)

1

  • 编写代码测试:
#include <reg52.h>

/* byte device */
#define LED_PORT P0
#define KEY_PORT P2

int main(void)
{
	while (1) {
		KEY_PORT = 0x0F;
		
		LED_PORT = KEY_PORT;		
	}
}

通过测试,
【K00】~ 【K03】按下时,D1灯亮; // KEY_PORT == 0x0E;
【K10】 ~【K13】按下时,D2灯亮; // KEY_PORT == 0x0D;
【K20】~ 【K23】按下时,D3灯亮; // KEY_PORT == 0x0B;
【K30】~ 【K33】按下时,D4灯亮 // KEY_PORT == 0x07;

得出结论:
通过对KEY_PORT 写0x0F,和读,能确定按键的X(行)坐标;




2.3> 步骤2: 确定按键Y(坐标)坐标

写端口:P2 = 0xF0;
读端口P2值, 假如【K00】按下, 则P2.0电平拉低,读取值为 0xE0(0b 1110 0000);

2.2

  • 编写代码测试
#include <reg52.h>

/* byte device */
#define LED_PORT P0
#define KEY_PORT P2

int main(void)
{
	while (1) {
		KEY_PORT = 0xF0;
		
		LED_PORT = KEY_PORT;		
	}
}

【K00】~ 【K30】按下时,D5灯亮; // KEY_PORT == 0xE0;
【K01】 ~【K31】按下时,D6灯亮; // KEY_PORT == 0xD0;
【K02】~ 【K32】按下时,D7灯亮; // KEY_PORT == 0xB0;
【K03】~ 【K33】按下时,D8灯亮 // KEY_PORT == 0x70;
对KEY_PORT 写0xF0, 读值,能确定key的Y(列)坐标;



2.4> 步骤3: 根据按键(X,Y)坐标,给按键编码(0~F);

【K00】:X坐标(0x0E), Y坐标(0xE0);0 + 0 = 0
【K01】:X坐标(0x0E), Y坐标(0xD0);1 + 0 = 1
【K02】:X坐标(0x0E), Y坐标(0xB0);2 + 0 = 2
【K03】:X坐标(0x0E), Y坐标(0x70);3 + 0 = 3

【K10】:X坐标(0x0D), Y坐标(0xE0);0+4 = 4
【K11】:X坐标(0x0D), Y坐标(0xD0);1+4 = 5
【K12】:X坐标(0x0D), Y坐标(0xB0);2+ 4 = 6
【K13】:X坐标(0x0D), Y坐标(0x70);3+4 = 7

【K20】:X坐标(0x0B), Y坐标(0xE0);0+8 = 8
【K21】:X坐标(0x0B), Y坐标(0xD0);1+8 = 9
【K22】:X坐标(0x0B), Y坐标(0xB0);2+ 8 = 10 (A)
【K23】:X坐标(0x0B), Y坐标(0x70);3+ 8 = 11 (B)

【K30】:X坐标(0x07), Y坐标(0xE0);0+12 = 12 (C)
【K31】:X坐标(0x07), Y坐标(0xD0);1+ 12 = 13 (D)
【K32】:X坐标(0x07), Y坐标(0xB0);2+12 = 14 (E)
【K33】:X坐标(0x07), Y坐标(0x70);3+ 12 = 15 (F)



有什么规律?X坐标,与Y坐标,按位或运算


X坐标: ---------- Y坐标
0x0E == 0; ------0xE0 == 0
0x0D == 4; ------0xD0 == 1
0x0B == 8; ------0xB0 == 2
0x07 == 12; ------0x70 == 3



3> 程序设计

  • 设计要求:
  • 给按键编码0~F,并在数码管上显示;
#include <reg52.h>

typedef unsigned char	uchar8_t;
typedef unsigned short	ushort16_t;

/* byte device */
#define NUM_PORT P0
#define KEY_PORT P2


/*0~F, off*/
unsigned char DS_code[17] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99,
							 0x92, 0x82, 0xF8, 0x80, 0x90,
							 0x88, 0x83, 0xa7, 0xa1, 0x86,
							 0x8E, 0xFF };

void digit_ctrl(uchar8_t num);
uchar8_t key_scan(void);

/**
 *  main
 */
int main(void)
{
	uchar8_t key_val = 0xFF;	

	while (1) {
		key_val = key_scan();

		if (key_val != 0xFF) {
			digit_ctrl(key_val);
		} else {
			digit_ctrl(DS_code[16]);
		}		
	}
}


uchar8_t key_scan(void)
{
	uchar8_t X_val = 0;
	uchar8_t Y_val = 0;
	uchar8_t K_val = 0xFF;
	
	/* Step 1> Find X pointer  */
	KEY_PORT = 0x0F;	// Write 0000 1111;
	
	if (KEY_PORT != 0x0F) {
		switch (KEY_PORT) {
		case 0x0E: 
			X_val = 0;
			break;

		case 0x0D: 
			X_val = 4;
			break;

		case 0x0B:
			X_val = 8;
			break;

		case 0x07:
			X_val = 12;
			break;

		default:
			X_val = 0;
			break;		
		}

		/* Step 2> Find Y pointer */
		KEY_PORT = 0xF0;	// Write 1111 0000;
		
		if (KEY_PORT != 0xF0) {
			switch (KEY_PORT) {
			case 0xE0:
				Y_val = 0;
				break;

			case 0xD0:
				Y_val = 1;
				break;

			case 0xB0:
				Y_val = 2;
				break;

			case 0x70:
				Y_val = 3;
				break;   // Lost the 'break'

			default:
				Y_val = 0;
				break;			
			}
				
			/* Step 3> Find Key code */
			K_val = X_val + Y_val;	
		}
									
	} else {
		K_val = 0xFF;
	}
	
	return	K_val; 
}



/**
 * Ctrl digit number 
 */
void digit_ctrl(uchar8_t num)
{

	NUM_PORT = DS_code[num];

}


// end file




4> 视频链接

🔗 B站-视频教程

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值