1840 views|3 replies

3191

Posts

0

Resources
The OP
 

Matrix keyboard program problem [Copy link]

I wrote a matrix keyboard program, but there is a problem. Sometimes when I press a key, it returns the key value twice, and sometimes it returns 0 (no key is detected)

I debug, return the key value, and send it to the network debugging assistant through the network port.

Schematic diagram:

//初始化PA8和PD2为输出口.并使能这两个口的时钟		    
//LED IO初始化
void KEY_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PA,PD端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;	    		 //LED1-->PD.2 端口配置, 推挽输出
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
	
 
}
void Hang_Output(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PA,PD端口时钟
	
 
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;	    		 //LED1-->PD.2 端口配置, 推挽输出
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
	
}
void Hang_Input(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PA,PD端口时钟
	
 
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;	    		 //LED1-->PD.2 端口配置, 推挽输出
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
	
}
void Lie_Input(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PA,PD端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
}

void Lie_Output(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PA,PD端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
}
unsigned char GetKey(void)
{
	
	unsigned char keyvalue = 0;
	uint16_t hangvalue=0,lievalue=0;
	
// 第1回合第1步
	KEY_Init();
	delay_us(20);
	GPIO_ResetBits(GPIOE,GPIO_Pin_6); 						 //PE.6 输出低 
	GPIO_ResetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出低
	GPIO_ResetBits(GPIOE,GPIO_Pin_4); 						 //PE.4 输出低 
	GPIO_ResetBits(GPIOE,GPIO_Pin_3); 						 //PE.3 输出低
	
	
	hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
	if (hangvalue != 0x3f)// 从IO口输入,读IO口
	{
	// 读出的不是0x0f说明有按键被按下
	// 第1回合第2步:读出端口从读出值来判断是哪一行
		delay_ms(20);
		GPIO_ResetBits(GPIOE,GPIO_Pin_6); 						 //PE.6 输出低 
		GPIO_ResetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出低
		GPIO_ResetBits(GPIOE,GPIO_Pin_4); 						 //PE.4 输出低 
		GPIO_ResetBits(GPIOE,GPIO_Pin_3); 						 //PE.3 输出低
		
		
		hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
		if (hangvalue != 0x3f)// 从IO口输入,读IO口
		{
			Hang_Output();
			Lie_Input();
			delay_us(20);
		// 第一回合中算出行号
			switch (hangvalue)
			{
				case 0x1F:
						
						GPIO_ResetBits(GPIOB,GPIO_Pin_9); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=4;
								break;
							case 0x0b:
								keyvalue=9;
								break;
							case 0x0d:
								keyvalue=14;
								break;
							case 0x0e:
								keyvalue=20;
								break;
							default :
								break;
						}
					break;
				case 0x2F:
						
						GPIO_ResetBits(GPIOB,GPIO_Pin_8); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=5;
								break;
							case 0x0b:
								keyvalue=10;
								break;
							case 0x0d:
								keyvalue=15;
								break;
							case 0x0e:
								keyvalue=21;
								break;
							default :
								break;
						}
					break;
				case 0x37: 
						
						GPIO_ResetBits(GPIOB,GPIO_Pin_7); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=6;
								break;
							case 0x0b:
								keyvalue=11;
								break;
							case 0x0d:
								keyvalue=16;
								break;
							case 0x0e:
								keyvalue=22;
								break;
							default :
								break;
						}
					break;
				case 0x3B:
						
						GPIO_ResetBits(GPIOE,GPIO_Pin_2); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=1;
								break;
							case 0x0b:
								keyvalue=6;
								break;
							case 0x0d:
								keyvalue=11;
								break;
							case 0x0e:
								keyvalue=17;
								break;
							default :
								break;
						}
					break;
				case 0x3D: 
						
						GPIO_ResetBits(GPIOE,GPIO_Pin_1); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=2;
								break;
							case 0x0b:
								keyvalue=7;
								break;
							case 0x0d:
								keyvalue=12;
								break;
							case 0x0e:
								keyvalue=18;
								break;
							default :
								break;
						}
					break;
				case 0x3E: 
						
						GPIO_ResetBits(GPIOE,GPIO_Pin_0); 
						lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
						switch(lievalue)
						{
							case 0x07:
								keyvalue=3;
								break;
							case 0x0b:
								keyvalue=8;
								break;
							case 0x0d:
								keyvalue=13;
								break;
							case 0x0e:
								keyvalue=19;
								break;
							default :
								break;
						}
					break;
				default: break;
				
			}
			Hang_Input();
			Lie_Output();
			delay_us(20);
			GPIO_ResetBits(GPIOE,GPIO_Pin_6); 						 //PE.6 输出低 
			GPIO_ResetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出低
			GPIO_ResetBits(GPIOE,GPIO_Pin_4); 						 //PE.4 输出低 
			GPIO_ResetBits(GPIOE,GPIO_Pin_3); 						 //PE.3 输出低
			
			hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
			while (hangvalue != 0x3f)
			{
				
				hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
			}
			return keyvalue;
		}
		return 0;
	}
	return 0;
}

Can someone please take a look, what's the problem? Thanks!

This post is from stm32/stm8

Latest reply

Yours is too long. It can be solved in a few sentences.   Details Published on 2020-6-20 21:28
Personal signature为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
 

1w

Posts

142

Resources
2
 

First of all, the original poster's circuit design is not good enough. When the number of rows and columns is more than an 8-bit IO port, try to use a certain IO sequence for each row and column separately. However, the original poster separated the columns, which will increase the complexity of programming and make it easy to make mistakes. Another problem is the working mode. The problem encountered by the original poster can only occur when the active polling is continuously performed, and the polling cycle setting is unreasonable. Try not to use active polling for the keyboard, which takes up too much time and consumes more power. Try to use interrupts to start keyboard scanning, and debounce when scanning.

A highly simplified process: a key is pressed, scan is started - if the scan value is different from the initial value, it means a key is pressed - after debounce, judge again - if the key value is the same as the previous value, return the key value, if it is different, give up. The debounce cycle can generally be about 50mS.

This post is from stm32/stm8

Comments

Thanks! The circuit was not designed by me.  Details Published on 2020-6-18 13:48
 
Personal signature上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
 

3191

Posts

0

Resources
3
 
chunyang posted on 2020-6-18 13:31 The original poster's circuit design is not good enough. When the number of rows and columns exceeds one 8-bit IO port, try to use a certain IO sequence for the rows and columns separately, but the original poster separated the columns, ...

Thanks! The circuit was not designed by me.

This post is from stm32/stm8
 
Personal signature为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
 

4005

Posts

0

Resources
4
 

Yours is too long. It can be solved in a few sentences.

This post is from stm32/stm8
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list