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

ESP32在ISR执行期间触发LoadProhibited报错的解决方法咨询

问题根源

你出现崩溃的核心原因不是命令耗时太长,中断服务程序(ISR)上下文不允许调用任何非ISR安全的函数,你用到的Serial.println、LVGL相关操作、显示驱动接口、电源管理类函数大部分都不是ISR安全的,这些函数内部会调用FreeRTOS系统调用、持有互斥锁,在中断上下文运行会直接触发异常,也就是你看到的Guru Meditation报错。

原来的示例代码耗电高的原因是loop()里固定执行delay(1000),即使没有中断事件,CPU也会定时唤醒空转,白白消耗电量。

解决方案

不要尝试把业务逻辑放到ISR中执行,仅需修改loop的轮询逻辑,让CPU在没有事件的时候处于休眠状态即可,功耗可以降到你预期的水平,操作步骤如下:

  1. 保留ISR仅做事件标记的逻辑,标记事件的布尔变量必须加volatile修饰:
volatile bool axpIrq = false;
// 其余全局变量保持不变
  1. ISR里只做标记,不要添加任何业务逻辑:
attachInterrupt(AXP202_INT, [] {
    axpIrq = true;
}, FALLING);
  1. 把原来loop()里的delay(1000)替换为休眠等待逻辑,没有事件的时候CPU直接进入轻量睡眠,几乎不消耗电量,只有中断触发才会唤醒执行逻辑:
void loop() {
    if (axpIrq) {
        axpIrq = false;
        ttgo->power->readIRQ();
        // 所有业务逻辑都放在这里,包括Serial打印、调用low_energy()、显示操作等
        if (ttgo->power->isPEKShortPressIRQ()) {
            Serial.println("button pressed");
            low_energy();
        }
        // 其余IRQ事件判断逻辑保持不变
        ttgo->power->clearIRQ();
    }
    // 替换原来的delay(1000),无事件时核心休眠
    esp_light_sleep_start();
}

如果你需要同时处理定时任务,比如每秒更新时间,可以搭配esp_sleep_enable_timer_wakeup设置定时唤醒,比如设置1秒定时唤醒,既可以处理定时任务,无事件时核心也处于休眠状态,功耗比原来空转delay低90%以上:

void loop() {
    // 你的事件处理逻辑保持不变

    // 单位为微秒,1000000对应1秒,可按需调整时长
    esp_sleep_enable_timer_wakeup(1000000);
    esp_light_sleep_start();
}

双核方案补充说明

ESP32确实搭载两个核心,但不建议把中断处理逻辑绑定到第二核心运行,上述中断标记+休眠等待的方案已经可以实现最低功耗,完全满足智能手表的使用需求,实现逻辑也更简单,不需要额外处理多核同步问题。

内容的提问来源于stack exchange,提问作者Παναγιώτης Θ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:15:03