【ESP32笔记】SDIO读写TF卡
本节目标分清 SDIO 与 SPI 两种接法学会用 FATFS 挂载 TF 卡并用标准 C 文件 API 完成读写一、本节要解决的问题ESP32 自带几 MB Flash装完程序后剩下的空间有限而且数据不方便拿到电脑上。遇到记录日志、存图片、放音频等需求时最方便的方案就是插一张MicroSD/TF 卡。要让 ESP32 用上 TF 卡需要三层东西配合物理接口用 SDIO 还是 SPI 方式与卡通信文件系统卡上存的是 FAT 文件系统需要FATFS组件来解析统一接口ESP-IDF 通过VFS虚拟文件系统把 FATFS 挂到某个路径下之后就能用标准 C 的fopen/fread/fwrite操作卡上文件不必自己写扇区读写。二、硬件基础2.1 从 MMC 到 SD 卡MMCMulti-Media Card1997 年由西门子和 SanDisk 推出7 针引脚、体积小支持 1bit 模式SD 卡在 MMC 基础上发展而来向下兼容MMC 今天基本退出消费市场衍生出的eMMCBGA 封装、焊接在板上在嵌入式领域很常见SDIOSecure Digital Input and Output安全数字输入输出在 SD 卡接口基础上增加了低速 I/O 标准既能读卡也能连接蓝牙、WiFi、GPS 等 SDIO 外设。2.2 SDIO 与 SPI 两种接法MicroSD 卡同时支持 SPI 和 SDIO 两种通信模式本板/本工程用的是SDIO 4bit 模式对比项SDIO 模式SPI 模式信号线CLK、CMD、D0~D3 共 6 根CS、CLK、MOSI、MISO 共 4 根数据宽度1bit 或 4bit 并行固定 1bit速度快本工程 4bit、默认 20MHz相对慢受 SPI 时钟限制引脚使用 SDMMC 外设专用引脚性能最好任意 GPIO布线灵活挂载 APIesp_vfs_fat_sdmmc_mount()esp_vfs_fat_sdspi_mount()特殊限制D2/D0 等引脚与 ESP32 启动配置有关见 2.4无此类限制注意教程只实现了 SDIO 方式。如果以后引脚不够或布线不方便改成 SPI 方式时要把挂载函数换成esp_vfs_fat_sdspi_mount()其余文件操作代码不用改——VFS 已经把底层差异屏蔽掉了。2.3 ESP32 的 SDMMC 外设与卡槽ESP32 的 SDMMC 主机外设有两个卡槽每个卡槽都可以单独使用信号卡槽 0卡槽 1CMDGPIO11GPIO15CLKGPIO6GPIO14D0GPIO7GPIO2D1GPIO8GPIO4D2GPIO9GPIO12D3GPIO10GPIO13D4~D7GPIO16 / GPIO17 / GPIO5 / GPIO18无卡槽 0 的引脚GPIO6~GPIO11与 ESP32 模组内部 Flash 的引脚冲突所以实际只能用卡槽 1SDMMC_HOST_DEFAULT()的默认配置就是卡槽 1。注意MicroSD 卡的 CD 插入检测与 D3 引脚公用没有独立的 WP 写保护引脚所以检测卡是否插入要另想办法如定期尝试挂载。2.4 上拉与两个坑引脚SD 协议要求 CMD、D0~D3 接上拉电阻10K~90K。ESP32 内部带可编程上拉代码里用一个标志打开slot_config.flags|SDMMC_SLOT_FLAG_INTERNAL_PULLUP;教程作者踩过的两个坑板级设计要牢记D2 GPIO12如果外部接 10K 上拉ESP32 上电时会误判 Flash 供电为 1.8VGPIO12 是启动配置脚程序直接起不来官方解决办法是烧 eFuse 强制 3.3V本板选择不焊这个上拉D0 GPIO2如果外部接 10K 上拉会影响启动模式导致无法烧录程序。因此板子把 D0、D2 的外部上拉 NC 掉、改用内部上拉作者实测工作正常。注意这是作者实践结论官方注释也写明内部上拉不够、“仅用于调试/示例”。正式产品设计时上拉方案要结合自己的原理图和启动配置引脚一起评估不要直接照抄。三、知识点3.1 FATFS VFS挂载点挂载成功后卡上文件出现在 VFS 的某个目录下本工程是/sdcard后面所有路径都要带这个前缀例如/sdcard/hello.txt。挂载需要准备三样东西sdmmc_host_t用哪个主机外设、哪个卡槽、频率SDMMC_HOST_DEFAULT()默认卡槽 1、20MHzsdmmc_slot_config_t管脚配置与总线宽度SDMMC_SLOT_CONFIG_DEFAULT()默认 1bit本工程改成 4bitesp_vfs_fat_sdmmc_mount_config_t文件系统层面的参数。3.2 挂载参数的取舍esp_vfs_fat_sdmmc_mount_config_tmount_config{.format_if_mount_failedtrue,//挂载失败是否执行格式化.max_files5,//最大可打开文件数.allocation_unit_size16*1024//执行格式化时的分配单元大小分配单元越大读写越快};format_if_mount_failed true挂载失败就格式化。实验阶段方便空卡、格式不对都能自动处理但会把卡上原有数据清掉max_files 5最多同时打开 5 个文件每个打开的文件都占描述符和内存够用即可allocation_unit_size 16 * 1024格式化时的分配单元簇大小越大顺序读写越快小文件多时越浪费空间。四、代码分析4.1 工程结构sdcard/ ├── CMakeLists.txt ├── main/ │ ├── CMakeLists.txt # SRCS main.c │ └── main.c # 挂载 写/读/重命名 卸载 └── sdkconfig # 目标芯片 esp324.2 挂载准备 host / slot / mount_configsdmmc_card_t*card;constcharmount_point[]MOUNT_POINT;ESP_LOGI(TAG,Initializing SD card);ESP_LOGI(TAG,Using SDMMC peripheral);//默认配置速度20MHz,使用卡槽1sdmmc_host_thostSDMMC_HOST_DEFAULT();//默认的IO管脚配置sdmmc_slot_config_tslot_configSDMMC_SLOT_CONFIG_DEFAULT();//4位数据slot_config.width4;//不适用通过IO矩阵进行映射的管脚只使用默认支持的SDMMC管脚可以获得最大性能#if0slot_config.clkCONFIG_EXAMPLE_PIN_CLK;slot_config.cmdCONFIG_EXAMPLE_PIN_CMD;slot_config.d0CONFIG_EXAMPLE_PIN_D0;slot_config.d1CONFIG_EXAMPLE_PIN_D1;slot_config.d2CONFIG_EXAMPLE_PIN_D2;slot_config.d3CONFIG_EXAMPLE_PIN_D3;#endif// Enable internal pullups on enabled pins. The internal pullups// are insufficient however, please make sure 10k external pullups are// connected on the bus. This is for debug / example purpose only.//管脚启用内部上拉slot_config.flags|SDMMC_SLOT_FLAG_INTERNAL_PULLUP;被#if 0 ... #endif关住的是一段自定义 SDIO 引脚的示例CONFIG_EXAMPLE_PIN_*宏未定义所以保持关闭不经过 GPIO 交换矩阵、直接用 SDMMC 专用引脚才能获得最大性能slot_config.width 4表示启用 4bit 数据线这是 SDIO 比 SPI 快的主要来源挂载代码与错误处理ESP_LOGI(TAG,Mounting filesystem);retesp_vfs_fat_sdmmc_mount(mount_point,host,slot_config,mount_config,card);if(ret!ESP_OK){if(retESP_FAIL){ESP_LOGE(TAG,Failed to mount filesystem. );}else{ESP_LOGE(TAG,Failed to initialize the card (%s). Make sure SD card lines have pull-up resistors in place.,esp_err_to_name(ret));}return;}ESP_LOGI(TAG,Filesystem mounted);// Card has been initialized, print its propertiessdmmc_card_print_info(stdout,card);ESP_FAIL一般表示卡能通信但文件系统有问题其他错误码多是接线、上拉或卡本身的问题。4.3 读写文件标准 C API写文件和读文件各封装成一个函数用的全是标准 C 库接口staticesp_err_ts_example_write_file(constchar*path,char*data){ESP_LOGI(TAG,Opening file %s,path);FILE*ffopen(path,w);if(fNULL){ESP_LOGE(TAG,Failed to open file for writing);returnESP_FAIL;}fprintf(f,data);fclose(f);ESP_LOGI(TAG,File written);returnESP_OK;}staticesp_err_ts_example_read_file(constchar*path){ESP_LOGI(TAG,Reading file %s,path);FILE*ffopen(path,r);if(fNULL){ESP_LOGE(TAG,Failed to open file for reading);returnESP_FAIL;}charline[EXAMPLE_MAX_CHAR_SIZE];fgets(line,sizeof(line),f);fclose(f);// strip newlinechar*posstrchr(line,\n);if(pos){*pos\0;}ESP_LOGI(TAG,Read from file: %s,line);returnESP_OK;}写fopen(path, w)→fprintf→fclosefclose之后数据才可靠落盘读fopen(path, r)→fgets读一行 →fclose再把行尾的\n去掉后打印。主流程依次演示了 写、重命名、读、再写、再读、卸载constchar*file_helloMOUNT_POINT/hello.txt;chardata[EXAMPLE_MAX_CHAR_SIZE];snprintf(data,EXAMPLE_MAX_CHAR_SIZE,%s %s!\n,Hello,card-cid.name);rets_example_write_file(file_hello,data);constchar*file_fooMOUNT_POINT/foo.txt;// Check if destination file exists before renamingstructstatst;if(stat(file_foo,st)0){// Delete it if it existsunlink(file_foo);}// Rename original fileif(rename(file_hello,file_foo)!0){ESP_LOGE(TAG,Rename failed);return;}rets_example_read_file(file_foo);先写/sdcard/hello.txt内容是Hello 卡的 CID 名字!重命名前先用stat判断目标文件是否存在存在就unlink删掉再rename成/sdcard/foo.txt读回并打印再用同样方式写/sdcard/nihao.txt内容Nihao 卡名!并读回。注意教程与仓库代码的差异教程代码清单里没有给出s_example_write_file()/s_example_read_file()的实现只调用了它们仓库里两个函数完整存在见本节代码。另外仓库还多了一段被#if 0关掉的格式化示例esp_vfs_fat_sdcard_format()教程未提及。学习和引用时以仓库代码为准。4.4 卸载// All done, unmount partition and disable SDMMC peripheralesp_vfs_fat_sdcard_unmount(mount_point,card);ESP_LOGI(TAG,Card unmounted);卸载会把文件系统刷盘并释放 SDMMC 外设卸载后card句柄失效再访问/sdcard/...会失败。五、关键 API 速查API作用SDMMC_HOST_DEFAULT()生成默认 host 配置卡槽 1、20MHzSDMMC_SLOT_CONFIG_DEFAULT()生成默认管脚配置默认 1bitesp_vfs_fat_sdmmc_mount()初始化 SDMMC 并把 FATFS 挂到挂载点返回卡对象sdmmc_card_print_info()打印卡信息名称、容量、速度等esp_vfs_fat_sdcard_unmount()卸载文件系统并释放外设esp_vfs_fat_sdcard_format()格式化卡仓库中被#if 0关掉未启用fopen()/fprintf()/fgets()/fclose()标准 C 文件读写VFS 转发给 FATFSstat()/unlink()/rename()判断文件是否存在、删除、重命名六、编译与现象验证cdesp32-board/sdcard# 工程当前配置的目标就是 esp32idf.py build idf.py-pCOM端口flash monitor依次打印Initializing SD card、Using SDMMC peripheral、Mounting filesystem、Filesystem mounted然后是一段卡信息sdmmc_card_print_info的输出接着Opening file /sdcard/hello.txt、File written、Renaming file /sdcard/hello.txt to /sdcard/foo.txt、Read from file: Hello 卡名!再Opening file /sdcard/nihao.txt、Read from file: Nihao 卡名!最后Card unmounted。把卡插到电脑上能看到foo.txt和nihao.txt两个文件。

相关新闻

实测 5 款 2026 人才测评工具,横评踩坑后锁定靠谱平台

实测 5 款 2026 人才测评工具,横评踩坑后锁定靠谱平台

一、为什么你买的测评工具总是“用不上”“招进来的人聊得挺好,干了三个月发现不合适。”这句话在HR圈子里出现的频率太高了。问题不在人,在选人时缺了一条数据链路。据市场研究机构统计,2026年全球人才评估服务市场规模预计达到99.2亿美元&a…

2026/10/14 19:44:52 阅读更多 →
Linux驱动学习(1)

Linux驱动学习(1)

Linux 驱动学习:基于 Platform 架构编写驱动之前编写 LED 字符设备驱动时,需要自己申请设备号、创建设备节点,并且将寄存器地址直接写在驱动代码中。这种方式虽然可以实现功能,但是不方便管理和移植。为了让驱动结构更加清晰&…

2026/10/14 19:44:52 阅读更多 →
人才测评结果能否作晋升加薪依据,2026实操深度解读

人才测评结果能否作晋升加薪依据,2026实操深度解读

一、先说结论:测评可以“参考”,但不能“单飞”智联招聘2026年报告显示,影响人才晋升与调岗结果的因素中,综合素质占54%,工作业绩占53%,资历与经验占53%,而领导认可仅占7%。测评数据在“综合素质…

2026/10/14 19:44:52 阅读更多 →

最新新闻

权威测评!2026年最火AI论文工具榜单,免费款也能高效产初稿

权威测评!2026年最火AI论文工具榜单,免费款也能高效产初稿

一、实测方法论:5 大维度量化评估 本次实测覆盖全学科论文场景,重点考察以下维度,结果客观可复现: 表格 评估维度权重测评标准中文适配度25%是否符合 GB/T7714 引用规范,语言逻辑自然度,术语准确性免费功能…

2026/10/14 20:21:39 阅读更多 →
Linux嵌入式SD/MMC驱动调试:信号流向、三层架构与实战排错

Linux嵌入式SD/MMC驱动调试:信号流向、三层架构与实战排错

1. 项目概述:为什么一个SD/MMC驱动分析值得花时间深挖?在嵌入式Linux开发一线干了十多年,我经手过的板子从ARM9、ARM11到Cortex-A7/A53/A72,再到如今的RISC-V SoC,几乎每一块主控芯片的BSP包里,SD/MMC子系统…

2026/10/14 20:21:39 阅读更多 →
最小二乘法全攻略:从线性回归原理到代码实现与避坑实践

最小二乘法全攻略:从线性回归原理到代码实现与避坑实践

我第一次真正用上最小二乘法,是在处理一组传感器校准实验数据的时候。当时手里是一堆带噪声的采样点,教科书里的公式能帮我“找一条最合理的直线”,但工程上真正让人头疼的,其实是后面这些事:数据里混了离群点怎么办&a…

2026/10/14 20:21:39 阅读更多 →
大模型应用落地指南:从模型选型到Agent与RAG实践

大模型应用落地指南:从模型选型到Agent与RAG实践

1. 模型维度:基座能力的格局与选型逻辑距离大模型真正进入大众视野到现在,已经过了好几个年头。站在2026年10月这个时间窗口往回看,最明显的变化是:市面上能叫得出名字的大模型,已经从早期的"百家争鸣"收敛成…

2026/10/14 20:21:39 阅读更多 →
Linux MMC驱动深度解析:SD卡识别流程与SDIO协议栈实战

Linux MMC驱动深度解析:SD卡识别流程与SDIO协议栈实战

1. 项目概述:这不是教科书里的驱动理论,而是现场拆解一张SD卡如何被Linux真正“认出来” 你有没有遇到过这样的情况:插上一张SD卡,系统日志里刷出一串 mmc0: new high speed SDHC card at address 0001 ,但紧接着 d…

2026/10/14 20:21:39 阅读更多 →
从Zernike波前到PSF/MTF:光学像质仿真完整指南

从Zernike波前到PSF/MTF:光学像质仿真完整指南

做光学系统设计的人应该都有过这种体验:镜头草图画完、光线追迹也跑通了,但别人问"那成像到底清不清楚、能分辨多小的细节",你一时却拿不出一个直观的答复。光线追迹给的是光路,不是像质。真正用来回答"成像多锐利…

2026/10/14 20:20:38 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →