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

ESP32C3挂载FAT格式SD卡创建FILE_10.LOG文件失败求助

问题:ESP32C3创建序号≥10的日志文件失败

我在ESP32C3上挂载了FAT格式SD卡,读写正常。需求是自动创建现有最大序号+1的日志文件(比如目录有FILE_0.LOG、FILE_4.LOG、FILE_5.LOG时,生成FILE_6.LOG)。

编写的代码如下:

#define MOUNT_POINT "/sdcard"
#define MAX_FILENAME_LENGTH 256
char next_filename[MAX_FILENAME_LENGTH];

DIR* dir;
struct dirent* entry;
int max_number = 0;

dir = opendir(MOUNT_POINT);

while ((entry = readdir(dir)) != NULL) {
    int current_number;
    if (sscanf(entry->d_name, "FILE_%d.LOG", &current_number) == 1) {
        ESP_LOGI(TAG, "Extracted number: %d , Max number: %d", current_number, max_number);
        if (current_number > max_number) {
            max_number = current_number;
        }
    }
}

closedir(dir);

int new_number = max_number + 1;
ESP_LOGI(TAG, "%d %d", max_number, new_number);

snprintf(next_filename, MAX_FILENAME_LENGTH, "%s/FILE_%d.LOG", MOUNT_POINT, new_number);

FILE* file = fopen(next_filename, "w");
if (file == NULL) {
    ESP_LOGE(TAG, "Failed to create file: %s\n", next_filename);
    return;
}

fprintf(file, "NEW LOG %d\n", new_number);
fclose(file);

代码在序号小于10时可正常工作,但创建FILE_10.LOG时失败,错误日志如下:

...
I (405) CL: Extracted number: 1 , Max number: 0
I (415) CL: Extracted number: 2 , Max number: 1
I (415) CL: Extracted number: 3 , Max number: 2
I (425) CL: Extracted number: 4 , Max number: 3
I (425) CL: Extracted number: 5 , Max number: 4
I (435) CL: Extracted number: 6 , Max number: 5
I (435) CL: Extracted number: 7 , Max number: 6
I (445) CL: Extracted number: 8 , Max number: 7
I (445) CL: Extracted number: 9 , Max number: 8
I (455) CL: 9 10
E (455) CL: Failed to create file: /sdcard/FILE_10.LOG

代码基于ESP-IDF的SD卡SPI示例开发,请问失败原因是什么?


原因分析与解决方案

1. 优先排查具体错误码

fopen返回NULL时,先打印errno确定具体失败原因,在错误日志后添加代码:

#include <errno.h>
// ...
ESP_LOGE(TAG, "Failed to create file: %s, errno: %d\n", next_filename, errno);

常见错误码对应问题:

  • EEXIST:文件已存在(可能之前创建失败残留了损坏的目录项)
  • ENOSPC:SD卡空间不足
  • EMFILE:同时打开的文件数超过挂载时配置的上限
  • EACCES:无文件创建权限

2. 最可能的核心原因

(1)FATFS长文件名支持未启用

虽然FILE_10.LOG符合FAT的8.3短文件名规则,但ESP-IDF默认可能未开启长文件名(LFN)支持,部分场景下会导致文件名解析或创建异常。

解决:
在menuconfig中开启长文件名支持:

  • 进入Component config → FAT Filesystem Support
  • 勾选Enable long filename support (LFN)
  • 选择长文件名存储方式(推荐Dynamic allocation)

(2)目录遍历未过滤非文件条目

readdir会返回目录中的所有条目(包括.、..目录、隐藏的长文件名辅助条目),虽然你的sscanf不会匹配这些条目,但如果SD卡目录存在异常条目,可能干扰序号计算或文件创建。

解决:
遍历目录时仅处理普通文件:

while ((entry = readdir(dir)) != NULL) {
    // 跳过非普通文件条目
    if (entry->d_type != DT_REG) {
        continue;
    }
    int current_number;
    if (sscanf(entry->d_name, "FILE_%d.LOG", &current_number) == 1) {
        ESP_LOGI(TAG, "Extracted number: %d , Max number: %d", current_number, max_number);
        if (current_number > max_number) {
            max_number = current_number;
        }
    }
}

(3)挂载时文件数上限不足

ESP-IDF的SD卡挂载配置中,max_files参数限制了同时打开的文件数,若未修改示例默认值(通常为5),可能因系统资源限制导致创建失败。

解决:
修改挂载配置的max_files参数,设置更大的值(比如20):

esp_vfs_fat_sdmmc_mount_config_t mount_config = {
    .format_if_mount_failed = false,
    .max_files = 20, // 增大同时打开的文件数上限
    .allocation_unit_size = 16 * 1024
};

(4)目录打开未做错误检查

代码中未判断opendir是否成功,若目录打开失败,后续逻辑会基于无效的dir指针执行,可能导致异常。

解决:
添加目录打开失败的判断:

dir = opendir(MOUNT_POINT);
if (dir == NULL) {
    ESP_LOGE(TAG, "Failed to open directory: %s", MOUNT_POINT);
    return;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:43:10