c++如何在内存极其有限的单片机上读写SD卡文件_FatFs库移植【附代码】

千雪吖_8088

千雪吖_8088

2026-03-25

675人浏览

原创

FatFs在小内存单片机上卡在f_mount返回FR_NOT_READY,根本原因是默认配置申请缓冲区远超RAM容量;需关闭长文件名、禁用exFAT、改用静态工作区缓冲,并确保FF_MAX_SS=512。

c++如何在内存极其有限的单片机上读写sd卡文件_fatfs库移植【附代码】

为什么 FatFs 在小内存单片机上常卡在 f_mount 返回 FR_NOT_READY

根本原因不是 SD 卡没插好,而是 FatFs 默认配置仍试图分配远超你 MCU RAM 容量的缓冲区。比如 STM32F103C8(20KB RAM)跑默认 FF_FS_EXFAT=0 + FF_USE_LFN=1 时,f_mount 会悄悄申请几百字节栈空间+动态堆缓冲,而你的 heap 可能根本没开,或只开了 2KB —— 这时它连磁盘状态都读不全,直接报 FR_NOT_READY。

实操建议:

  • 关闭长文件名:FF_USE_LFN = 0(否则每个目录项额外吃 256 字节栈+缓存)
  • 禁用 exFAT:FF_FS_EXFAT = 0(FAT32 足够,省掉大块扇区解析逻辑)
  • 把工作区缓冲挪到静态内存:定义全局数组 uint8_t g_work_buffer[FF_MAX_SS];,传给 f_mount 的第三个参数,别用 NULL
  • 确认 FF_MAX_SS 设为 512(SD 卡标准扇区大小),别误设成 4096

SDIO 或 SPI 模式下,f_open 失败返回 FR_DISK_ERR 怎么定位

这个错误本质是底层 disk_read/disk_write 函数出问题,和 FatFs 无关。SPI 模式下最常见的是 CS 电平没拉低、MOSI/MISO 时序错半拍;SDIO 模式则多因时钟分频没配对(比如 APB2=72MHz 时,SDIOCLK 分频后必须 ≥ 400kHz 初始化阶段,但 ≤ 25MHz 数据阶段)。

实操建议:

  • 先写个裸机函数发 0x00 到 SD 卡,用逻辑分析仪看 MOSI 是否真有输出、CS 是否按时拉低
  • SPI 模式务必检查 disk_ioctl 中 CTRL_SYNC 是否真的等待了 SPI 总线空闲(很多移植漏掉这步,导致后续命令乱序)
  • SDIO 模式下,初始化前调用 HAL_SD_InitCard 后,立刻用 HAL_SD_GetCardState 看返回值,不是 HAL_SD_CARD_READY 就别进 FatFs
  • f_open 前加一句 if (f_mount(&FatFs, "", 1) != FR_OK) while(1);,避免挂载失败还硬开文件

f_write 写入速度慢、中途卡死的三个硬件级原因

FatFs 层面的 f_write 慢,90% 是被底层拖住:要么 SPI 时钟太低(比如 100kHz),要么 SD 卡内部忙没检测(disk_ioctl 没实现 CTRL_POWER 或 CTRL_STATUS),要么扇区写未对齐(向非 512 字节边界地址写,触发 FatFs 隐式读-改-写流程,小内存设备直接爆栈)。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

实操建议:

  • SPI 时钟至少设到 4MHz(STM32 HAL 库里 hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;)
  • disk_ioctl 必须响应 CTRL_STATUS:返回 STA_NOINIT / STA_NODISK / STA_PROTECT,否则 FatFs 以为卡一直就绪,狂发命令
  • 所有 f_write 的 buff 地址和 size 必须是 512 字节对齐——用 __align(512) uint8_t tx_buf[512]; 声明缓冲区,别用 malloc
  • 别在中断里调用 f_write,SD 卡操作全程阻塞,中断里调用等于锁死整个系统

如何让 f_printf 在无 stdio 的环境下工作

默认 f_printf 依赖 libc 的 vprintf,而小内存单片机往往禁用 newlib-nano 或没链接 printf 相关.o。强行开启会导致代码体积暴涨、RAM 不够。

实操建议:

  • 关闭 FF_USE_STRFUNC(设为 0),彻底不用 f_printf,改用 f_write + 手动 itoa 拼接字符串
  • 若真需要格式化,自己实现极简版:void my_fprintf(FIL* fp, const char* fmt, ...),只支持 %d 和 %s,用 vsprintf 重定向到 64 字节栈缓冲,再 f_write 出去
  • 注意:FatFs 的 f_puts 是安全的,它只是封装了 f_write,可放心用

最麻烦的从来不是 FatFs 本身,而是你忘了 SD 卡上电后要等至少 1ms 才能发 CMD0,或者 SPI 的 CPOL/CPHA 配成了 0/1 而 SD 卡只认 0/0 —— 这些细节不会报错,只会让你对着 FR_TIMEOUT 发呆一整天。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.25

354

5

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

2023.06.20

848

5

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.28

1029

10

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2318

7

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1818

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2884

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6204

49

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习