You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32硬件定时器首次正常触发后后续回调未执行的问题求助

解决ESP32硬件定时器第二次触发后回调不执行的问题

你的问题出在定时器的闹钟状态管理上:第一次触发后,闹钟要么被自动禁用(单次模式),要么被timerStop()停止计数但状态未正确处理,导致第二次调用timerRestart()时,定时器计数重启但闹钟未启用,无法触发回调。

修改后的代码及说明

1. 回调函数调整

void IRAM_ATTR LaunchTimerEnd() {
  function_to_turn_off_GPIO();
  portENTER_CRITICAL_ISR(&timerMux);
  input_values.LTE_value = true;    // 通知FSM定时器已完成
  portEXIT_CRITICAL_ISR(&timerMux);
  timerAlarmDisable(launch_current_timer); // 显式禁用闹钟,确保状态正确
  Serial.println("***LT OFF");
}
  • 移除timerStop(),改用timerAlarmDisable():我们需要禁用闹钟触发而非单纯停止计数,避免后续启动时状态混乱。

2. 定时器初始化调整

void timerSetup() {
  launch_current_timer = timerBegin(0, 80, true);
  timerAttachInterrupt(launch_current_timer, &LaunchTimerEnd, false);
  timerAlarmWrite(launch_current_timer, 5000000, false); // 设置为单次触发(5秒)
  // 初始状态不启用闹钟,避免定时器自动运行
  input_values.LTE_value = true;
}
  • 将timerAlarmWrite()的最后参数设为false(单次触发),匹配你“每次启动后只运行一次”的需求。
  • 去掉初始的timerAlarmEnable(),让定时器默认处于未激活状态。

3. 定时器启动函数调整

void LaunchTimerStart() {
  portENTER_CRITICAL(&timerMux);
  input_values.LTE_value = false;   // 通知FSM定时器正在运行
  portEXIT_CRITICAL(&timerMux);
  Serial.println("***LT ON");
  timerRestart(launch_current_timer); // 重置定时器计数到0
  timerAlarmEnable(launch_current_timer); // 启用闹钟,触发5秒后的中断
}
  • 每次启动时先重置计数到0,再启用闹钟:确保定时器从0开始计时,且闹钟处于激活状态,到时间必然触发回调。

额外注意事项

  • 如果定时器0被其他代码占用,可尝试更换定时器编号(ESP32支持0-3共4个硬件定时器)。
  • IRAM_ATTR必须保留,中断回调函数需存储在IRAM中以保证执行效率。
  • 中断内的Serial.println()仅用于调试,正式代码建议移除或改用非阻塞日志方式。

内容的提问来源于stack exchange,提问作者user1045680

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:57:18