菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
41
0

基于跳变检测的按键检测

原创
05/13 14:22
阅读数 15224

背景

1、传统的按键检测使用阻塞式延迟去抖动,容易造成CPU浪费。

2、对于输入动作容易造成重复,引发混乱(假设我按住一个按钮,得到了111111111111111111111111111的结果)

因此,我们引入通过检测跳变来间接检测输入按键的检测。

原理很简单:

1、初始化一个flag,给定默认值。

2、按下按钮以后,电平发生变化,同时让flag置到某个状态。

3、在还没松开按键之前,系统将定期检测(检测间隔大于抖动时间,所以不用额外去抖动),由于flag并不满足条件,所以不执行任何动作

4、松开以后,flag置为默认值,执行按键响应代码,结束。

代码为:

(STM32F4xx HAL库版本)

#include "sys.h"
#include "usart.h"
#define KEY0        PAin(0) //KEY0按键PA0

u8 KEY_Scan(u8 mode)            // 可拓展以支持多键检测    
{                
/*                 
mode: 扫描模式            
0:跳变模式    :仅在“低-高”时有效
1:连按模式 :长按多久便多久有效

返回值:
0 :表示没有按键按下(即读取无效)
非0:用户自定义,不同的返回值可以是不同的键值
*/                
    static u8 key_up = 1;            //按键松开标志(模式0使用)

    if(mode == 1)     key_up = 1;        // 支持连按
    if(key_up && (KEY0 == 0 /* 逻辑 “或 xx==0” 拓展区 ,可获取其他的IO*/))            
    {            
        key_up = 0;        
        if(KEY0 == 0) return 1;            // 键值1
        /* 键值有效返回区 ,可获取其他的IO*/
        // if(KEY1 == 0) return 2;        // 键值2

    }else if(KEY0 == 1/* 逻辑 “且 xx==1” 拓展区 ,*/) key_up = 1;            
    return 0;    //无按键按下      
}            

// 跳变式检测按钮是否输入
int main(void)
{
    int key = -1;
    int flag = 0;
    GPIO_InitTypeDef GPIO_Initure;

    HAL_Init();                     //初始化HAL库    
    Stm32_Clock_Init(360,8,2,8);   //设置时钟,180Mhz


    __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    __HAL_RCC_GPIOG_CLK_ENABLE();           //开启GPIOG时钟

    GPIO_Initure.Pin   = GPIO_PIN_0; 
    GPIO_Initure.Mode  = GPIO_MODE_INPUT;
    GPIO_Initure.Pull  = GPIO_NOPULL; 
    GPIO_Initure.Speed = GPIO_SPEED_LOW; 
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);

    GPIO_Initure.Pin   = GPIO_PIN_13|GPIO_PIN_14; 
    GPIO_Initure.Mode  = GPIO_MODE_OUTPUT_PP; 
    GPIO_Initure.Pull  = GPIO_NOPULL;
    GPIO_Initure.Speed = GPIO_SPEED_LOW;
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);

    while(1)
    {
        // 这一段代码是为了直观地看出按钮按下去的情况:按下亮灯,否则灭灯
        key = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
        if(key == 1)
        {
            HAL_GPIO_WritePin(GPIOG,GPIO_PIN_14,GPIO_PIN_SET);
        }else
            HAL_GPIO_WritePin(GPIOG,GPIO_PIN_14,GPIO_PIN_RESET);

        // 跳变式检测按钮是否输入的代码:当有低-高的电平跳变时,对灯状态取反
        key = KEY_Scan(1);
        if(key!=0)
        {
            flag = ~flag;
            if(flag == 0)
            {
                HAL_GPIO_WritePin(GPIOG,GPIO_PIN_13,GPIO_PIN_SET);
            }else
            {
                HAL_GPIO_WritePin(GPIOG,GPIO_PIN_13,GPIO_PIN_RESET);
            }
            Delay_ms(10);
        }
    }
}

发表评论

0/200
41 点赞
0 评论
收藏