天天看點

新型按鍵掃描程式改良

硬體基礎

四個獨立按鍵
           

邏輯圖

說明:與bsp_key.c 的代碼有一點出入

程式

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 = , KEY1_TRIGER = , KEY2_TRIGER = , KEY3_TRIGER = ,
    KEY0_CLICKED = , KEY1_CLICKED = , KEY2_CLICKED = , KEY3_CLICKED = ,
    KEY0_LONG_PRES = , KEY1_LONG_PRES = , KEY2_LONG_PRES = , KEY3_LONG_PRES = ,
    KEY_NONE = 
}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 = ,
    .Continue = ,
    .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 > ){\
            sKeyDownLastTime -= ;\
        }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 > ){
            sKeyDownLastTime -= ;
        }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 & ) == )&&(KeyStateStruct.Triger == )){    //按鍵釋放長按計算還原
        sKeyDownLastTime = KEYDOWN_LONG_TIME;
        sKeyValue = KEY_NONE;  
    }

    return rKeyValue;
}

/*
******************************************************************************
*   函 數 名: Key_loopRead
*   功能說明: 按鍵電平掃描
*   形    參: 無
*   返 回 值: 無
******************************************************************************
*/
void Key_loopRead(void)
{
    uint16_t ReadData = ~((GPIOC->IDR) & );
    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);
}
           

繼續閱讀