32单片机按键扫描 实现长短按

key.c

cpp 复制代码
/**
 ****************************************************************************************************
 * @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

cpp 复制代码
/**
 ****************************************************************************************************
 * @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
相关推荐
悠哉悠哉愿意7 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
Lester_11017 天前
STM32霍尔传感器输入口设置为复用功能输入口时,还能用GPIO函数直接读取IO的状态吗
stm32·单片机·嵌入式硬件·电机控制
LCG元7 天前
低功耗显示方案:STM32L0驱动OLED,动态波形绘制与优化
stm32·嵌入式硬件·信息可视化
三佛科技-187366133977 天前
120W小体积碳化硅电源方案(LP8841SC极简方案12V10A/24V5A输出)
单片机·嵌入式硬件
z20348315207 天前
STM32F103系列单片机定时器介绍(二)
stm32·单片机·嵌入式硬件
Alaso_shuang7 天前
STM32 核心输入、输出模式
stm32·单片机·嵌入式硬件
脚后跟7 天前
AI助力嵌入式物联网项目全栈开发
嵌入式硬件·物联网·ai编程
2501_918126917 天前
stm32死锁是怎么实现的
stm32·单片机·嵌入式硬件·学习·个人开发
z20348315207 天前
STM32F103系列单片机定时器介绍(一)
stm32·单片机
星马梦缘7 天前
驱动层开发——蜂鸣器驱动
stm32·单片机·嵌入式硬件·hal·驱动