新型按键扫描程序改良

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/jickjiang/article/details/81385287

硬件基础

四个独立按键

逻辑图

说明:与bsp_key.c 的代码有一点出入

Created with Raphaël 2.1.2 开始 KEYx_TRIGER? 记录键值 KEYx_CONTINE? 计数器减数 是否有键值? 计数器减为0? 如果有键值为长按 结束 如果有键值为短按 yes no yes no yes no yes no

程序

bsp_key.h

/**
*****************************************************************************
* @文  件: bsp_key.h 
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 8-May-2018
* @描  述: 按键处理驱动接口文件
******************************************************************************
* @修改记录:
*   2018/05/08:初始版本
*    
*
******************************************************************************
**/

#ifndef _BSP_KEY_H_
#define _BSP_KEY_H_

#ifdef _cplusplus
    extern "C" {
#endif

//C库
#include <stdint.h>

//宏定义
#define KEYDOWN_LONG_TIME       100         //以每20ms调用一次。 二秒钟种为按键长按

//定义枚举
typedef enum {
    KEY0_TRIGER = 0, KEY1_TRIGER = 1, KEY2_TRIGER = 2, KEY3_TRIGER = 3,
    KEY0_CLICKED = 10, KEY1_CLICKED = 11, KEY2_CLICKED = 12, KEY3_CLICKED = 13,
    KEY0_LONG_PRES = 20, KEY1_LONG_PRES = 21, KEY2_LONG_PRES = 22, KEY3_LONG_PRES = 23,
    KEY_NONE = 255
}KEY_VALUE_ENUM;

//定义结构体
typedef struct{
    uint16_t Triger;
    uint16_t Continue;
    KEY_VALUE_ENUM KeyValue;
}KEY_STATE_STRUCT;

//接口函数
void Key_init(void);
KEY_VALUE_ENUM Key_getValue(void);

void Key_put(KEY_VALUE_ENUM cKeyVal);
KEY_VALUE_ENUM Key_get(void);

//外部引用
extern KEY_STATE_STRUCT KeyStateStruct;

#ifdef _cplusplus
    }
#endif

#endif

bsp_key.c

/**
*****************************************************************************
* @文  件: bsp_key.c 
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 20-July-2018
* @描  述: 按键处理驱动
******************************************************************************
* @修改记录:
*   2018/07/20:初始版本
*   2018/07/23:增加短按、长按、触发
*
******************************************************************************
**/

//按键头文件
#include "bsp_key.h"

//硬件驱动
#include "hardware.h"

//宏定义
#define KEY0        0x01
#define KEY1        0x02
#define KEY2        0x04
#define KEY3        0x08


//全局变量
KEY_STATE_STRUCT KeyStateStruct = {
    .Triger = 0,
    .Continue = 0,
    .KeyValue = KEY_NONE,
};



/*
******************************************************************************
*   函 数 名: Key_init
*   功能说明: 按键IO初始化, 按下为低电平 释放为高电平
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Key_init(void)
{

    GPIO_InitTypeDef gpioInitStructure;

    gpioInitStructure.GPIO_Mode = GPIO_Mode_IPU;
    gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    gpioInitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;

    GPIO_Init(GPIOC, &gpioInitStructure);

}

/*
******************************************************************************
*   函 数 名: Key_parse
*   功能说明: 键值解析,触发、短按、长按
*   形    参: 无
*   返 回 值: 键值
******************************************************************************
*/
#define JUDGE_KEY_VALUE(A,X,Y,Z)\
    if(KeyStateStruct.Continue & A){\
        if(sKeyDownLastTime > 0){\
            sKeyDownLastTime -= 1;\
        }else{\
            sKeyValue = Z;\
            sKeyDownLastTime = KEYDOWN_LONG_TIME;\
        }\
    }else{\
        if(sKeyDownLastTime != KEYDOWN_LONG_TIME){\
            if(sKeyValue == X){\
                sKeyValue = Y;\
            }\
        }\
    }\

KEY_VALUE_ENUM Key_parse(void)
{
    static KEY_VALUE_ENUM sKeyValue = KEY_NONE;
    static int32_t sKeyDownLastTime = KEYDOWN_LONG_TIME;

    KEY_VALUE_ENUM rKeyValue = KEY_NONE;

    if(KeyStateStruct.Triger & KEY0){
        sKeyValue = KEY0_TRIGER;
    }

    if(KeyStateStruct.Continue & KEY0){    
        if(sKeyDownLastTime > 0){
            sKeyDownLastTime -= 1;
        }else{
            sKeyValue = KEY0_LONG_PRES;
            sKeyDownLastTime = KEYDOWN_LONG_TIME;
        }
    }else{
        if(sKeyDownLastTime != KEYDOWN_LONG_TIME){
            if(sKeyValue == KEY0_TRIGER){
                sKeyValue = KEY0_CLICKED;
            }
        }
    }

    if(KeyStateStruct.Triger & KEY1){
        sKeyValue = KEY1_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY1,KEY1_TRIGER,KEY1_CLICKED,KEY1_LONG_PRES);

    if(KeyStateStruct.Triger & KEY2){
        sKeyValue = KEY2_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY2,KEY2_TRIGER,KEY2_CLICKED,KEY2_LONG_PRES);

    if(KeyStateStruct.Triger & KEY3){
        sKeyValue = KEY3_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY3,KEY3_TRIGER,KEY3_CLICKED,KEY3_LONG_PRES);

    rKeyValue = sKeyValue;                                                          //负值需要返回的键值

    if(((KeyStateStruct.Continue & 0x000F) == 0)&&(KeyStateStruct.Triger == 0)){    //按键释放长按计算还原
        sKeyDownLastTime = KEYDOWN_LONG_TIME;
        sKeyValue = KEY_NONE;  
    }

    return rKeyValue;
}

/*
******************************************************************************
*   函 数 名: Key_loopRead
*   功能说明: 按键电平扫描
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Key_loopRead(void)
{
    uint16_t ReadData = ~((GPIOC->IDR) & 0x000F);
    KeyStateStruct.Triger = ReadData & (ReadData ^ KeyStateStruct.Continue);
    KeyStateStruct.Continue = ReadData;
}

/*
******************************************************************************
*   函 数 名: Key_getValue
*   功能说明: 按键电平扫描
*   形    参: 无
*   返 回 值: 键值
******************************************************************************
*/
KEY_VALUE_ENUM Key_getValue(void)
{
    Key_loopRead();

    return Key_parse();
}

/*
******************************************************************************
*   函 数 名: Key_put
*   功能说明: 配置按键全局变量
*   形    参: 无
*   返 回 值: 键值
******************************************************************************
*/
void Key_put(KEY_VALUE_ENUM cKeyVal)
{
    KeyStateStruct.KeyValue = cKeyVal;
}

/*
******************************************************************************
*   函 数 名: Key_get
*   功能说明: 获取按键全局变量
*   形    参: 无
*   返 回 值: 键值
******************************************************************************
*/
KEY_VALUE_ENUM Key_get(void)
{
    KEY_VALUE_ENUM  rValue;
    rValue = KeyStateStruct.KeyValue;
    KeyStateStruct.KeyValue = KEY_NONE;
    return rValue;
}

应用

/** 
  * @name   void UserInterface_menuRefresh (void)
  * @brief  菜单更新函数
  * @param  none
  * @retval none
  */
void UserInterface_loop (void)
{
    KEY_VALUE_ENUM tKeyValue;

    tKeyValue = Key_get();
    if(tKeyValue != KEY_NONE)
        KeyCodeAction(tKeyValue);

    Delay_mSec(PAGE_REFRESH_TIME);
}

猜你喜欢

转载自blog.csdn.net/jickjiang/article/details/81385287
今日推荐