FreeRTOS定时器大坑:12小时周期变5分钟?解密ms转Ticks的整数溢出陷阱
问题现象
在嵌入式开发中使用FreeRTOS时,我设置了一个12小时(43,200,000毫秒)的定时器,如下
// app_timer_start是我封装后的定时器创建,不影响
app_timer_start(&app_esp8285_send_timer, 43200000, portMAX_DELAY, pdTRUE);
但实际运行时,定时器却在5分钟左右就提前触发,误差超过140倍!
关键代码
// FreeRTOS标准宏定义
#define pdMS_TO_TICKS(xTimeInMs) ((TickType_t)(((TickType_t)(xTimeInMs) *
(TickType_t)configTICK_RATE_HZ) /
(TickType_t)1000U))
// 实际配置
typedef uint32_t TickType_t; // 32位计数器
#define configTICK_RATE_HZ 1000 // 系统时钟1kHz
崩溃的数学计算
问题出在毫秒到Ticks的转换过程:
- 计算原理:
Ticks = (ms × configTICK_RATE_HZ) / 1000 - 预期计算:
43,200,000 × 1,000 = 43,200,000,000 - 实际发生:
43,200,000,000 ÷ 4,294,967,296 = 10.05次整循环
余数 = 43,200,000,000 - (10 × 4,294,967,296)
= 43,200,000,000 - 42,949,672,960
= 250,327,040
- 最终错误结果:
Ticks = 250,327,040 ÷ 1000 = 250,327 Ticks
为什么是5分钟左右
250,327 Ticks × (1000ms/s ÷ 1000 ticks/s) = 250,327毫秒 ≈ 250秒 ≈ 4.17分钟
解决办法
// 在FreeRTOSConfig.h中,会覆盖默认的pdMS_TO_TICKS
#define pdMS_TO_TICKS(x) ((TickType_t)((uint64_t)(x) * \
configTICK_RATE_HZ / 1000U))
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 活着死去
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

