使用 STM32 + FATFS (官方中間件) 將 UART 接收資料寫入 SD 卡,電腦讀取卻顯示亂碼。本文系統性分析三大常見成因:f_write 長度參數錯誤、資料編碼 (ASCII/UTF-8/二進位) 不匹配、檔案開啟模式遺漏 FA_READ 導致無法驗證,並提供逐步除錯流程與修正代碼。
f_write 回傳 FR_OK,但電腦用記事本/Notepad++ 開啟 test.txt 顯示亂碼或 NUL 字元。void WriteSDFile(unsigned char *USARTx_RX_BUF) {
disk_initialize(0);
f_mount(0, &fs);
res = f_open(&fsrc, "test.txt", FA_OPEN_ALWAYS | FA_WRITE); // 缺少 FA_READ
if (res == FR_OK) {
f_lseek(&fsrc, fsrc.fsize); // 追加模式
// ❌ 錯誤:傳遞指標位址 &USARTx_RX_BUF,長度用 NUM_SAVE-1 (常數)
res = f_write(&fsrc, &USARTx_RX_BUF, NUM_SAVE-1, &br);
f_close(&fsrc);
}
}
錯誤:&USARTx_RX_BUF 是 unsigned char** (指標的位址),而非資料起始位址。長度 NUM_SAVE-1 為固定常數,不等於實際接收長度。
修正:
// 假設實際接收長度存於全域變數 USARTx_RX_LEN
UINT bytesWritten;
res = f_write(&fsrc, USARTx_RX_BUF, USARTx_RX_LEN, &bytesWritten);
// 或使用 strlen (若確定以 '\0' 結尾且無二進位 0)
res = f_write(&fsrc, USARTx_RX_BUF, strlen((char*)USARTx_RX_BUF), &bytesWritten);
.txt,文字編輯器嘗試以 UTF-8/ANSI 解碼會產生亂碼。test.bin,用十六進位編輯器 (HxD) 檢視。sprintf(buf, "%02X ", data[i])) 或 Base64 編碼後再寫入。// 建議模式:可讀可寫、追加、不存在則建立
res = f_open(&fsrc, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
具備 FA_READ 才能在 MCU 端用 f_read 回讀驗證,排除「寫入成功但資料錯誤」vs「寫入成功、讀取端解碼錯誤」。
FRESULT WriteSDFile(const uint8_t *buf, uint16_t len) {
FRESULT res;
FATFS fs;
FIL fil;
UINT bw;
res = f_mount(&fs, "0:", 1);
if (res != FR_OK) return res;
res = f_open(&fil, "0:/test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
if (res != FR_OK) { f_mount(NULL, "0:", 1); return res; }
res = f_lseek(&fil, f_size(&fil)); // 移至檔案末尾 (追加)
if (res != FR_OK) { f_close(&fil); f_mount(NULL, "0:", 1); return res; }
res = f_write(&fil, buf, len, &bw);
f_close(&fil);
f_mount(NULL, "0:", 1); // 釋放掛載
return res;
}
// 呼叫範例
WriteSDFile(USARTx_RX_BUF, USARTx_RX_LEN);
f_read 並透過 UART 印出十六進位,確認資料位元模式正確。test.txt,查看原始位元組是否與 MCU 端一致。Encoding 切換 UTF-8/ANSI/UCS-2 LE 觀察是否可讀。bw (實際寫入位元組數) 與 len、檔案大小是否一致。| 誤區 | 正確認知 |
|---|---|
f_write(&fil, &buf, ...) | 應為 f_write(&fil, buf, ...),陣列名即起始位址 |
用 sizeof(buf) 當長度 | sizeof 取得指標大小 (4/8),需傳入實際資料長度變數 |
以為 FA_WRITE 含蓋讀取 | FatFs 權限位元獨立,需額外加 FA_READ |
未呼叫 f_mount(NULL, ...) 卸載 | 長時間運行會耗盡檔案系統物件,建議每次用完卸載 |

SD 卡寫入亂碼 90% 源自 f_write 緩衝區指標/長度錯誤、編碼預期不符、缺乏讀回驗證。遵循「正確指標、實際長度、二進位存二進位檔/文字存文字檔、MCU 端先驗證」四原則,配合完整錯誤碼檢查與掛載管理,即可建立可靠的嵌入式檔案記錄功能。