基础硬件——按键处理

前言

本文主要介绍按键的的处理方法。按键通常分成边沿检测和电平检测。

本文提供一种简单的按键处理方法,优点在于减少判断语句的使用。

本文的主要参考资料为:

本文的实验平台:

  • 正点原子的阿波罗F429开发板

本文工程下载地址:

主函数

本文不再详细粘贴所有的代码,仅介绍核心代码部分:

    while (1)
    {
        timeMs = HAL_GetTick();

        /* KEY */
        KeyResetEdge();
        if (timeMs - time10Ms >= 10)
        {
            time10Ms = timeMs;
            KeyScan();
        }

        /* LED */
        if (KeyGetEdgeActive() & KEY_0)
        {
            set_led_0 = !set_led_0;
            set_led_1 = set_led_0;
        }
        if (KeyGetEdgeActive() & KEY_1)
        {
            set_led_1 = !set_led_1;
        }
        if (KeyGetEdgeActive() & KEY_2)
        {
            set_led_0 = !set_led_0;
        }
        if (KeyGetEdgeActive() & KEY_WKUP)
        {
            set_led_0 = !set_led_0;
            set_led_1 = !set_led_0;
        }
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }

其中,timeMs 的增加量为 毫秒增量。所以,扫描程序KeyScan() 每10ms 执行一次。这就相当于去抖处理。函数KeyGetEdgeActive() 是获得有效边沿。因为该函数为每次按下一次按键,LED灯变化一次。所以,应该使用边缘检测。而函数KeyResetEdge()的作用为,清除有效边沿。这是因为while循环执行一周速度不超过10ms。而若没有该函数的话,10ms有效边沿才会清除,这样,每次有效边沿会被执行很多次。

按键处理程序

/**
  ******************************************************************************
  * @file    key.c
  * @author  zhy
  * @version 1.0
  * @date    2021-05-18
  * @brief   按键处理程序
  ******************************************************************************
  */

#include "sys.h"
#include "key.h"

//{
/*-----------------------------------私有域:开始--------------------------------------*/

uint8_t edgeActive = 0;  //有效边沿
uint8_t levelActive = 0; //有效电平

/*-----------------------------------私有域:结束--------------------------------------*/
//}

void KeyScan(void)
{
    static uint8_t edge = 0;                                                             //触发边缘
    static uint8_t level = 0;                                                            //有效电平
    uint8_t key = get_key_0 | (get_key_1 << 1) | (get_key_2 << 2) | (get_key_wkup << 3); //用后四位作为处理
    key ^= 0x07;                                                                         //将常高的按键置反,取下降沿
    edgeActive = edge & key;                                                             //上一次为有效触发,且当前还是有效电平
    levelActive = level & key;                                                           //上一次为有效电平,且当前还是有效电平
    edge = key & (key ^ level);                                                          //键值发生变化,且当前位有效电平
    level = key;                                                                         //保留上一次有效电平
}

uint8_t KeyGetLevelActive(void)
{
    return levelActive;
}

uint8_t KeyGetEdgeActive(void)
{
    return edgeActive;
}

void KeyResetEdge(void)
{
    edgeActive = 0;
}

只有keyScan程序比较难以理解,下面详细介绍:

 uint8_t key = get_key_0 | (get_key_1 << 1) | (get_key_2 << 2) | (get_key_wkup << 3);

该语句是将所有的键值合并到同一个数值上。这是因为正点原子开发板硬件设计没有将所有的按键在同一个总线中,若是在同一个总线中,读取一次寄存器即可以获取所有键值。

key ^= 0x07;                                                                         //将常高的按键置反,取下降沿

这是为了统一处理方便。

其中 key0,key1,key2的有效电平为低电平,而key_wkup的有效电平为高电平。为了统一处理,取1为有效数字。这样将有效电平为低电平的按键统一取反。

先跳过两句代码,先看最后两句:

    edge = key & (key ^ level);                                                          //键值发生变化,且当前位有效电平
    level = key;                                                                         //保留上一次有效电平

key为1的位代表当前位有效电平。level为1的位代表该按键上一次为有效电平。这两个变量进行异或,即代表查找电平发生变化的按键。然后在与当前为有效电平的按键位与,即获得当前电平为有效电平的按键且在这次采样中发生了电平变化 ,即edge为1的位代表 按键发生了由无效电平到有效电平的跳变 。然后,再将 这一次的电平值 保存到 变量level中,留作下一次采样使用。

再看刚刚跳过的两句代码

    edgeActive = edge & key;                                                             //上一次为有效触发,且当前还是有效电平
    levelActive = level & key;   

一般的为了去抖,按键的有效边沿检测为 无效电平——有效电平——有效电平 。 而最终有效电平的检测为 有效电平——有效电平

这样,很容易就理解第二句代码的含义:上一次为有效电平,这一次同样是有效电平,就可以认为该按键确实按下。而第一句含义类似,上一次发生了有效跳变,即无效电平——有效电平,而这一次电平为有效电平,所以,最终为:无效电平——有效电平——有效电平

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值