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 秒触发操作" 的功能。

相关推荐
零一iTEM1 小时前
MAX98357A_音频输出测试
单片机·嵌入式硬件·开源·音视频·硬件工程
逐步前行1 小时前
STM32_标准库结构
stm32·单片机·嵌入式硬件
Hello_Embed1 小时前
libmodbus STM32 主机实验(USB 串口版)
笔记·stm32·学习·嵌入式·freertos·modbus
不做无法实现的梦~2 小时前
PX4各个模块的作用(3)
linux·stm32·嵌入式硬件·机器人·自动驾驶
清风6666662 小时前
基于单片机的喷漆机器人自动控制系统
单片机·嵌入式硬件·机器人·毕业设计·课程设计·期末大作业
不能跑的代码不是好代码2 小时前
STM32独立看门狗(IWDG)知识点及标准库使用指南
stm32·嵌入式硬件
程序员良许2 小时前
嵌入式处理器架构
后端·单片机·嵌入式
来自晴朗的明天3 小时前
15、隔离 DC-DC 电源电路(18S12 模块)
单片机·嵌入式硬件·硬件工程
我送炭你添花3 小时前
电子世界的奇妙冒险:从一个电阻开始(系列目录)
人工智能·单片机·嵌入式硬件·fpga开发
VekiSon3 小时前
Linux内核驱动——设备树原理与应用
linux·c语言·arm开发·嵌入式硬件