ESP32保存时间至SPIFFS时触发重启的问题求助
ESP32点击网页按钮触发重启(LoadProhibited Guru Meditation Error)
我尝试通过ESP32托管的网页将当前时间与日期保存至SPIFFS,但点击按钮 <button type="button" onclick="sendTime()">Record Time&Date</button> 时,ESP32会立即触发重启,串口输出Guru Meditation Error(LoadProhibited)。
前端JavaScript代码
<script> function sendTime() { // 获取当前时间和日期 const now = new Date(); const dateStr = now.toLocaleDateString(); const timeStr = now.toLocaleTimeString(); // 创建请求体 const body = { date: dateStr, time: timeStr }; // 向服务器发送HTTP POST请求 fetch('/save-time', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) .then(response => { if (!response.ok) { throw new Error('Error saving time to server'); } }) .catch(error => { console.error(error); }); } </script>
ESP32服务端代码
使用的库:WiFi.h、FS.h、SPIFFS.h、Arduino.h、ArduinoJson.h 和 ESPAsyncWebServer.h
setup()代码片段
// 初始化SPIFFS if (!SPIFFS.begin(true)) { Serial.println("Failed to mount file system"); return; } Serial.println("SPIFFS mounted"); // 设置路由 server.on("/save-time", HTTP_POST, [](AsyncWebServerRequest *request){ // 获取请求体字符串 String body = request->getParam("plain")->value(); // 解析JSON格式的请求体 DynamicJsonDocument doc(1024); deserializeJson(doc, body); // 从请求体中获取日期和时间 String dateStr = doc["date"].as<String>(); String timeStr = doc["time"].as<String>(); // 用日期创建文件名 String fileName = "/watering-" + dateStr + ".txt"; // 打开文件用于写入 File file = SPIFFS.open(fileName, FILE_APPEND); if (!file) { Serial.println("Failed to open file for writing"); request->send(500, "text/plain", "Failed to open file for writing"); return; } // 写入时间到文件 file.print(timeStr); file.print("\n"); // 关闭文件 file.close(); // 返回成功响应 request->send(200, "text/plain", "Time saved successfully"); }); // 获取浇水时间记录的路由 server.on("/watering-times", HTTP_GET, [](AsyncWebServerRequest *request){ String response = ""; // 获取根目录下的所有文件 File root = SPIFFS.open("/"); File file = root.openNextFile(); while(file){ // 检查文件名是否以"watering-"开头 String fileName = file.name(); if (fileName.startsWith("/watering-")) { // 读取文件内容并添加到响应字符串中 response += fileName.substring(10, 20) + " " + file.readString() + "<br>"; } file = root.openNextFile(); } // 返回包含浇水时间记录的响应 request->send(200, "text/html", response); }); // 启动服务器 server.begin();
串口错误输出
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. Core 1 register dump: PC : 0x400dec30 PS : 0x00060e30 A0 : 0x800dec6e A1 : 0x3ffd2280 A2 : 0x3ffd230c A3 : 0x00000010 A4 : 0x00000005 A5 : 0x0000ff00 A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x800de95c A9 : 0x3ffd2260 A10 : 0x00000010 A11 : 0x00000000 A12 : 0x00000006 A13 : 0x3ffce334 A14 : 0x00ff0000 A15 : 0x00000002 SAR : 0x0000001b EXCCAUSE: 0x0000001c EXCVADDR: 0x0000001f LBEG : 0x40089db9 LEND : 0x40089dc9 LCOUNT : 0xfffffffe Backtrace: 0x400dec2d:0x3ffd2280 0x400dec6b:0x3ffd22a0 0x400d45a2:0x3ffd22c0 0x400d48a5:0x3ffd2390 0x400dbbf9:0x3ffd23b0 0x400d9fbd:0x3ffd2400 0x400da02d:0x3ffd2450 0x400dcca5:0x3ffd2470 0x400dcd21:0x3ffd24a0 0x400dd32a:0x3ffd24c0 ELF file SHA256: 78ff020431f74c0c Rebooting...
问题原因及修复方案
核心问题
request->getParam("plain")->value() 直接访问了可能为空的指针。当请求为JSON格式时,plain 参数不一定存在,直接调用 ->value() 会触发空指针引用,导致LoadProhibited错误(访问无效内存地址)。
修复后的/save-time路由代码
server.on("/save-time", HTTP_POST, [](AsyncWebServerRequest *request){ // 检查plain参数是否存在 AsyncWebParameter* param = request->getParam("plain"); if (!param) { Serial.println("No request body received"); request->send(400, "text/plain", "Missing request body"); return; } // 获取请求体字符串 String body = param->value(); // 解析JSON并检查错误 DynamicJsonDocument doc(1024); DeserializationError jsonError = deserializeJson(doc, body); if (jsonError) { Serial.print("JSON parse failed: "); Serial.println(jsonError.c_str()); request->send(400, "text/plain", "Invalid JSON format"); return; } // 提取并验证日期、时间字段 String dateStr = doc["date"].as<String>(); String timeStr = doc["time"].as<String>(); if (dateStr.isEmpty() || timeStr.isEmpty()) { Serial.println("Missing date or time in request"); request->send(400, "text/plain", "Missing date or time"); return; } // 替换日期中的非法字符(避免SPIFFS路径错误) dateStr.replace("/", "-"); String fileName = "/watering-" + dateStr + ".txt"; // 打开文件并写入 File file = SPIFFS.open(fileName, FILE_APPEND); if (!file) { Serial.println("Failed to open file for writing"); request->send(500, "text/plain", "Failed to open file for writing"); return; } file.print(timeStr); file.print("\n"); file.close(); request->send(200, "text/plain", "Time saved successfully"); });
额外优化说明
- 空指针检查:先判断
plain参数是否存在,避免直接访问空指针 - JSON解析校验:添加DeserializationError检查,处理无效JSON格式
- 文件名合法性:替换日期中的斜杠
/为-,避免SPIFFS路径解析错误 - 参数有效性验证:确保日期和时间字段不为空
内容的提问来源于stack exchange,提问作者Svet GEoff
相关产品推荐
相关产品推荐

