2021/11/10矩阵键盘问题

预备知识:行列扫描识别原理

2021/11/10矩阵键盘问题_第1张图片

线扫描法原理和应用

1.利用矩阵键盘实现独立键盘功能(加一个接地线)

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P3  //位选IO口
#define N  4           //数码管个数
sbit KEYIN1=P2^0;
sbit KEYIN2=P2^1;
sbit KEYIN3=P2^2;
sbit KEYIN4=P2^3;
unsigned char LEDBUF[]={
     8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
     
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
     
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=1;
			if(!KEYIN2)
				KeyNum=2;
			if(!KEYIN3)
				KeyNum=3;
			if(!KEYIN4)
				KeyNum=4;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	return KeyNum;
}

void main()
{
     
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
     
		switch(Key_Scan())
		{
     
			case 0:break;
			case 1:LEDBUF[3]=1;break;
			case 2:LEDBUF[3]=2;break;
			case 3:LEDBUF[3]=3;break;
			case 4:LEDBUF[3]=4;break;
			default:break;
		}
		Display();
	}
}

2021/11/10矩阵键盘问题_第2张图片

拓展:按下不同的键显示不同的数(简单方法的实现)

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P3  //位选IO口
#define N  4           //数码管个数
sbit KEYIN1=P2^0;
sbit KEYIN2=P2^1;
sbit KEYIN3=P2^2;
sbit KEYIN4=P2^3;

sbit KEYOUT1=P2^4;
sbit KEYOUT2=P2^5;
sbit KEYOUT3=P2^6;
sbit KEYOUT4=P2^7;

unsigned char LEDBUF[]={
     8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
     
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
     
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=0;KEYOUT2=1;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=1;
			if(!KEYIN2)
				KeyNum=2;
			if(!KEYIN3)
				KeyNum=3;
			if(!KEYIN4)
				KeyNum=4;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=0;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=5;
			if(!KEYIN2)
				KeyNum=6;
			if(!KEYIN3)
				KeyNum=7;
			if(!KEYIN4)
				KeyNum=8;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=0;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=9;
			if(!KEYIN2)
				KeyNum=10;
			if(!KEYIN3)
				KeyNum=11;
			if(!KEYIN4)
				KeyNum=12;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=1;KEYOUT4=0;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=13;
			if(!KEYIN2)
				KeyNum=14;
			if(!KEYIN3)
				KeyNum=15;
			if(!KEYIN4)
				KeyNum=16;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	return KeyNum;
}

void main()
{
     
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
     
		switch(Key_Scan())
		{
     
			case 0:break;
			case 1:LEDBUF[3]=1;break;
			case 2:LEDBUF[3]=2;break;
			case 3:LEDBUF[3]=3;break;
			case 4:LEDBUF[3]=4;break;
			case 5:LEDBUF[3]=5;break;
			case 6:LEDBUF[3]=6;break;
			case 7:LEDBUF[3]=7;break;
			case 8:LEDBUF[3]=8;break;
			case 9:LEDBUF[3]=9;break;
			case 10:LEDBUF[3]=0;break;
			case 11:LEDBUF[3]=10;break;
			case 12:LEDBUF[3]=11;break;
			case 13:LEDBUF[3]=12;break;
			case 14:LEDBUF[3]=13;break;
			case 15:LEDBUF[3]=14;break;
			case 16:LEDBUF[3]=15;break;
			default:break;
		}
		Display();
	}
}

2021/11/10矩阵键盘问题_第3张图片

改进:由于main()函数里面的switch-case语句太多了,我们直接用Key_Scan()返回的数值作为想显示的数传进去,注意当按下“0”键时KeyNum=0,以后的KeyNum都需要减1

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P3  //位选IO口
#define N  4           //数码管个数
sbit KEYIN1=P2^0;
sbit KEYIN2=P2^1;
sbit KEYIN3=P2^2;
sbit KEYIN4=P2^3;

sbit KEYOUT1=P2^4;
sbit KEYOUT2=P2^5;
sbit KEYOUT3=P2^6;
sbit KEYOUT4=P2^7;

unsigned char LEDBUF[]={
     8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
     
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
     
	//unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	static unsigned char KeyNum=23;//静态变量初始化一次就不会再次初始化了
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=0;KEYOUT2=1;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=1;
			if(!KEYIN2)
				KeyNum=2;
			if(!KEYIN3)
				KeyNum=3;
			if(!KEYIN4)
				KeyNum=4;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=0;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=5;
			if(!KEYIN2)
				KeyNum=6;
			if(!KEYIN3)
				KeyNum=7;
			if(!KEYIN4)
				KeyNum=8;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=0;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=9;
			if(!KEYIN2)
				KeyNum=0;
			if(!KEYIN3)
				KeyNum=10;
			if(!KEYIN4)
				KeyNum=11;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=1;KEYOUT4=0;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=12;
			if(!KEYIN2)
				KeyNum=13;
			if(!KEYIN3)
				KeyNum=14;
			if(!KEYIN4)
				KeyNum=15;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	return KeyNum;
}

void main()
{
     
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
     
		LEDBUF[3]=Key_Scan();
		Display();
	}
}

线反转法的原理及其应用(目前还存在一些问题有待改进,主要是按了按键会影响P0口)

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P3  //位选IO口
#define N  4           //数码管个数
#define KEYPORT P2

unsigned char LEDBUF[]={
     8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
     
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
     
	unsigned char temp,temp2
	static unsigned char KeyNum=20;
	KEYPORT=0xf0;
	temp=KEYPORT;
	if(temp!=0xf0)
	{
     
		DelayXms(10);
		if(temp!=0xf0)
		{
     
			temp=KEYPORT&0xf0;
			KEYPORT=0x0f;
			temp2=KEYPORT&0x0f;
		}
	}
	switch(temp+temp2)
	{
     
    case 0xee:KeyNum=1;break;
		case 0xed:KeyNum=2;break;
		case 0xeb:KeyNum=3;break;
		case 0xe7:KeyNum=4;break;
		
		case 0xde:KeyNum=5;break;
		case 0xdd:KeyNum=6;break;
		case 0xdb:KeyNum=7;break;
		case 0xd7:KeyNum=8;break;
		
		case 0xbe:KeyNum=9;break;
		case 0xbd:KeyNum=0;break;
		case 0xbb:KeyNum=10;break;
		case 0xb7:KeyNum=11;break;
		
		case 0x7e:KeyNum=12;break;
		case 0x7d:KeyNum=13;break;
		case 0x7b:KeyNum=14;break;
		case 0x77:KeyNum=15;break;
		default:break;
	}
	
	return KeyNum;
}

void main()
{
     
	//unsigned char i;
	
	while(1)
	{
     
		LEDBUF[0]=23;
	    LEDBUF[1]=23;
	    LEDBUF[2]=23;
		LEDBUF[3]=Key_Scan();
		Display();
	}
}

2021/11/10矩阵键盘问题_第4张图片

3.外部中断控制矩阵键盘(线翻转法起作用了,真的很奇怪)

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P1  //位选IO口
#define N  4           //数码管个数
#define KEYPORT P2
unsigned char LEDBUF[]={
     22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
unsigned char KeyNum;
unsigned char KeyPressFlag;
void EX0_Init();
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
//段码表
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	//static unsigned char i=0;
	unsigned char i;
	//1,送段码
	GPIO_DIG=leddata[LEDBUF[i]];
	//2.送位选
	GPIO_PLACE=PLACE_CODE[i];
	//3.延时1ms<10ms
	DelayXms(1);
	//4.消隐
	GPIO_DIG=0xff;
	i++;
	if(N==i)
	{
     
		i=0;
	}
}


void Dis_Service()
{
     
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	LEDBUF[3]=KeyNum;
}
unsigned char Key_Scan()
{
     
	unsigned char temp,temp2;
	static unsigned char KeyNum=20;
	KEYPORT=0xf0;
	temp=KEYPORT;
	if(temp!=0xf0)
	{
     
		DelayXms(10);
		if(temp!=0xf0)
		{
     
			temp=KEYPORT&0xf0;
			KEYPORT=0x0f;
			temp2=KEYPORT&0x0f;
		}
	}
	switch(temp+temp2)
	{
     
    case 0xee:KeyNum=1;break;
		case 0xed:KeyNum=2;break;
		case 0xeb:KeyNum=3;break;
		case 0xe7:KeyNum=4;break;
		
		case 0xde:KeyNum=5;break;
		case 0xdd:KeyNum=6;break;
		case 0xdb:KeyNum=7;break;
		case 0xd7:KeyNum=8;break;
		
		case 0xbe:KeyNum=9;break;
		case 0xbd:KeyNum=0;break;
		case 0xbb:KeyNum=10;break;
		case 0xb7:KeyNum=11;break;
		
		case 0x7e:KeyNum=12;break;
		case 0x7d:KeyNum=13;break;
		case 0x7b:KeyNum=14;break;
		case 0x77:KeyNum=15;break;
		default:break;
	}
	
	return KeyNum;
}



void main()
{
     
	//unsigned int i;
	EX0_Init();
	P2=0x0f;
	while(1)
	{
     
		if(KeyPressFlag==1)
		{
     
			KeyPressFlag=0;//清0
			KeyNum=Key_Scan();
		}
		Dis_Service();
		Display();
	}
}

void EX0_Init()
{
     
	IT0=1;
	EX0=1;
	EA=1;
}

void EX0_ISR(void) interrupt 0
{
     
    KeyPressFlag=1;
}
	


2021/11/10矩阵键盘问题_第5张图片
**

补充:用线扫描法(好像又不起作用了,必须加上一句话)

#include
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P1  //位选IO口
#define N  4           //数码管个数
#define KEYPORT P2

sbit KEYIN1=P2^0;
sbit KEYIN2=P2^1;
sbit KEYIN3=P2^2;
sbit KEYIN4=P2^3;

sbit KEYOUT1=P2^4;
sbit KEYOUT2=P2^5;
sbit KEYOUT3=P2^6;
sbit KEYOUT4=P2^7;
unsigned char LEDBUF[]={
     22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={
     0x01,0x02,0x04,0x08};//位信号
unsigned char KeyNum;
unsigned char KeyPressFlag;
void EX0_Init();
void DelayXms(unsigned int xms)
{
     
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
//段码表
unsigned char leddata[]={
      

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
     
	//static unsigned char i=0;
	unsigned char i;
	//1,送段码
	GPIO_DIG=leddata[LEDBUF[i]];
	//2.送位选
	GPIO_PLACE=PLACE_CODE[i];
	//3.延时1ms<10ms
	DelayXms(1);
	//4.消隐
	GPIO_DIG=0xff;
	i++;
	if(N==i)
	{
     
		i=0;
	}
}


void Dis_Service()
{
     
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	LEDBUF[3]=KeyNum;
}

unsigned char Key_Scan()
{
     
	//unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	static unsigned char KeyNum=23;//静态变量初始化一次就不会再次初始化了
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=0;KEYOUT2=1;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=1;
			if(!KEYIN2)
				KeyNum=2;
			if(!KEYIN3)
				KeyNum=3;
			if(!KEYIN4)
				KeyNum=4;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=0;KEYOUT3=1;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=5;
			if(!KEYIN2)
				KeyNum=6;
			if(!KEYIN3)
				KeyNum=7;
			if(!KEYIN4)
				KeyNum=8;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=0;KEYOUT4=1;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=9;
			if(!KEYIN2)
				KeyNum=0;
			if(!KEYIN3)
				KeyNum=10;
			if(!KEYIN4)
				KeyNum=11;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	
	KEYIN1=1;KEYIN2=1;KEYIN3=1;KEYIN4=1;
	KEYOUT1=1;KEYOUT2=1;KEYOUT3=1;KEYOUT4=0;
	if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查按键是否被按下
	{
     
		DelayXms(8);
		if(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4)//检查具体哪一个按键被按下
		{
     
			if(!KEYIN1)
				KeyNum=12;
			if(!KEYIN2)
				KeyNum=13;
			if(!KEYIN3)
				KeyNum=14;
			if(!KEYIN4)
				KeyNum=15;
		}while(!KEYIN1||!KEYIN2||!KEYIN3||!KEYIN4);//松手等待
	}
	return KeyNum;
}

void main()
{
     
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
     
		LEDBUF[3]=Key_Scan();
		Display();
	}
}



void main()
{
     
	//unsigned int i;
	EX0_Init();
	P2=0x0f;//给一个中断信号
	while(1)
	{
     
		if(KeyPressFlag==1)
		{
     
			KeyPressFlag=0;//清0
			KeyNum=Key_Scan();
			P2=0x0f;//线扫描法需要再给一个中断信号,但是嫌犯转发法不需要
		}
		Dis_Service();
		Display();
	}
}

void EX0_Init()
{
     
	IT0=1;
	EX0=1;
	EA=1;
}

void EX0_ISR(void) interrupt 0
{
     
    KeyPressFlag=1;
}

2021/11/10矩阵键盘问题_第6张图片

**

你可能感兴趣的:(矩阵,单片机)