[STM32] 矩阵键盘的问题

[复制链接]
 楼主| 发表于 2020-8-21 11:48 | 显示全部楼层 |阅读模式
我用STM32写矩阵键盘程序。以前发过几个帖子,一直没搞好。
电路图:

代码:
  1. /*******************************************************************************
  2. * 函数名  : TIM4_IRQHandler
  3. * 描述    : 定时器4中断断服务函数
  4. * 输入    : 无
  5. * 输出    : 无
  6. * 返回    : 无
  7. * 说明    : 无
  8. *******************************************************************************/
  9. void TIM4_IRQHandler(void)
  10. {
  11.        static uint8_t    key_Pace = 0;
  12.        static uint32_t  old_KeyVal;
  13.       

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

  17.                //键盘检测可以做成for循环4次
  18.                // PE.3,5,4设施成输入 ,PE6输出L
  19.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
  20.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_6 );
  21.                                                          delay_us(XD);       
  22.                new_KeyVal = (~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f ;
  23.                //PE.3输入,PE5输出L
  24.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_4);
  25.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
  26.                                                                 delay_us(XD);
  27.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f) << 5);
  28.                //PE.4输入,PE4输出L
  29.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_3);
  30.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
  31.                                                                 delay_us(XD);
  32.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4))) & 0x3f) << 10);
  33.                //PE.5输入,PE3输出L
  34.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5);
  35.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
  36.                                                          delay_us(XD);
  37.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4)))& 0x3f ) << 16);
  38.                //恢复键盘待机,PE.6,5,4,  3全部输出L
  39.                                                                 GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_3);
  40.                                                           
  41.                 key_Pace ++;
  42.                 if(key_Pace < 6)
  43.                 {  //键盘按下去抖, 时间4ms×6 = 24ms ,也可以设置6~8ms中断一次,响应该值调整
  44.                     if((new_KeyVal == 0) || new_KeyVal != old_KeyVal)  //无键操作或者键值不对应
  45.                        {old_KeyVal = new_KeyVal;  key_Pace = 0;}                      //返回等待键盘状态
  46.                 }
  47.                 else if(key_Pace == 6)
  48.                 {  
  49.                                                                                
  50.                                                                                 //键值处理,或启动发送
  51.                      switch(old_KeyVal)
  52.                     {  //键盘比较离散或允许组合键采用这个方法
  53.                     case   0x000001:        //键盘1
  54.                                                                                                                 keyvalue=3;
  55.                               break;
  56.                     case   0x000002:        //键盘2
  57.                                                                                                                 keyvalue=2;
  58.                               break;
  59.                     case   0x000004:        //键盘3
  60.                                                                                                                 keyvalue=1;
  61.                               break;
  62.                     case   0x000008:        //键盘4
  63.                                                                                                                         keyvalue=5;
  64.                               break;
  65.                     case   0x000010:        //键盘5
  66.                                                                                                                         keyvalue=4;
  67.                               break;
  68.                     case   0x000020:        //键盘6
  69.                                                                                                                 keyvalue=8;
  70.                               break;
  71.                     case   0x000040:        //键盘7
  72.                                                                                                                 keyvalue=7;
  73.                               break;
  74.                     case   0x000080:        //键盘8
  75.                                                                                                                 keyvalue=6;
  76.                               break;
  77.                     case   0x000100:        //键盘9
  78.                                                                                                                 keyvalue=10;
  79.                               break;
  80.                     case   0x000200:        //键盘10
  81.                                                                                                                 keyvalue=9;
  82.                               break;
  83.                     case   0x000400:        //键盘11
  84.                                                                                                                 keyvalue=13;
  85.                               break;
  86.                     case   0x000800:        //键盘12
  87.                                                                                                                 keyvalue=12;
  88.                               break;
  89.                     case   0x001000:        //键盘13
  90.                                                                                                                 keyvalue=11;
  91.                               break;
  92.                     case   0x002000:        //键盘14
  93.                                                                                                                         keyvalue=16;
  94.                               break;
  95.                     case   0x004000:        //键盘15
  96.                                                                                                                         keyvalue=15;
  97.                               break;
  98.                     case   0x008000:        //键盘16
  99.                                                                                                                         keyvalue=14;
  100.                               break;
  101.                     case   0x010000:        //键盘17
  102.                                                                                                                         keyvalue=19;
  103.                               break;
  104.                     case   0x020000:        //键盘18
  105.                                                                                                                         keyvalue=18;
  106.                               break;
  107.                     case   0x040000:        //键盘19
  108.                                                                                                                         keyvalue=17;
  109.                               break;
  110.                     case   0x080000:        //键盘20
  111.                                                                                                                         keyvalue=22;
  112.                               break;
  113.                     case   0x100000:        //键盘21
  114.                                                                                                                         keyvalue=21;
  115.                               break;
  116.                     case   0x200000:        //键盘22
  117.                                                                                                                         keyvalue=20;
  118.                               break;

  119.                     default:        //其它组合键盘
  120.                               break;
  121.                     }
  122. // 可以用统筹方法组合好后统一发送数据到通讯口
  123.                                                                                 keynum=keyvalue ;
  124.                     old_KeyVal = 0;
  125.                                                                                
  126.                 }
  127.                 else if(key_Pace < 20)
  128.                 {   //键盘释放去抖
  129.                     if(new_KeyVal != 0)  key_Pace = 6;    //等待键盘释放
  130.                 }
  131.                 else    key_Pace = 0;                               //键盘释放
  132.         }
  133. }
实际测试,发现按键3,8,12比较难按,不容易检测到,经常按了没反应。
大神看看,哪里有问题?谢谢

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2020-8-21 12:23 | 显示全部楼层
  1. TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

  2.                //键盘检测可以做成for循环4次
  3.                // PE.3,5,4设施成输入 ,PE6输出L
  4.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
  5.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_6 );
  6.                                                          delay_us(XD);      
  7.                new_KeyVal = (~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f ;
  8.                //PE.3输入,PE5输出L
  9.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_4);
  10.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
  11.                                                                 delay_us(XD);
  12.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0300) >>5))) & 0x1f) << 5);
  13.                //PE.4输入,PE4输出L
  14.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_3);
  15.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
  16.                                                                 delay_us(XD);
  17.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4))) & 0x3f) << 10);
  18.                //PE.5输入,PE3输出L
  19.                                                          GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5);
  20.                                                          GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
  21.                                                          delay_us(XD);
  22.                new_KeyVal |= (((~((GPIO_ReadInputData(GPIOE) & 7) + ((GPIO_ReadInputData(GPIOB)&0x0380) >>4)))& 0x3f ) << 16);
  23.                //恢复键盘待机,PE.6,5,4,  3全部输出L
  24.                                                                 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 | 显示全部楼层
谢谢!我不明白为什么个别键有问题,会不会硬件的问题。
发表于 2020-8-21 15:23 | 显示全部楼层
比神乐 发表于 2020-8-21 13:38
谢谢!我不明白为什么个别键有问题,会不会硬件的问题。

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

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

按键扫描根本不用中断,浪费资源,定时调用即可,比如20MS调用一次,两次的结果一致则确定按下
 楼主| 发表于 2020-8-22 08:57 | 显示全部楼层
谢谢各位。我有个问题,是不是说,按下哪个按键,相应的keyin和keyout是通的,弹起不通,就说明按键是好的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

470

主题

3541

帖子

7

粉丝
快速回复 返回顶部 返回列表