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

FatFS CSV写入Bug排查:如何避免向CSV文件写入空行?

解决FatFS CSV写入空行问题

我来帮你排查这个随机出现空行的问题,先从你的代码里找出几个关键问题,再给出修复方案:

空行的核心原因

你遇到的空行大概率是写入了栈上的垃圾数据导致的:

  • 你调用f_write时用了sizeof(buffer)作为写入长度,但snprintf生成的CSV行内容长度远小于50字节,剩下的buffer空间是栈里未初始化的随机数据,这些数据里可能包含\r\n,就会被当成空行写入文件。
  • 另外,你的strcmp(buffer, "") != 0判断完全没用——snprintf至少会输出\r\n,buffer永远不可能是空字符串。

还有一个潜在逻辑问题:你只有在T1-T4全不为0时才写入,但如果某个循环里这些值有0,你跳过了写入,但这不会产生空行;核心问题还是写入垃圾数据导致的。

分步修复方案

1. 只写入有效字符串长度

别再用sizeof(buffer),而是用snprintf的返回值来确定实际要写入的字节数,避免把垃圾数据写到文件里:

// 生成CSV行时获取有效长度
int line_len = snprintf(buffer, sizeof(buffer), "%s,%s,%s,%s,%s,%s\r\n",stUT,stT1,stT2,stT3,stT4,stPd);
// 确保生成的字符串有效且未溢出buffer
if (line_len > 0 && line_len < sizeof(buffer)) {
    UINT bytes_written;
    ff_result = f_write(&file, buffer, line_len, &bytes_written);
}

2. 提前过滤无效数据

把数据有效性判断移到生成buffer之前,避免做无用的字符串拼接:

for(int i = 0; i<MAXIMUM_BUFFER_STORAGE;i ++)
{
    // 先判断数据是否有效,无效直接跳过当前循环
    if((SD_CARD_T1[i] == 0) || (SD_CARD_T2[i] == 0) || (SD_CARD_T3[i] == 0) || (SD_CARD_T4[i] == 0))
    {
        ID++;
        continue;
    }

    // 下面再做字符串拼接和写入操作
    char buffer[50];
    // ... 你的sprintf代码 ...
}

3. 修复写入字节数统计

你现在用单次写入的bytes_written乘以循环次数来统计总字节数,这完全错误——每次f_write会覆盖bytes_written的值。应该定义一个累加变量:

// 循环前初始化累加变量
UINT total_bytes = 0;

// 写入成功后累加
total_bytes += bytes_written;

// 最后日志输出总字节数
NRF_LOG_INFO("Write new entry %d bytes written.", total_bytes);

4. 优化浮点数输出精度(可选)

你用%f输出浮点数,默认精度会生成较长的字符串,容易导致buffer溢出,建议指定精度,比如保留两位小数:

sprintf(stPd, "%.2f", SD_CARD_Pdiff[i]);

5. 简化错误处理逻辑

你代码里f_open的错误判断重复了,简化成:

ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
if(ff_result != FR_OK)
{
    NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
    SD_CARD_PRESENT = 0;
    return;
}

修复后的完整代码

void Write_block_to_sd_card() {
    while (fno.fname[0]);
    FRESULT ff_result;
    FIL file;
    UINT total_bytes_written = 0;

    ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
    if(ff_result != FR_OK) {
        NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
        SD_CARD_PRESENT = 0;
        return;
    }

    NRF_LOG_RAW_INFO("");
    NRF_LOG_INFO("Writing to file as a block " FILE_NAME "...");
    SD_CARD_PRESENT = 1;

    for(int i = 0; i < MAXIMUM_BUFFER_STORAGE; i++) {
        // 提前过滤无效数据
        if((SD_CARD_T1[i] == 0) || (SD_CARD_T2[i] == 0) || (SD_CARD_T3[i] == 0) || (SD_CARD_T4[i] == 0)) {
            ID++;
            continue;
        }

        char buffer[50];
        char stT1 [MAX_BUFFER_SIZE];
        char stT2 [MAX_BUFFER_SIZE];
        char stT3 [MAX_BUFFER_SIZE];
        char stT4 [MAX_BUFFER_SIZE];
        char stPd [MAX_BUFFER_SIZE];
        char stUT [MAX_BUFFER_SIZE];

        sprintf(stT1, "%d", SD_CARD_T1[i]);
        sprintf(stT2, "%d", SD_CARD_T2[i]);
        sprintf(stT3, "%d", SD_CARD_T3[i]);
        sprintf(stT4, "%d", SD_CARD_T4[i]);
        sprintf(stPd, "%.2f", SD_CARD_Pdiff[i]);
        sprintf(stUT, "%d", SD_CARD_UNIX_TIME[i]);

        int line_len = snprintf(buffer, sizeof(buffer), "%s,%s,%s,%s,%s,%s\r\n",stUT,stT1,stT2,stT3,stT4,stPd);
        if (line_len > 0 && line_len < sizeof(buffer)) {
            UINT bytes_written;
            ff_result = f_write(&file, buffer, line_len, &bytes_written);
            if (ff_result != FR_OK) {
                NRF_LOG_INFO("Write failed for entry %d\r\n.", i);
            } else {
                total_bytes_written += bytes_written;
            }
        } else {
            NRF_LOG_INFO("Buffer overflow or invalid line for entry %d\r\n.", i);
        }

        ID = ID + 1;
    }

    NRF_LOG_INFO("Write new entry %d bytes written.", total_bytes_written);
    (void) f_close(&file);
    Time_stamp_id = ID;
    return;
}

为什么之前会出现间歇性空行?

当栈上的buffer未被完全覆盖时,残留的垃圾数据里恰好包含了\r\n,就会被写入成空行;而后续循环中如果生成的CSV行内容较长,把buffer的剩余空间也覆盖了,垃圾数据被清空,空行就不再出现——这就是你看到"运行一段时间后恢复正常"的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:32:58