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

ESP32CAM日志写入SD卡仅出现乱码问题排查求助

问题原因及修复方案

核心错误分析

日志文件出现乱码的直接原因是写入了指针地址而非字符串内容,同时存在SD卡重复挂载/卸载的低效操作:

  1. 错误的fwrite参数

    • &info传递的是指针变量自身的地址,而非字符串的起始地址,导致写入的是指针的内存值(如L@?这类乱码),正确写法应为直接使用info。
    • sizeof(info)返回的是指针类型的大小(ESP32上为4字节),而非字符串的实际长度,需替换为strlen(info)获取字符串长度。
  2. SD卡重复挂载/卸载
    每次调用Log函数都重新初始化并卸载SD卡,不仅效率极低,还可能导致文件系统不稳定,应改为初始化时挂载一次,仅在设备 shutdown 时卸载。

  3. 缺乏错误检查
    未校验fopen和Open_Card的返回值,若SD卡或文件操作失败会引发未定义行为。

修复后的代码

1. 全局SD卡初始化(建议放在setup函数中)

#include <string.h>
#include <sys/stat.h>
#include <sys/unistd.h>

sdmmc_card_t *g_card = NULL; // 全局存储SD卡指针

// 初始化SD卡(仅调用一次)
void Init_SD_Card() {
    g_card = Open_Card();
    if (g_card == NULL) {
        // 处理SD卡初始化失败逻辑
        return;
    }
}

// 卸载SD卡(仅在关机时调用)
void Deinit_SD_Card() {
    if (g_card != NULL) {
        esp_vfs_fat_sdcard_unmount(MOUNT_POINT, g_card);
        g_card = NULL;
    }
}

2. 修复后的Log函数

void Log(const char *info){
    if (g_card == NULL || info == NULL) {
        return; // SD卡未初始化或输入为空,直接返回
    }

    FILE *f;
    const char *file_foo = MOUNT_POINT"/Log.txt";

    // 打开文件,不存在则创建
    f = fopen(file_foo, "a");
    if (f == NULL) {
        // 处理文件打开失败逻辑
        return;
    }

    // 写入字符串内容
    fwrite(info, 1, strlen(info), f);
    fwrite("\n", 1, 1, f); // 可选:添加换行符,提升日志可读性

    fclose(f);
}

3. 调用示例

// 在setup中初始化SD卡
void setup() {
    Init_SD_Card();
    
    // ...其他初始化逻辑
}

// 在需要记录日志的地方调用
const char *string_err = esp_err_to_name(wifi_err); 
Log(string_err);
Log("This is my ip:");

额外注意事项

  • 确保包含<string.h>头文件,否则strlen函数无法正常使用。
  • 若日志需要包含时间戳,可添加strftime等函数生成时间字符串后拼接写入。
  • SD卡文件系统操作建议添加适当的延时或使用文件系统缓存,避免频繁写入导致SD卡寿命缩短。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:15:00