[求助] 矩阵键盘的问题

chenbingjy   2020-8-21 11:46 楼主

我用STM32写矩阵键盘程序。以前发过几个帖子,一直没搞好。

 

电路图:

1.jpg

代码:

/*******************************************************************************
* 函数名  : TIM4_IRQHandler
* 描述    : 定时器4中断断服务函数
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
       static uint8_t    key_Pace = 0;
       static uint32_t  old_KeyVal;
       

        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {   //设定4ms中断一次
                TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

               //键盘检测可以做成for循环4次
               // PE.3,5,4设施成输入 ,PE6输出L
							 GPIO_SetBits(GPIOE,GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
							 GPIO_ResetBits(GPIOE, GPIO_Pin_6 ); 
							 delay_us(XD);	
               new_KeyVal = (~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f ;
               //PE.3输入,PE5输出L
							 GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_4);
							 GPIO_ResetBits(GPIOE, GPIO_Pin_5 ); 
								delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f) << 5);
               //PE.4输入,PE4输出L
							 GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_3);
							 GPIO_ResetBits(GPIOE, GPIO_Pin_4 ); 
								delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4))) & 0x3f) << 10);
               //PE.5输入,PE3输出L
							 GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5);
							 GPIO_ResetBits(GPIOE, GPIO_Pin_3 ); 
							 delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4)))& 0x3f ) << 16);
               //恢复键盘待机,PE.6,5,4,  3全部输出L
								GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_3);
							  
                key_Pace ++;
                if(key_Pace < 6)
                {  //键盘按下去抖, 时间4ms×6 = 24ms ,也可以设置6~8ms中断一次,响应该值调整
                    if((new_KeyVal == 0) || new_KeyVal != old_KeyVal)  //无键操作或者键值不对应
                       {old_KeyVal = new_KeyVal;  key_Pace = 0;}                      //返回等待键盘状态
                }
                else if(key_Pace == 6)
                {  
										
										//键值处理,或启动发送
                     switch(old_KeyVal)
                    {  //键盘比较离散或允许组合键采用这个方法
                    case   0x000001:        //键盘1
														keyvalue=3;
                              break;
                    case   0x000002:        //键盘2
														keyvalue=2;
                              break;
                    case   0x000004:        //键盘3
														keyvalue=1;
                              break;
                    case   0x000008:        //键盘4
															keyvalue=5;
                              break;
                    case   0x000010:        //键盘5
															keyvalue=4;
                              break;
                    case   0x000020:        //键盘6
														keyvalue=8;
                              break;
                    case   0x000040:        //键盘7
														keyvalue=7;
                              break;
                    case   0x000080:        //键盘8
														keyvalue=6;
                              break;
                    case   0x000100:        //键盘9
														keyvalue=10;
                              break;
                    case   0x000200:        //键盘10
														keyvalue=9;
                              break;
                    case   0x000400:        //键盘11
														keyvalue=13;
                              break;
                    case   0x000800:        //键盘12
														keyvalue=12;
                              break;
                    case   0x001000:        //键盘13
														keyvalue=11;
                              break;
                    case   0x002000:        //键盘14
															keyvalue=16;
                              break;
                    case   0x004000:        //键盘15
															keyvalue=15;
                              break;
                    case   0x008000:        //键盘16
															keyvalue=14;
                              break;
                    case   0x010000:        //键盘17
															keyvalue=19;
                              break;
                    case   0x020000:        //键盘18
															keyvalue=18;
                              break;
                    case   0x040000:        //键盘19
															keyvalue=17;
                              break;
                    case   0x080000:        //键盘20
															keyvalue=22;
                              break;
                    case   0x100000:        //键盘21
															keyvalue=21;
                              break;
                    case   0x200000:        //键盘22
															keyvalue=20;
                              break;

                    default:        //其它组合键盘
                              break;
                    }
// 可以用统筹方法组合好后统一发送数据到通讯口
										keynum=keyvalue ;
                    old_KeyVal = 0;
										
                }
                else if(key_Pace < 20)
                {   //键盘释放去抖
                    if(new_KeyVal != 0)  key_Pace = 6;    //等待键盘释放
                }
                else    key_Pace = 0;                               //键盘释放
        }
}

实际测试,发现按键3,8,12比较难按,不容易检测到,经常按了没反应。

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

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

回复评论 (20)

怎么代码显示不全?

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-21 11:47

写得太复杂了

点赞  2020-8-22 10:32

// PE.3,5,4设施成输入 ,PE6输出L 这个不对吧。都应该设置为输出啊。只是PE.3,5,4设施成输出高 ,PE6输出低。 

 

其实PB7,8,9  PE0  1 2做输出好

       PE3 4 5 6读

这样不用与或之类的事。

本帖最后由 damiaa 于 2020-8-23 23:11 编辑
点赞  2020-8-23 23:05
引用: damiaa 发表于 2020-8-23 23:05 // PE.3,5,4设施成输入 ,PE6输出L 这个不对吧。都应该设置为输出啊。只是PE.3,5,4设施成输出高 ,PE6 ...

那个注释有问题

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 08:21
引用: chenbingjy 发表于 2020-8-24 08:21 那个注释有问题

//如果按键值没有变化KeyValue=0 ModiFlag =0;按键按下ModiFlag置1 值在ModiFlag里 用完请清ModiFlag和ModiFlag

KeyVal[]是做消抖用。

unsigned char keytable[] ={3,2,1,5,4,8,7,6,10,9,13,12,11,16,15,14,,19,18,17,22,21,20};
void TIM4_IRQHandler(void)
{
       static uint32_t  KeyVal[6],KeyOldVal=0,KeyValue;
       static uint8_t KeyPoint=0,ModiFlag=0;
        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {   
               TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
               GPIO_SetBits(GPIOE,GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5); GPIO_ResetBits(GPIOE, GPIO_Pin_6 );  delay_us(XD);	
               new_KeyVal = (~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f ;
			   GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_4);GPIO_ResetBits(GPIOE, GPIO_Pin_5 );   delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f) << 5);
               GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_3); GPIO_ResetBits(GPIOE, GPIO_Pin_4 ); 	delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4))) & 0x3f) << 10); 
			   GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5); GPIO_ResetBits(GPIOE, GPIO_Pin_3 );  delay_us(XD);
               new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4)))& 0x3f ) << 16);
               GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_3);
			  
               KeyVal[KeyPoint++]= new_KeyVal; 
               if(KeyPoint >= 6) KeyPoint =0; 
			   if((KeyVal[0] == KeyVal[1])&&(KeyVal[0] == KeyVal[2])&&&&(KeyVal[0] == KeyVal[3])&&(KeyVal[0] == KeyVal[4])&&(KeyVal[0] == KeyVal[5]))
			   {	for(i=0;i<22;i++)
					{    
						if(KeyVal[0] &(1<<i))
							break;
					}	
					if(i >=22)
						KeyValue =0;
					else
						KeyValue =keytable[i];
						
					if(KeyValue != KeyOldVal)
					{
						KeyOldVal=KeyValue;
						ModiFlag=1;
					}
				}
		}			 
}

 

点赞  2020-8-24 09:40

中断里面还delay,这很不合适吧,中断程序要尽量断,你可以看看别人的按键程序的框架,不用定时器都能做好的。

点赞  2020-8-24 09:44
引用: 29447945 发表于 2020-8-24 09:44 中断里面还delay,这很不合适吧,中断程序要尽量断,你可以看看别人的按键程序的框架,不用定时器都能做好 ...

我现在就是不明白,有几个按键有问题。

我看了一些别人的矩阵键盘程序,都差不多

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 10:07
chenbingjy 发表于 2020-8-24 10:07 我现在就是不明白,有几个按键有问题。 我看了一些别人的矩阵键盘程序,都差不多

这里有一个简单的例程,你可以用这个完善下,不一定要用中断,只要保证程序进scan的时间在100ms内就可以了。

微信截图_20200824101158.png

点赞  2020-8-24 10:14
引用: chenbingjy 发表于 2020-8-24 10:07 我现在就是不明白,有几个按键有问题。 我看了一些别人的矩阵键盘程序,都差不多

你这种用法,即使找到问题,解决了也不合适用,所以我并没有分析问题的原因

点赞  2020-8-24 10:18
引用: 29447945 发表于 2020-8-24 10:14 chenbingjy 发表于 2020-8-24 10:07 我现在就是不明白,有几个按键有问题。 我看了一些别人的矩阵键盘程 ...

谢谢,我看看

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 10:49
引用: 29447945 发表于 2020-8-24 09:44 中断里面还delay,这很不合适吧,中断程序要尽量断,你可以看看别人的按键程序的框架,不用定时器都能做好 ...

中断里的delay主要是让IO口电平稳定,不加会出错。

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 17:14
引用: damiaa 发表于 2020-8-24 09:40 //如果按键值没有变化KeyValue=0 ModiFlag =0;按键按下ModiFlag置1 值在ModiFlag里 用完请清ModiFlag和M ...

用完请清ModiFlag和ModiFlag

是不是清ModiFlag和KeyValue?

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 17:16
引用: damiaa 发表于 2020-8-24 09:40 //如果按键值没有变化KeyValue=0 ModiFlag =0;按键按下ModiFlag置1 值在ModiFlag里 用完请清ModiFlag和M ...

谢谢!我试了一下,发现要使劲按按键才出键值,不知道哪个参数没设置对,是不是定时器时间。我现在设的4ms

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 17:46
引用: chenbingjy 发表于 2020-8-24 17:14 中断里的delay主要是让IO口电平稳定,不加会出错。

我明白delay是消抖,但是中断里面delay处理不太合理,其次,消抖时间一般ms级别,如果是机械按键,us级别消抖是不够的。

点赞  2020-8-24 18:34
引用: 29447945 发表于 2020-8-24 18:34 我明白delay是消抖,但是中断里面delay处理不太合理,其次,消抖时间一般ms级别,如果是机械按键,us级别 ...

那个delay不是消抖,是让矩阵键盘行线发出的驱动高低电平稳定,否则会误判。

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-24 19:12

你那个一大堆case没必要,最好不要在中断里处理按键以后的分支程序,那样会混乱不清。。。。。 关于按键以前写过一个贴你可以看看 输出口的speed设置为低就可以避免延时,如果不行的话可以把扫描拆成几次在中断里输出,这样效率高

点赞  2020-8-25 03:43
引用: huo_hu 发表于 2020-8-25 03:43 你那个一大堆case没必要,最好不要在中断里处理按键以后的分支程序,那样会混乱不清。。。。。 关于按键以 ...

谢谢,我再试试

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-25 08:03
引用: huo_hu 发表于 2020-8-25 03:43 你那个一大堆case没必要,最好不要在中断里处理按键以后的分支程序,那样会混乱不清。。。。。 关于按键以 ...

输出口的speed设置为低还是不行,原来50MHz,现在2MHz。

为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
点赞  2020-8-25 08:49
引用: chenbingjy 发表于 2020-8-24 17:16 用完请清ModiFlag和ModiFlag 是不是清ModiFlag和KeyValue?

是呢 就是你根据ModiFlag和ModiFlag判断有按键了。你就使用。使用完了你要让他们数据为0

这样他们就可以开始下次按键的判断。

点赞  2020-8-25 09:50
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复