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
相关推荐
码小文17 小时前
CAM350使用笔记(6)---Gerber文件铺铜间距检查
嵌入式硬件·cam350软件·cam350使用笔记
Yiran_G19 小时前
双频 Wi-Fi 6 + 蓝牙 5.4:无声讯通 WS8712 模组的开发与集成要点
网络·嵌入式硬件·物联网·智能家居
光子物联单片机19 小时前
ESP32传感器模块编程实践(一)DIY智能WIFI视频控制小车
嵌入式硬件·esp32·智能硬件·硬件
2501_9226395820 小时前
率能半导体 SS6628E直流双向马达驱动芯片:20V/7A,覆盖电子锁、玩具、无线充电、机器人四大应用场景
单片机·嵌入式硬件·硬件工程
硅基造物主20 小时前
STM32 从 0 到 1 做智能家居(五):工程结构与代码骨架
stm32·单片机·嵌入式硬件·智能家居
深圳老胡20 小时前
STM32F103 硬件 SPI 与软件 IO 模拟 SPI 最高速度差异详解
笔记·stm32·单片机·代码规范·1024程序员节
smartpi_ai20 小时前
机芯智能离线语音模块实战问答:SU-03T、CI-03T、SU-63T 与 JX-A7T 高频问题排查
人工智能·单片机·嵌入式硬件·ci/cd·语音识别
2501_9226395821 小时前
率能半导体 SS6635E直流双向马达驱动芯片:30V/4.5A,覆盖电子锁、玩具、无线充电、机器人四大应用场景
单片机·嵌入式硬件·硬件工程
wuyk55521 小时前
TinyML 初探:在 MCU 上部署异常检测模型,实现本地振动故障诊断
stm32·单片机·嵌入式硬件·重构
新晨单片机设计21 小时前
S031A-基于STM32单片机指纹考勤系统【Proteus仿真+Keil程序+原理图】
stm32·单片机·嵌入式硬件·proteus·指纹考勤系统