新型按鍵掃描程式改良
阿新 • • 發佈:2019-02-04
硬體基礎
四個獨立按鍵
邏輯圖
說明:與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 = 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);
}