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
相关推荐
FreakStudio7 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘12 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484912 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150012 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼12 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
wohoo_wangzi12 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘12 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展12 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司12 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
踏着七彩祥云的小丑12 天前
嵌入式测试学习第 37 天:异常场景测试:断电、拔插、干扰、非法指令
单片机·嵌入式硬件·学习