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

ESP32搭配PN532出现LoadProhibited崩溃问题求助

解决ESP32定时器ISR中调用PN532函数导致的Guru Meditation Error崩溃

问题根源

崩溃的核心原因是在中断服务函数(ISR)中执行了不允许的操作:

  • nfc.startPassiveTargetIDDetection涉及SPI通信,属于耗时且依赖系统资源的复杂操作,ISR要求执行时间极短,不能包含这类非原子操作
  • Serial.print依赖硬件中断和缓冲区管理,在ISR中调用会触发死锁或非法内存访问
  • 全局变量boton_restart未加volatile修饰,编译器会优化其读取,导致主循环无法及时获取ISR修改的值
  • 每次检测到卡片都重新初始化定时器,可能造成资源泄漏

修复方案

使用标志位机制,ISR仅做最基础的状态更新,将复杂操作交给主循环处理,同时修正变量修饰和定时器初始化逻辑:

修改后的代码

#include <Wire.h>
#include <SPI.h>
#include <UNIT_PN532.h>

// 引脚定义
#define PN532_SCK  (18)
#define PN532_MOSI (23)
#define PN532_SS   (5)
#define PN532_MISO (19)
#define motor1 (33)
#define motor2 (32)
#define motor3 (25)
#define motor4 (26)
#define boton1 (2)

// 函数声明
void IRAM_ATTR onTimer();
void isr_boton();

// 全局变量(ISR中修改的变量必须加volatile)
volatile int contador = 0;
volatile int boton_restart = 0;
volatile bool stop_motor = false;

UNIT_PN532 nfc(PN532_SS);
hw_timer_t * timer = NULL;

void setup() {
  Serial.begin(115200);
  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (!versiondata) {
    Serial.print("No se encontró la placa PN53x");
    while (1);
  }

  nfc.setPassiveActivationRetries(0xFF);
  nfc.SAMConfig();

  // 初始化电机引脚
  pinMode(motor1, OUTPUT);
  pinMode(motor2, OUTPUT);
  pinMode(motor3, OUTPUT);
  pinMode(motor4, OUTPUT);
  pinMode(boton1, INPUT_PULLDOWN);
  attachInterrupt(boton1, isr_boton, RISING);

  // 提前初始化定时器,避免重复创建
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  // 默认不启用定时器,检测到卡片后再开启
}

void loop() {
  boolean LeeTarjeta;
  uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
  uint8_t LongitudUID;

  LeeTarjeta = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &LongitudUID);
  Serial.println("loop");

  if (LeeTarjeta) {
    // 重置状态并启动定时器
    contador = 0;
    boton_restart = 0;
    stop_motor = false;
    timerAlarmWrite(timer, 1000000, true);
    timerAlarmEnable(timer);
  } else {
    Serial.print(PN532_SCK);
    Serial.println("Se agotó el tiempo de espera de una tarjeta");
  }

  // 处理ISR设置的停止标志
  if (stop_motor) {
    // 停止电机
    digitalWrite(motor1, LOW);
    digitalWrite(motor2, LOW);
    digitalWrite(motor3, LOW);
    digitalWrite(motor4, LOW);
    // 禁用定时器
    timerAlarmDisable(timer);
    // 重启NFC检测
    nfc.startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A);
    Serial.print("fin");
    stop_motor = false;
  }

  vTaskDelay(portMAX_DELAY);
}

void IRAM_ATTR onTimer() {
  // ISR中仅做快速操作
  digitalWrite(motor1, !digitalRead(motor1));
  digitalWrite(motor2, !digitalRead(motor2));
  digitalWrite(motor3, !digitalRead(motor3));
  digitalWrite(motor4, !digitalRead(motor4));
  contador++;

  if (contador == 20 || boton_restart == 1) {
    stop_motor = true; // 设置标志位,由主循环处理后续操作
  }
}

void isr_boton() {
  boton_restart = 1;
}

关键修改点

  1. 变量修饰:给contador、boton_restart、stop_motor添加volatile,防止编译器优化导致的变量值不同步
  2. 定时器初始化:在setup中提前创建定时器,避免每次检测卡片重复分配资源
  3. ISR轻量化:ISR仅翻转电机状态、计数、设置停止标志,所有复杂操作(NFC重启、串口打印、电机停止)都交给主循环处理
  4. 状态分离:将中断逻辑和业务逻辑解耦,避免ISR占用过多系统资源

错误信息解释

Guru Meditation Error: Core 1 panic'ed (LoadProhibited) 表示CPU尝试访问无效的内存地址,这里是因为在ISR中调用了未放入IRAM的函数(如PN532的SPI通信函数),或者执行了依赖中断的操作(如Serial打印),违反了ESP32的中断执行规则。

内容的提问来源于stack exchange,提问作者Ana Maria Montañez Becerra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:17:12