一种你值得学习的按键扫描方式

2021-08-16 12:25:21 浏览数 (1)

  最近在群里跟小伙伴聊到按键键值的获取方式,提到一种使用状态机的方式,小伙伴有点疑问,小飞哥马上放下饭碗,停止干饭,撸他一个,大神自动飘过...不想飘过的,欢迎批评指导~

实验目标

  • 学会HAL库定时器的配置及使用
  • 状态机法获取键值

软件环境

  • cubemx
  • keil5

硬件环境

  • 能“点灯”的板子
  • 按键4个(我用的是正点原子系列的,4个按键)
  • TFT LCD(可选)

一、cubemx配置

 鉴于本次实验难度不高,也不宜多吹牛x,所以直接干就完事了!

Q&A 什么是状态机?

来源:https://blog.csdn.net/xinghuanmeiying/article/details/81586954

大家可以前去查看该博主,或者百度哈~

1.1 按键配置:

  这是我的硬件连接,小伙伴们根据自己的配置进行,

1.2 定时器3配置

  配置比较简单,就不啰嗦了,不懂的话,欢迎加群,轰炸我~

二、软件代码编写

2.1 定时器相关函数

代码语言:javascript复制
void TIM3_Init(void)
{
  HAL_TIM_Base_Start_IT(&htim3); //开启定时器中断3,10ms中断周期
}
/* 
定时器中断回调函数
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM3) //定时器中断3发生中断事件
  {
    if (Key_Scan_TimCallBack())
    {
      key_value = Key_Scan_TimCallBack();
    }
  }
}

2.2 按键相关函数

代码语言:javascript复制

//下面的方式是通过直接操作HAL库函数方式读取IO
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)  //KEY0按键PE4
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)  //KEY1按键PE3
#define KEY2 HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin)  //KEY2按键PE2
#define WK_UP HAL_GPIO_ReadPin(WK_UP_GPIO_Port, WK_UP_Pin) //WKUP按键PA0

#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4



typedef enum 
{
    key_no_Press,   //按键尚未按下
    key_Press,      //按键按下
    key_PressCheck, //按键是否松开
    key_Release     //按键松开
    
}key_status;

/*----------------------------------------------------------------
按键IO状态查询函数
----------------------------------------------------------------*/
uint8_t KEY_Scan(void)
{
    if ((KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1))
    {
        if (KEY0 == 0)
            return KEY0_PRES;
        else if (KEY1 == 0)
            return KEY1_PRES;
        else if (KEY2 == 0)
            return KEY2_PRES;
        else if (WK_UP == 1)
            return WKUP_PRES;
    }
    else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0)
    return 0; //无按键按下
}

/*----------------------------------------------------------------
定时器中断中调用此函数
----------------------------------------------------------------*/
uint8_t Key_Scan_TimCallBack(void)
{
    static key_status Press_status;
    uint8_t key = 0;
    switch (Press_status)
    {
    case key_no_Press:
        if (KEY_Scan()) //有按键按下
        {
            Press_status  ;
            key = 0;
        }
        else
        {
            Press_status = key_no_Press;
            key = 0;
        }
        break;
    case key_Press:
        if (KEY_Scan()) //有按键按下,第一次消抖,仍有按键按下,认为按键有效
        {
            Press_status  ;
            key = KEY_Scan();
        }
        break;
    case key_PressCheck:
        if (KEY_Scan()) //有按键按下,仍有按键按下,可做长按键判断,目前仍按照短按键键值处理,可修改
        {
            Press_status  ;
            key = KEY_Scan();
        }
        break;
    case key_Release:
        if (KEY_Scan())  //有按键按下,仍有按键按下,可做长按键判断,目前仍按照短按键键值处理,可修改
        {
            Press_status = key_no_Press;
            key = 0;
        }
        break;
    default:
        Press_status = key_no_Press;
        key = 0;
    }
    if (key)
    {
        key_debug_printf("key value is %drn", key);
    }
    return key;
}

2.3 LCD显示相关

本次的介绍就到这里啦,后面有更精彩的内容,欢迎大家持续关注嵌入式实验基地,来这里还可以学习HAL库 cubemx的更多精彩内容哦!

0 人点赞