打印
[STM32]

矩阵键盘的问题

[复制链接]
949|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我用STM32写矩阵键盘程序。以前发过几个帖子,一直没搞好。
电路图:

代码:
/*******************************************************************************
* 函数名  : 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比较难按,不容易检测到,经常按了没反应。
大神看看,哪里有问题?谢谢

使用特权

评论回复

相关帖子

沙发
叶春勇| | 2020-8-21 12:23 | 只看该作者
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);

这一段可以放在中断中,加上按键码
其他的防抖什么的,移出中断

使用特权

评论回复
板凳
叶春勇| | 2020-8-21 12:44 | 只看该作者

  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 ;

比如读PE2为低电平,硬件按键变量HK为32位整数
伪代码:
if(pe2==0) HK|=(1<<0);
else HK&=~(1<<0);
这个时候HK的bit0与第一行第一列对应。这个可以放在中断中。
这个时候防抖就是普通的单按钮类似的防抖其中VK是32位数,虚拟键盘变量,这个不需要放在中断中。
if(HK & (1<<0))
{
    if(++acc_pressed>10) VK|=(1<<0);
    acc_released=0;
}
else
{
     if(++acc_released>10) VK&=~(1<<0);
    acc_pressed=0;
}
以上代码将HK的bit转换成防抖后的VK的bit。

使用特权

评论回复
地板
比神乐|  楼主 | 2020-8-21 13:38 | 只看该作者
谢谢!我不明白为什么个别键有问题,会不会硬件的问题。

使用特权

评论回复
5
ayb_ice| | 2020-8-21 15:23 | 只看该作者
比神乐 发表于 2020-8-21 13:38
谢谢!我不明白为什么个别键有问题,会不会硬件的问题。

这种按键适合正反扫描,读两次就可以了

每次读到的数据只有一位是0,则表示有一个按键按下
按键号根据公式 y=kx+b,速度很快

按键扫描根本不用中断,浪费资源,定时调用即可,比如20MS调用一次,两次的结果一致则确定按下

使用特权

评论回复
6
比神乐|  楼主 | 2020-8-22 08:57 | 只看该作者
谢谢各位。我有个问题,是不是说,按下哪个按键,相应的keyin和keyout是通的,弹起不通,就说明按键是好的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

438

主题

3433

帖子

7

粉丝