key.c
/******************************************************************************************************* @file key.c* @author Kyro Qu* @brief 按键驱动代码* 实验平台: STM32G431RB开发板*****************************************************************************************************/#include "key.h"
#include "lcd.h"
#include "stdio.h"typedef struct
{GPIO_TypeDef *Key_Port;uint16_t Key_Pin;}Key_GPIO_t;static Key_GPIO_t g_KeyList[] =
{{ KEY_B1_GPIO_Port, KEY_B1_Pin },{ KEY_B2_GPIO_Port, KEY_B2_Pin },{ KEY_B3_GPIO_Port, KEY_B3_Pin },{ KEY_B4_GPIO_Port, KEY_B4_Pin }/* add other KEY, ... */
};#define KEY_NUM_MAX (sizeof(g_KeyList)/sizeof(g_KeyList[0]))typedef enum
{KEY_RELEASE =0, /* 释放松开 */KEY_CONFIRM, /* 消抖确认 */KEY_SHORT_PRESS, /* 短按 */KEY_LONG_PRESS, /* 长按 */}KEY_STATE;#define CONFIRM_TIME 10 /* 消抖时间 ms */
#define LONG_PRESS_TIME 2000 /* 长按时间窗 ms */typedef struct
{KEY_STATE keyState; /* 按键状态 */uint32_t prvTime; /* 按键时间 */ }Key_Info_t;static Key_Info_t g_Key_Info[KEY_NUM_MAX];/*** @brief 扫描单个按键不同状态函数* @param 按键端口号* @retval 键值*/
static uint8_t keyScan(uint8_t keyIndex)
{uint8_t keyPress;keyPress=HAL_GPIO_ReadPin(g_KeyList[keyIndex].Key_Port,g_KeyList[keyIndex].Key_Pin);#if !ElECTRIC_LEVELkeyPress=!keyPress;#endifswitch (g_Key_Info[keyIndex].keyState) /* 按键状态机 */{ case KEY_RELEASE :if(keyPress ) /* 如果按下 */ {g_Key_Info[keyIndex].keyState = KEY_CONFIRM;g_Key_Info[keyIndex].prvTime = HAL_GetTick(); /* 获取按下起始时间 */ }break;case KEY_CONFIRM :if(keyPress ){if(HAL_GetTick()-g_Key_Info[keyIndex].prvTime>CONFIRM_TIME ){g_Key_Info[keyIndex].keyState = KEY_SHORT_PRESS;}}else{g_Key_Info[keyIndex].keyState = KEY_RELEASE;}break;case KEY_SHORT_PRESS :if(keyPress ){if(HAL_GetTick()-g_Key_Info[keyIndex].prvTime>LONG_PRESS_TIME ){g_Key_Info[keyIndex].keyState = KEY_LONG_PRESS;}}else /* 如果松开 */ {g_Key_Info[keyIndex].keyState = KEY_RELEASE;return (keyIndex+0x01); /* 返回短按对应码值 0x01 0x02 0x03 ..... */ }break;case KEY_LONG_PRESS :if(!keyPress ) /* 如果松开 */ {g_Key_Info[keyIndex].keyState = KEY_RELEASE;return (keyIndex+0x81); /* 返回短按对应码值 0x81 0x82 0x83 ..... */ } break;default:g_Key_Info[keyIndex].keyState = KEY_RELEASE;}return 0;
}/*** @brief 扫描单个按键 按键的码值* @param 无* @retval 键值*/
uint8_t GetKeyVal(void)
{uint8_t res = 0; for(uint8_t i=0;i<KEY_NUM_MAX;i++){res = keyScan(i); /* 临时保存键值 */if(res!= 0) /* 返回键值不为0,则跳出 */{break;}}return res; /* 返回键值 */
}/*** @brief 按键处理函数* @param 无* @retval 无*/void KeyHandler(void)
{uint8_t KEY_STATE;KEY_STATE=GetKeyVal();switch(KEY_STATE){case B1_SHORT_PRESS:break;case B1_LONG_PRESS:break;case B2_SHORT_PRESS:break;case B2_LONG_PRESS:break;case B3_SHORT_PRESS:break;case B3_LONG_PRESS:break;case B4_SHORT_PRESS:break;case B4_LONG_PRESS:break;}
}
key.h
/******************************************************************************************************* @file key.h* @author Kyro Qu* @brief 按键驱动代码* 实验平台: STM32G431RB开发板*****************************************************************************************************/#ifndef __KEY_H
#define __KEY_H#include "main.h"//按键另一端口的电平 1为高电平 0为低电平
#define ElECTRIC_LEVEL 0/* 键值 */
#define B1_SHORT_PRESS 0x01
#define B1_LONG_PRESS 0x81#define B2_SHORT_PRESS 0x02
#define B2_LONG_PRESS 0x82#define B3_SHORT_PRESS 0x03
#define B3_LONG_PRESS 0x83#define B4_SHORT_PRESS 0x04
#define B4_LONG_PRESS 0x84uint8_t keyScan(uint8_t mode);/* 按键扫描函数 */
uint8_t GetKeyVal(void);
void KeyHandler(void);#endif