STM32——使用定时器+按键中断来实现长按事件检测触发

复制代码
#include "main.h"
#include "tim.h"
void Key_ExitEvent()
{
	static bool flag=true;
	if(flag)
	{
		HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
	}
	else
	{
		HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
	}
	flag=!flag;
	HAL_TIM_Base_Stop_IT(&htim2);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==KEY1_Pin)
	{
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
		{
		//去除定时器 2(TIM2)的更新中断标志位(UIF) 的宏函数
		//防止定时器中断上电误触发
		__HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF); 
		htim2.Instance->CNT=0;
		HAL_TIM_Base_Start_IT(&htim2);		
		}
		else
		{
			HAL_TIM_Base_Stop_IT(&htim2);
		}
	}
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM2)
	{
		//进入定时器中断后再次对按键IO口高低电平进行判断,如果此时按键依然按下说明是长按9
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
		{
		Key_ExitEvent();		
		}
		HAL_TIM_Base_Stop_IT(&htim2);
	}
	
}

该程序实现 "按键持续按下 3 秒后执行 LED 状态翻转" 的核心执行过程如下,可分为 4 个关键阶段:

1. 按键按下(触发外部中断)

  • 当按键KEY1被按下(假设低电平有效,即HAL_GPIO_ReadPin返回0)时,触发HAL_GPIO_EXTI_Callback中断回调函数。
  • 函数内首先清除定时器TIM2的更新中断标志位(UIF),防止上电时误触发。
  • 清零TIM2的计数器(CNT),确保从 0 开始计时,然后启动TIM2的定时中断(HAL_TIM_Base_Start_IT),开始 3 秒计时。

2. 定时器计时期间(3 秒内)

  • TIM2以 3 秒为周期运行,计数器从 0 开始累加。
  • 若在 3 秒内松开按键(HAL_GPIO_ReadPin返回1),则再次触发HAL_GPIO_EXTI_Callback,执行else分支:立即停止TIM2定时中断(HAL_TIM_Base_Stop_IT),计时终止,后续无操作。
  • 若 3 秒内持续按下按键,TIM2会继续计时直到 3 秒结束。

3. 定时器 3 秒溢出(触发定时中断)

  • TIM2计时满 3 秒,触发HAL_TIM_PeriodElapsedCallback定时中断回调函数。
  • 函数内首先判断定时器实例为TIM2,然后再次检查按键状态
    • 若按键仍处于按下状态(HAL_GPIO_ReadPin返回0,即持续按下 3 秒),则调用Key_ExitEvent执行操作。
    • 若按键已松开(HAL_GPIO_ReadPin返回1),则不执行任何操作。
  • 无论是否执行操作,最终都会停止TIM2定时中断(HAL_TIM_Base_Stop_IT)。

4. 执行 LED 状态翻转(Key_ExitEvent函数)

  • 该函数通过静态变量flag记录 LED 当前状态,初始为true
  • flagtrue时,熄灭 LED(GPIO_PIN_RESET);为false时,点亮 LED(GPIO_PIN_SET)。
  • 执行后翻转flag状态(flag=!flag),并再次停止TIM2(双重保障,防止定时器未正确停止)。

核心逻辑总结

程序通过 "外部中断启动定时 + 定时中断时二次检查按键状态" 的机制,确保只有当按键持续按下满 3 秒时,才会执行 LED 状态翻转;若中途松开按键,会提前终止计时,不执行任何操作,最终实现 "长按 3 秒触发操作" 的功能。

相关推荐
真的想上岸啊1 天前
开发STM32日记1:安装软件、配置软件(芯片为STM32F103C8T6 )
stm32·单片机·嵌入式硬件
bai5459361 天前
按键控制LED灯亮灭
单片机·嵌入式硬件
赋能大师兄1 天前
单片机/嵌入式修行之路
单片机·嵌入式
Maryfang132918915511 天前
RTL8367RB的国产P2P替代方案用JL6107-PC的可行性及实现方法
单片机·网络协议·p2p
ACP广源盛139246256731 天前
GSV6127E(EA)#Type-C / 显示端口 1.4/HDMI 2.0 转 MIPI/LVDS 转换器(带音频提取和嵌入式微控制器)
单片机·嵌入式硬件·音视频
.普通人1 天前
stm32f103c8t6寄存器点灯法
stm32·单片机·嵌入式硬件
电子工程师-C511 天前
基于单片机的智能手表
单片机·嵌入式硬件·智能手表
蓁蓁啊1 天前
ARM交叉编译中编译与链接参数不一致导致的问题
开发语言·arm开发·嵌入式硬件
Jerry丶Li1 天前
二十八、STM32的USART (介绍)
stm32·单片机·嵌入式硬件
偶像你挑的噻1 天前
3-Linux驱动开发-简单内核模块代码详解
linux·驱动开发·stm32·嵌入式硬件