矩阵键盘的基本操作

发布时间 2023-10-05 11:26:39作者: 夏日清`凉

矩阵键盘的基本操作

1、矩阵键盘的扫描思想
与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。我们以4X4的矩阵键盘为例,试着探讨其工作方式和扫描思路。

162041kqz3pk95ykxfa1nh.png.thumb

在上面的矩阵键盘中,要识别出黄色按键的按下状态,应该怎么做呢?
对于矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:
<1> R1输出点电平,R2、R3、R4输出高电平,逐个读取判断列信号,如果都为高电平则R1行上没有按键按下。
<2> R2输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
<3> R3输出点电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
<4> R4输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
如此循环往复,扫描的按键的状态。
我们知道有按键按下动作,那么又怎么知道是哪一个按键按下呢?这时,我们最好定义一个键值全局变量,给矩阵行列上的每一个的按键编一个唯一的号码。当扫描的某一行某一列的按键动作后,把对应的编号复制给键值变量,这样我们判断这个键值,就知道是那个按键有触发动作了。

20231004170145

由上可知:

对于该单片机与51单片机相比的差别在于电路变化,其P37=>P44 ,P36=>P42,且都按下后为低电平

代码如下:

#include <REGX52.H>
// 由于51单片机没有对于P4口的定义
sfr P4 = 0XC0;
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;


sbit R5 = P3^4;
sbit R6 = P3^5;
sbit R7 = P4^2;
sbit R8 = P4^4;
// 此数码管为共阳数码管
unsigned char code num[] = {
	0xc0,  //0  // 1100 0000
	0xf9,  //1      // 1111 1001
	0xa4,  //2      // 1010 0100
	0xb0,  // 3     // 1011 0000
	                // dp g f e   d c b a  
	0x99,      // 4         1001      1001
	0x92,       // 5       1 0 0 1   0 0 10
	0x82,           // 6   1  000    0010
	0xf8, 	// 7       1111   1000
	0x80,       // 8        1000  0000
	0x90,            // 9     1001 0000
	0x88,             // A       1000   1000
	0x83,                 // b    1000  0011
	0xc6,        	// C     1100 0110
	0xa1,              // d    1010   0001
	0x86,                   //E    1000  0110
	0x8e                     // F   1000  1110
};
// 单片机使能
void SelectHC573(unsigned char chinnel) {
	switch(chinnel) {  // LED使能
		case 4: P2 =(P2 & 0x1f) | 0x80;
		break;     // 蜂鸣器和继电器使能
		case 5: P2 =(P2 & 0x1f) | 0xa0;
		break;  // 数码管位选使能
		case 6: P2 =(P2 & 0x1f) | 0xc0;
		break;   // 数码管段选使能
		case 7: P2 =(P2 & 0x1f) | 0xe0;
		break;
		
	}
}
// 初始化
void SystemInit(void) {
	SelectHC573(4);
	P0 = 0xFF;  // LED回到初始状态,全关
	SelectHC573(5);
	P0 = 0x00;  // 关闭蜂鸣器和继电器
}

void DisplayKeyNum(unsigned char value) {
	SelectHC573(6);
	P0 = 0x01;   // 选择数码管第一位使能
	SelectHC573(7);
	P0 = value;  // 段选传值
}
unsigned char Keynum;
void ScanKeyMulti(void) {
    // 此采用逐行扫描模式
    // 首先将该行所在的列全部置为高电平,如果有该行所在的列被按下时,就为低电平
	R1 = 0;  // P30 = 0  
	R2=R3=R4=R5=R6=R7=R8=1;
	if(R8==0){while(R8==0);Keynum=0;DisplayKeyNum(num[Keynum]);}  // S7
	if(R7==0){while(R7==0);Keynum=1;DisplayKeyNum(num[Keynum]);} // S11
	if(R6==0){while(R6==0);Keynum=2;DisplayKeyNum(num[Keynum]);} // S15
	if(R5==0){while(R5==0);Keynum=3;DisplayKeyNum(num[Keynum]);} // S19
	
	R2 = 0; // P31 = 0
	R1=R3=R4=R5=R6=R7=R8=1;
	if(R8==0){while(R8==0);Keynum=4;DisplayKeyNum(num[Keynum]);} // S6
	if(R7==0){while(R7==0);Keynum=5;DisplayKeyNum(num[Keynum]);} // S10
	if(R6==0){while(R6==0);Keynum=6;DisplayKeyNum(num[Keynum]);} // S14
	if(R5==0){while(R5==0);Keynum=7;DisplayKeyNum(num[Keynum]);} // S18
	
	R3 = 0;  // P32=0
	R1=R2=R4=R5=R6=R7=R8=1;
	if(R8==0){while(R8==0);Keynum=8;DisplayKeyNum(num[Keynum]);} // S5
	if(R7==0){while(R7==0);Keynum=9;DisplayKeyNum(num[Keynum]);} // S9
	if(R6==0){while(R6==0);Keynum=10;DisplayKeyNum(num[Keynum]);} // S13
	if(R5==0){while(R5==0);Keynum=11;DisplayKeyNum(num[Keynum]);} //S17
	
	R4 = 0; // P33 = 0
	R1=R3=R2=R5=R6=R7=R8=1;
	if(R8==0){while(R8==0);Keynum=12;DisplayKeyNum(num[Keynum]);} // S4
	if(R7==0){while(R7==0);Keynum=13;DisplayKeyNum(num[Keynum]);} // S8
	if(R6==0){while(R6==0);Keynum=14;DisplayKeyNum(num[Keynum]);} // S12
	if(R5==0){while(R5==0);Keynum=15;DisplayKeyNum(num[Keynum]);} // S16
}
void main() {
	SystemInit();
	while(1) {
		ScanKeyMulti();
	}

}