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

ESP32播放音频反馈后复位,报abort()错误求助

问题分析与修复方案

核心问题:内存泄漏与非法内存访问

ESP32触发abort()复位的主要原因是内存耗尽和非法指针操作,结合代码细节,以下是具体问题和修复方法:

1. 内存泄漏:malloc未释放

在updateSerial()函数中,使用malloc为lower分配内存后未调用free释放,每次处理短信都会占用新内存,最终堆内存耗尽触发系统abort。

修复代码:
在updateSerial()末尾添加内存释放逻辑:

// ... 原有代码
response = "";
res = "";
free(lower); // 释放malloc分配的内存
lower = nullptr; // 清空指针避免悬空

2. 非法指针与全局变量滥用

  • response = &res[0];:res是String对象,执行res = ""后,response会变成悬空指针,后续操作会访问非法内存。
  • CheckWordInString_rs和CheckWordInString_rsDot函数接收source参数,但实际使用全局变量lower,逻辑混乱且易引发指针错误。

修复代码:

  • 直接用String自带的toLowerCase()方法转换,无需额外分配内存:
// 替换updateSerial中转换小写的代码
String lower_str = res.toLowerCase();
const char* lower = lower_str.c_str();
Serial.print("whole Msg - "); Serial.println(lower);
  • 修改检查函数,使用传入的source参数而非全局lower:
int CheckWordInString_rs(char source[100]) {
  int i = 0;
  const int src_len = strlen(source);
  // 遍历source并添加边界检查
  while (i < src_len - 1 && (source[i] != 'r' || source[i + 1] != 's')) {
    i++;
  }
  // 未找到目标字符串则返回
  if (i >= src_len -1) return -1;
  
  String result = String(source).substring(i + 3);
  // ... 后续代码不变
}

int CheckWordInString_rsDot(char source[100]) {
  int i = 0;
  const int src_len = strlen(source);
  while (i < src_len - 2 && (source[i] != 'r' || source[i + 1] != 's' || source[i + 2] != '.')) {
    i++;
  }
  if (i >= src_len -2) return -1;
  
  String result = String(source).substring(i + 4);
  // ... 后续代码不变
}

3. SoftwareSerial与ESP32硬件冲突

ESP32自带多个硬件串口,使用SoftwareSerial会占用CPU资源,还可能与SIM800L使用的Serial2产生冲突,导致系统不稳定。

修复方案:
将DFPlayer Mini切换到硬件串口,比如Serial1:

// 删除原有SoftwareSerial定义
// SoftwareSerial mySoftwareSerial(33, 25);
#define DFSerial Serial1 // 使用硬件串口1

void setup() {
  // ... 原有代码
  DFSerial.begin(9600); // 初始化硬件串口
  if (!myDFPlayer.begin(DFSerial, true, false)) { // 改用硬件串口通信
    // ... 原有错误处理
  }
}

注意:需调整DFPlayer Mini的接线,连接到ESP32对应硬件串口的RX/TX引脚(具体引脚参考ESP32型号手册)。

4. 阻塞式循环导致系统异常

updateSerial()中的while (!SerialAT.available())会无限阻塞loop,导致DFPlayer状态无法及时处理,还可能因按钮频繁触发voice_commands引发资源竞争。

修复方案:
改为非阻塞式检查,添加按钮防抖:

void updateSerial() {
  // 替换原阻塞循环
  if (!SerialAT.available()) {
    if (digitalRead(Prev_button) == LOW) {
      static unsigned long lastPress = 0;
      // 500ms防抖
      if (millis() - lastPress > 500) {
        voice_commands(final_amount);
        lastPress = millis();
      }
    }
    return; // 直接返回,不阻塞loop
  }

  // ... 原有读取串口代码
}

5. 字符串越界风险

CheckWordInString_rs和CheckWordInString_rsDot的循环未做边界检查,若字符串中无"rs"或"rs.",会导致数组越界访问触发系统错误。

修复方案:
在循环中添加长度判断,避免越界:

// 以CheckWordInString_rs为例
const int src_len = strlen(source);
while (i < src_len -1 && (source[i] != 'r' || source[i + 1] != 's')) {
  i++;
}
// 未找到目标则直接返回
if (i >= src_len -1) return -1;

验证步骤

  1. 修复代码后重新编译上传至ESP32
  2. 测试收款短信触发音频播放,观察是否仍会复位
  3. 查看串口监视器,确认无内存相关错误信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:53:10