32单片机按键扫描 实现长短按
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_LEVEL
keyPress=!keyPress;
#endif
switch (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 0x84
uint8_t keyScan(uint8_t mode);/* 按键扫描函数 */
uint8_t GetKeyVal(void);
void KeyHandler(void);
#endif