如何让一段代码持续运行指定时长?
让LED精准闪烁指定时长的修复方案
你的代码核心问题是时间计算逻辑错误加上状态变量未重置,导致LED要么不按预期停止,要么后续触发失效。以下是具体修复:
核心问题分析
t_Diff未初始化:第一次进入内层while循环时,t_Diff是随机值,可能直接跳过循环或进入异常逻辑。clock()不适合嵌入式延时计时:clock()测量的是CPU占用时间,而HAL_Delay()是阻塞延时(CPU处于休眠),两者不匹配,时间计算会偏差。goodAttempt未重置:触发一次后goodAttempt被设为2,后续再触发GPIO_PIN_6时,内层循环直接不执行。- 整数除法导致精度丢失:
(t_Final-t_Zero)/CLOCKS_PER_SEC是整数除法,会丢失小数部分,时间计算不准确。 - 无用变量
i:每次循环都初始化i=0再自增,完全没有作用,可删除。
修复后的代码
#include <stdio.h> #include <time.h> int main() { uint32_t start_tick; // 用HAL的系统滴答定时器,精度更可靠 int goodAttempt = 1; const uint32_t BLINK_DURATION = 15000; // 要运行的时长:15秒(单位ms) while (1) { if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET) { // 触发后先初始化状态 goodAttempt = 1; // 点亮指示LED HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); HAL_Delay(5000); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 记录闪烁开始的系统滴答数 start_tick = HAL_GetTick(); // 循环闪烁直到达到指定时长,或触发终止条件 while ((HAL_GetTick() - start_tick) < BLINK_DURATION && goodAttempt == 1) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); HAL_Delay(100); // 100ms间隔,5Hz闪烁 // 检查终止条件:GPIOA_PIN_5和GPIOB_PIN_5同时为高 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_SET && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5) == GPIO_PIN_SET) { goodAttempt = 2; break; } } // 退出闪烁后确保LED处于熄灭状态(可选) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); } } }
关键修改说明
- 改用
HAL_GetTick():这是STM32 HAL库提供的系统滴答定时器接口,返回自系统启动后的毫秒数,适合测量实际流逝时间,和HAL_Delay()完全匹配。 - 初始化状态变量:每次触发GPIO_PIN_6时,重置
goodAttempt为1,保证后续触发能正常进入闪烁循环。 - 直接用毫秒计算:把15秒转换成15000毫秒,避免浮点数运算,更高效准确。
- 移除无用变量:删掉了无意义的
i和错误的clock_t相关变量。 - 添加LED复位:退出循环后把闪烁LED置低,避免停留在点亮状态。
内容的提问来源于stack exchange,提问作者Daniel Joseph
相关产品推荐
相关产品推荐

