这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【转载】延时函数的陷阱----from阿淼

共1条 1/1 1 跳转至

【转载】延时函数的陷阱----from阿淼

工程师
2026-08-22 02:16:49     打赏

朋友们,刚接触STM32时,大家可能都写过那种用for循环空转的延时函数。这种软件延时不仅精度极差,而且一旦遇到中断打断或者编译器优化,就会彻底失效。即使后来我们换成了SysTick或者硬件定时器做延时,本质上依然是让CPU原地踏步的阻塞式等待。在稍微复杂一点的工程里,我们必须彻底抛弃阻塞式延时的思维。真正的非阻塞调度,是利用一个基础定时器(比如TIM2)产生1ms的系统滴答,然后在主循环里通过记录时间戳来判断任务是否该执行。这样在等待的这段时间里,CPU完全可以去处理按键扫描、屏幕刷新或者传感器读取。

这种基于时间片轮询的轻量级调度框架,代码极其精简,而且没有任何阻塞。只要记住在任务函数里绝对不要使用任何死等延时,控制好单次任务的执行时长,你就能用裸机跑出类似操作系统的流畅感。这是从单片机爱好者迈向嵌入式工程师的必经之路。

当我们真正开始构建非阻塞调度框架时,会遇到一个非常考验编程功底的问题,那就是时间戳的溢出处理。在裸机系统中,我们通常使用一个32位的无符号整型变量(uint32_t)来记录毫秒级的系统滴答。当系统连续运行大约49.7天后,这个计数器就会从最大值溢出并归零。如果在判断时间差时,我们使用了常规的大小比较(例如if(current_time>target_time)),那么一旦跨越了溢出边界,条件判断就会彻底失效,导致任务永远无法执行或者疯狂执行。

解决这个问题的黄金法则,是利用无符号整数减法的天然溢出特性。我们永远不应该直接比较两个绝对时间的大小,而是应该计算时间差:if((current_time-last_time)>=interval)。因为无符号整数相减时,即使发生了下溢,其结果的二进制补码表示依然能够正确反映出两个时间点之间的真实间隔。这种利用底层数据类型特性来规避逻辑漏洞的做法,是高级嵌入式工程师的标志。此外,在设计非阻塞任务时,我们必须严格遵循“快进快出”的原则。任何一个任务函数的执行时间,都绝对不能大于系统的时间片基准。如果某个任务(比如LCD刷屏)确实需要耗费大量时间,我们就必须将其拆分成多个状态机步骤,每次只执行一小部分,将执行权迅速交还给主循环。这种将“时间维度”引入代码设计的思维,正是我们摆脱裸机桎梏、走向复杂系统架构的关键一步。


来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]