536|3

3048

帖子

0

资源

纯净的硅(中级)

矩阵键盘程序问题 [复制链接]

我写了个矩阵键盘程序,有点问题,有时按下一个按键,返回两次键值,有时返回0(没有检测到按键)

 

我调试,返回键值,通过网口发送到网络调试助手。

原理图:

5.jpg

//初始化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;
}

大神看看,哪里有问题?谢谢!

此帖出自stm32/stm8论坛
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。

回复

1万

帖子

143

资源

版主

楼主电路首先设计的不够好。行列数多于一个8位IO口时,尽量行列单独使用某个IO序列,楼主却把列给拆开了,这会导致程序编制时复杂性提高,容易出错。再有就是工作模式问题,楼主所遇问题只有在不断主动轮询时才可能出现且轮询周期设置不合理。键盘尽量不要用主动轮询,太占计时,功耗也比较大,尽量利用中断来启动键盘扫描,扫描时要有消抖处理。

高度简化的流程:有键按下,启动扫描——判断出扫描值与初值不同,说明确实有键按下——消抖后再次判断——与前值相同则返回键值,不同则放弃。消抖周期一般可取50mS左右。

点评

谢谢!电路不是我设计的。  详情 回复 发表于 2020-6-18 13:48
个人签名上传了一些书籍资料,也许有你想要的:http://download.eeworld.com.cn/user/chunyang

回复

3048

帖子

0

资源

纯净的硅(中级)

chunyang 发表于 2020-6-18 13:31 楼主电路首先设计的不够好。行列数多于一个8位IO口时,尽量行列单独使用某个IO序列,楼主却把列给拆开了, ...

谢谢!电路不是我设计的。

个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。

回复

3884

帖子

0

资源

版主

你这个太长了,几句就能搞定的事


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/8 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表