STM32如何实现LED点亮指定时长且支持中途中断的功能
实现方案思路
- 核心逻辑用全局状态标志位控制LED状态,纯裸机代码即可实现,不需要额外操作系统组件:
- 配置固定周期的定时器中断(比如1ms触发1次),中断内仅做计时计数累加和标志位修改,不执行复杂逻辑
- 配置按键/触控屏的外部中断,触发时直接重置计时计数、修改LED状态标志,即可实现中途终止
- 主循环仅根据标志位操作LED IO口电平,避免在中断内操作硬件产生抖动问题
示例代码(STM32 HAL库版本)
首先定义全局变量:
/* 全局变量定义,中断访问的变量必须加volatile避免编译器优化 */ volatile uint32_t led_on_counter = 0; // LED点亮剩余计时,单位ms volatile uint8_t led_running_flag = 0; // LED点亮进程标志:1=运行中,0=已停止 #define LED_TARGET_DURATION 5000 // 预设LED总点亮时长为5000ms=5s
定时器中断回调函数:
/* 定时器更新中断回调,配置为1ms触发一次 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { // 假设使用TIM2作为计时定时器 if (led_running_flag == 1 && led_on_counter > 0) { led_on_counter--; if (led_on_counter == 0) { led_running_flag = 0; // 计时结束,自动修改停止标志 } } } }
外部中断回调函数(按键触发终止用):
/* 外部中断回调,按键按下时触发 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == KEY_Pin) { // 假设按键接在对应外部中断引脚上 if (led_running_flag == 1) { // 中途终止LED点亮流程 led_on_counter = 0; led_running_flag = 0; } } }
主循环逻辑:
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); // 配置TIM2定时周期为1ms HAL_TIM_Base_Start_IT(&htim2); // 启动TIM2中断 /* LED点亮触发入口,可替换为触控屏触发、指令触发等自定义逻辑 */ led_on_counter = LED_TARGET_DURATION; led_running_flag = 1; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); // 点亮LED while (1) { /* 主循环仅根据标志位控制LED电平 */ if (led_running_flag == 0) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); // 熄灭LED } } }
注意事项
- 中断内不要放延时、串口打印等耗时逻辑,仅做计数和标志位修改,保证实时性
- 如果需要同时控制多个LED的定时点亮,可将计数器和标志位改为数组,分别对应每个LED的状态即可
内容的提问来源于stack exchange,提问作者Donkanaille
相关产品推荐
相关产品推荐

