野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15596|回复: 8

发一个逻辑很清晰的非阻赛4X4按键扫描

[复制链接]
发表于 2016-10-9 17:33:13 | 显示全部楼层 |阅读模式
     如标题所言,可以把这个 Key_scan( )直接扔到SYStick  10MS中断里面就可以了,很容易再加一个状态机外壳即可实现按键短按长按等功能,不需要频繁打开关闭定时器

     Key_count 是扫描计数器,每次到中断判断一下是否上次有按键按下,没有就+1,上次有按键事件就保持计数器值再检测一次按键是否还按下,利用 Key_count 奇数和偶数间隔,可以区分是切换扫描列还是进行按键检测。
    PE2 ,PE3,PE4, PE5 键盘检测口,上拉输入,低电平有效
    PC5,PC2,PC3,PE6  是扫描列,初始化高电平,低电平扫描


#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "Key.h"
void Key_scan(void);
__IO uint32_t Key_count=0;//扫描计数器
__IO uint32_t Key_flag=0;//按键标志


__IO uint32_t Key_end=0; //最终按键扫描结果
__IO uint32_t Key_head=0;  //缓冲队列头指针
__IO uint32_t Key_tail=2;  //缓冲队列尾指针
__IO uint32_t Key_buf[2]={0,0};   //按键缓冲区
enum Key {NONE,K1,K2,K3,K4,K5,K6,K7,K8,K9,K10,K11,K12,K13,K14,K15,K16}Key_num; //单次按键枚举值


void Key_scan(void)
{
  

   if(Key_count>=8)            //偶数扫描,奇数检测按键,间隔10MS
  {
     Key_count=0;
  
  }
    else
  {
    if(Key_flag==1)
    {
      Key_count=Key_count;  //维持扫描口低电平有效
    }  
    else
    {
     Key_count++;         //扫描下一列
       }     
   }
  
  switch(Key_count)
  
  {
  
    case 0:GPIOC->BRR=GPIO_Pin_5;//置0扫描
         
         
   break;
   
   case 2:GPIOC->BRR=GPIO_Pin_2;//置0扫描
         
         
   break;
   
   case 4:GPIOC->BRR=GPIO_Pin_3;//置0扫描
         
         
   break;
   
   
   case 6:GPIOE->BRR=GPIO_Pin_6;//置0扫描
         
         
   break;
   
   
   case 1: if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)    //奇数检测IO口,低位为按键按下
            {
          Key_num=K1;  //按键值
         Key_flag=1;  //按键标志有效
         
        }
        
               else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
        {
          Key_num=K4;
         
         Key_flag=1;
         
        }  
        
             else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==Bit_RESET)
        {
          Key_num=K7;
         Key_flag=1;
         
         
        }  
      
          else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==Bit_RESET)
        {
          Key_num=K10;
         
         Key_flag=1;
        }
        
        else
        {
         
         Key_num=NONE;
         Key_flag=0;
         GPIOC->BSRR=GPIO_Pin_5;//无按键按下对应扫描端置1复位,准备扫描下一列
        
        }  
               
        
               
    break;
        case 3: if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
            {
          Key_num=K2;
         Key_flag=1;
         
        }
        
               else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
        {
          Key_num=K5;
         
         Key_flag=1;
         
        }  
        
             else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==Bit_RESET)
        {
          Key_num=K8;
         Key_flag=1;
         
        }  
      
          else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==Bit_RESET)
        {
          Key_num=K11;
         
         Key_flag=1;
         
        }
        
        else
        {
         
         Key_num=NONE;
         Key_flag=0;
         GPIOC->BSRR=GPIO_Pin_2;//无按键按下对应扫描端置1复位,准备扫描下一列
        }  
        
      
        
        
    break;
        
    case 5: if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
            {
          Key_num=K3;
         
         Key_flag=1;
        }
        
               else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
        {
          Key_num=K6;
         
         Key_flag=1;
         
        }  
        
             else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==Bit_RESET)
        {
          Key_num=K9;
         
         Key_flag=1;
        }  
      
          else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==Bit_RESET)
        {
          Key_num=K12;
         
         Key_flag=1;
         
        }
        
        else
        {
         
         Key_num=NONE;
         Key_flag=0;
         GPIOC->BSRR=GPIO_Pin_3;//无按键按下对应扫描端置1复位,准备扫描下一列
        
        }  
        
        
    break;
   
    case 7: if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
            {
          Key_num=K15;
         Key_flag=1;
        
        }
        
               else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
        {
          Key_num=K16;
         
         Key_flag=1;
         
        }  
        
             else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==Bit_RESET)
        {
          Key_num=K14;
         Key_flag=1;
         
        }  
      
          else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==Bit_RESET)
        {
          Key_num=K13;
         Key_flag=1;
         
         
        }
        
        else
        {
         
         Key_num=NONE;
         Key_flag=0;
         GPIOE->BSRR=GPIO_Pin_6;
         
        
        }  
        
        
    break;
               
     
    default:
    break;
   
  }
  
   
   
  
      if(Key_head<Key_tail)
       {
          Key_buf[Key_head]=Key_num;      //缓冲未满一次,写入单次按键值
   
         Key_head++;
  
        }  
  
        else
       {
         
           Key_head=0;             //缓冲写满,判断按键
   
   
        
   
            if((Key_buf[0]==Key_buf[1]))
      
      
            
          {
   
                 Key_end=Key_num;   //满足消抖,按键输出
            
            
     
        
             }
      
      
      
   
      }
   
  
   
  
  

  
  
  
}








QQ图片20161009172900.png
回复

使用道具 举报

发表于 2016-10-9 20:26:17 来自手机 | 显示全部楼层
帮顶
回复

使用道具 举报

发表于 2016-10-9 20:27:01 来自手机 | 显示全部楼层
cool
回复

使用道具 举报

 楼主| 发表于 2016-10-9 20:53:12 | 显示全部楼层

谢谢火哥支持
回复 支持 反对

使用道具 举报

发表于 2016-10-10 08:35:02 | 显示全部楼层
:赞赞赞赞
回复

使用道具 举报

发表于 2016-10-10 08:51:37 | 显示全部楼层
好复杂的感觉
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-10 14:32:49 | 显示全部楼层

你看成物理运动试试,逻辑很简单清晰的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-10 21:57:36 | 显示全部楼层
本帖最后由 zhaoyi821103 于 2016-10-11 00:06 编辑

__IO uint32_t Key_temp=0;//按键松手临时变量
__IO uint32_t Key_ready=0;//按键松手检测标志

__IO uint32_t Key_tail=4;  //缓冲队列尾指针
__IO uint32_t Key_buf[4];   //按键缓冲区

增加两个变量即可实现按键松手检测,同时调整按键缓存大小,可以做到微调按键延迟以适应不同系统定时器节拍和不同类型按键的延迟微调


                       if(Key_head<Key_tail)
                     {
                             Key_buf[Key_head]=Key_num;      //缓冲未满一次,写入单次按键值
                        
                              Key_head++;
               
                      }               
               
                      else
                     {
                       
                                  Key_head=0;             //缓冲写满,判断按键
                        
                        
                             
                        
                                    if((Key_buf[0]==Key_buf[1])&&(Key_buf[0]==Key_buf[2])&&(Key_buf[0]==Key_buf[3])&&(Key_buf[0]!=0))
                                                        
                                                
                                                
                                 {
                        
                                                     Key_temp=Key_num;   //满足消抖
                                                     Key_ready=1;       //准备松手
                                                            
                                 
                                    
                                  }
                                                
                                                
                                   else
                                   {
                                                      
                                             if(Key_ready==1)
                                           {
                                                                 
                                                 Key_ready=0;
                                                 Key_end=Key_temp; //松手输出按键
                                                                    
                                            }         
                                                
                                                
                                                
                                     }         

回复 支持 反对

使用道具 举报

发表于 2016-10-11 18:04:05 | 显示全部楼层
COOL!!!
回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-16 18:22 , Processed in 0.036378 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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