找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8014|回复: 0
打印 上一主题 下一主题
收起左侧

简单的KEY扫描不简单,你还在用简陋的例程吗?

[复制链接]
跳转到指定楼层
楼主
ID:75926 发表于 2015-4-4 01:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一般的开发板,给出的例程,对按键扫描的写法如下:
#define KEY1  HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10)
#define KEY2  HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2)
uint8_t K1_Value;
uint8_t K2_Value;
void KEY_SCAN(void)
{
   if (KEY1 == 0)  {
      delay(200); // 延时200毫秒
      if(KEY1 == 0)  { K1_Value= 1; }
      else {K1_Value = 0;}
   }
   if (KEY2 == 0)  {
      delay(200); // 延时200毫秒
      if(KEY2 == 0)  { K2_Value= 1; }
      else {K2_Value = 0;}  
   }
}

这种写法非常简陋,也就是害人害己,无法在实际项目中使用,很多有名气的教授写的教材也是这样的。
以下是本人原创的按键扫描,经过反复实验,在DX103开发板上测试能正常工作。代码可以在项目中使用。

/**

  * @brief  KEY Scan Structure definition  
  */  
typedef struct
{
  uint16_t Shift_Cnt;                             /* 向下毫秒计数,粘滞键扫描延迟和启动标志,限制生成向上键值 */
  uint16_t Up_Cnt;                               /* 向下毫秒计数, 弹起键扫描延迟和启动标志 */
  uint16_t Down_Repeat;                     /* 限制500毫秒内仅产生一次按下的键值 */
  uint16_t Up_Repeat;                          /* 限制500毫秒内仅产生一次弹起的键值 */
  uint8_t  Flag_KEY_Down_Process;    /* KEY键按下处理标志 */
  uint8_t  Flag_KEY_Shift_Process;      /* KEY粘滞键处理标志 */
  uint8_t  Flag_KEY_Up_Process;        /* KEY键弹起处理标志 */
  uint8_t  Flag_KEY_Process;               /* KEY键后续继续处理标志 */
  uint8_t  Value;                                     /* KEY当前键值 */
  uint8_t  Old_Value;                              /* KEY上一个键值 */
}KEY_TypeDef;

KEY_TypeDef KEY1, KEY2;
__IO uint8_t Flag_TIM2_Update = 0;  /* 定时器2更新标志 */

/* 带参数的宏功能(预编译展开): 扫描GPIOx GPIO_PIN_x的单个按键  */
#define KEYX_SCAN(KEYx,GPIOx,GPIO_PIN_x) {\
  KEYx.Value = HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_x);\
  if(KEYx.Old_Value != KEYx.Value){\
    if(KEYx.Old_Value == 1){\
      if(KEYx.Down_Repeat == 0){\
        KEYx.Flag_KEY_Down_Process = 1;\
        KEYx.Down_Repeat = 500;\
      }\
      KEYx.Shift_Cnt = 800;\
    } else {\
      if(KEYx.Down_Repeat < 300){\
        KEYx.Shift_Cnt = 0;\
        KEYx.Up_Cnt = 0;\
        if(KEYx.Up_Repeat == 0){\
          KEYx.Flag_KEY_Up_Process = 1;\
          KEYx.Up_Repeat = 500;\
        }\
      }\
    }\
    KEYx.Old_Value = KEYx.Value;\
  }\
  if(KEYx.Down_Repeat){--KEYx.Down_Repeat;}\
  if(KEYx.Up_Repeat){--KEYx.Up_Repeat;}\
  if(KEYx.Shift_Cnt){\
    --KEYx.Shift_Cnt;\
    if(KEYx.Shift_Cnt==0){\
      KEYx.Value = HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_x);\
      if(KEYx.Value == 0){\
        KEYx.Flag_KEY_Shift_Process = 1;\
        KEYx.Down_Repeat = 200;\
        KEYx.Shift_Cnt   = 200;\
      } else {\
        KEYx.Up_Cnt = 20;\
      }\
      KEYx.Old_Value = KEYx.Value;\
    }\
  }\
  if(KEYx.Up_Cnt){\
    --KEYx.Up_Cnt;\
    if(KEYx.Up_Cnt==0){\
      KEYx.Value = HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_x);\
      if(KEYx.Value == 1){\
        KEYx.Flag_KEY_Up_Process = 1;\
        KEYx.Shift_Cnt = 0;\
        KEYx.Up_Cnt = 0;\
      }\
      KEYx.Old_Value = KEYx.Value;\
    }\
  }\
}

/*
* @ KEY_SCAN
* @ Edit by wjandcf@gmail.com
* @ 2015-2-3
*/
void KEY_SCAN(void)
{
  KEYX_SCAN(KEY1, GPIOB, GPIO_PIN_10); /* 扫描大虾103开发板上的KEY1 */
  KEYX_SCAN(KEY2, GPIOC, GPIO_PIN_2);  /* 扫描大虾103开发板上的KEY2 */

#if 0
  /* 保留此段代码,是为了让大家了解按键扫描的基本流程 */
  /* 按键扫描第一部分,快速的按下和弹起键值扫描 */
  KEY1.Value = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10);
  if(KEY1.Old_Value != KEY1.Value){
    if(KEY1.Old_Value == 1){              /* 有键按下 */
      if(KEY1.Down_Repeat == 0){
        KEY1.Flag_KEY_Down_Process = 1;   /* 按键按下标志 */
        KEY1.Down_Repeat = 500;           /* 500毫秒内不再产生键按下标志 */
      }
      KEY1.Shift_Cnt = 800;               /* 粘滞键产生的延迟时间,限制再产生向上按键 */
    } else {
      if(KEY1.Down_Repeat < 300){         /* (500-300)毫秒后才能产生向上按键 */
        KEY1.Shift_Cnt = 0;
        KEY1.Up_Cnt = 0;
        if(KEY1.Up_Repeat == 0){
          KEY1.Flag_KEY_Up_Process = 1;   /* 按键弹起标志 */
          KEY1.Up_Repeat = 500;           /* 500毫秒内不再产生键弹起标志 */
        }
      }
    }
    KEY1.Old_Value = KEY1.Value;
  }
  /* 按键扫描第二部分,粘滞键扫描,粘滞键后的弹起键扫描 */
  if(KEY1.Down_Repeat){
    --KEY1.Down_Repeat;                   /* 按键按下扫描时间限制,不为零限制再次生成 */
  }
  if(KEY1.Up_Repeat){
    --KEY1.Up_Repeat;                     /* 按键弹起扫描时间限制,不为零限制再次生成 */
  }
  if(KEY1.Shift_Cnt){
    --KEY1.Shift_Cnt;                     /* 粘滞键扫描延迟 */
    if(KEY1.Shift_Cnt==0){
      KEY1.Value = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10);
      if(KEY1.Value == 0){
        KEY1.Flag_KEY_Shift_Process = 1;  /* 粘滞键标志 */
        KEY1.Down_Repeat = 200;           /* 粘滞键时,限制300毫秒内不能生成按下键 */
        KEY1.Shift_Cnt   = 200;           /* 200毫秒生成一次粘滞键 */
      } else {
        KEY1.Up_Cnt = 20;                 /* 发现有按键弹起,延迟20毫秒再检查按键是否真正弹起 */
      }
      KEY1.Old_Value = KEY1.Value;
    }
  }
  if(KEY1.Up_Cnt){                        /* 在200毫秒的粘滞键生成时间限制里,每隔20毫秒检查按键是否弹起 */
    --KEY1.Up_Cnt;
    if(KEY1.Up_Cnt==0){
      KEY1.Value = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10);
      if(KEY1.Value == 1){
        KEY1.Flag_KEY_Up_Process = 1;     /* 按键弹起标志 */
        KEY1.Shift_Cnt = 0;               /* 按键弹起,关闭粘滞键扫描 */
        KEY1.Up_Cnt = 0;                  /* 按键弹起,关闭弹起键扫描 */
      }
      KEY1.Old_Value = KEY1.Value;
    }
  }
#endif
}





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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