单片机“C++开发”实为用C++语法编写裸机或RTOS代码,底层依赖C风格API(如ESP-IDF的esp_vfs_fat_sdmmc_mount、STM32需手动实现FATFS diskio.c),挂载MicroSD卡关键在物理初始化、FATFS驱动接入与路径挂载,而非语言本身。

单片机上没有“C++运行时”这种东西,所谓“C++单片机”实际是指用 C++ 语法写裸机或 RTOS 环境下的代码(比如 ESP-IDF、STM32 HAL + C++ 封装),但底层驱动、文件系统、SPI/SDIO 初始化全部依赖 C 风格 API 和硬件抽象层。挂载 MicroSD 卡的关键不在语言,而在三件事:物理接口初始化、FATFS 驱动接入、VFS 或 FatFs 直接挂载路径。下面分场景说明。
ESP-IDF 项目里用 C++ 类封装 SD 卡操作,但底层必须调 esp_vfs_fat_sdmmc_mount 或 esp_vfs_fat_sdspi_mount
你可以在 C++ 类里封装 fopen/fwrite 调用,但初始化阶段不能绕过 ESP-IDF 的 C 函数:
-
esp_vfs_fat_sdmmc_mount用于 SDIO 模式,要求 GPIO12/GPIO2 等引脚严格按 SDIO 复用功能配置,且必须启用内部 pull-up(GPIO12 默认是 SDIO_DATA2,容易误配成普通 IO) -
esp_vfs_fat_sdspi_mount用于 SPI 模式,mosi_io_num、miso_io_num、sclk_io_num、cs_io_num必须显式指定,不能依赖默认值;例如 ESP32-S3 常用GPIO_NUM_11(MOSI)、GPIO_NUM_13(MISO)、GPIO_NUM_12(SCK)、GPIO_NUM_10(CS) - 挂载后路径如
/sdcard是 VFS 注册的逻辑路径,C++ 里仍要用fopen("/sdcard/log.txt", "w"),不是std::ofstream—— 后者在 ESP-IDF 默认不启用 iostream 支持,且无底层 file descriptor 映射
STM32F103(无 SDIO)只能走 SPI,FATFS 必须手动对接 diskio.c 的 disk_ioctl 和 disk_read
HAL 库不提供 FATFS 自动集成,你得自己实现底层磁盘 I/O 接口:
- SD 卡在 SPI 模式下只用 DAT0(即 MISO)、CMD(即 MOSI)、CLK、CS 四根线,MicroSD 卡座第 2 脚(CD/DAT3)才是 CS,别接到 CMD 脚上
-
Disk_initialize内部要发 CMD0(74 个空闲时钟 + CS 高电平)、CMD8(检查电压)、ACMD41(初始化),任意一步失败都会卡在STA_NOINIT -
disk_read必须处理块对齐:FATFS 默认以 512 字节为单位读写,但 SPI 模式下 SD 卡不支持非对齐访问;传入的sector参数是 LBA 地址,不能直接当字节偏移用 - 别在中断里调
f_write—— FATFS 非重入,多任务下必须加互斥锁(如 FreeRTOS 的xSemaphoreTake)
挂载失败时先看 esp_err_to_name 或 FRESULT 错误码,不是查 C++ 异常
嵌入式环境几乎不用 try/catch,所有错误都通过返回值暴露:
- ESP-IDF 中
esp_vfs_fat_sdspi_mount返回ESP_FAIL时,立刻用esp_err_to_name(ret)打印,常见有ESP_ERR_INVALID_ARG(引脚号超出范围)、ESP_ERR_TIMEOUT(CMD0 无响应,大概率接线或供电问题) - STM32+FATFS 中
f_mount返回FR_NO_FILESYSTEM说明卡没格式化成 FAT32/FAT16,或扇区大小不对;返回FR_NOT_READY通常是Disk_initialize没成功,需检查 SPI 时序(CPOL=0, CPHA=0)和 CS 电平 - 逻辑分析仪比串口打印更管用:抓 SCK+MOSI,看前 8 个 clock 是否全是 0xFF(SD 卡空闲态),再看 CMD0 是否发出 0x40+0x00000000+0x95 —— 这三字节发错一个,卡就拒绝响应
真正难的从来不是“怎么写类”,而是让第一帧 CMD0 被 SD 卡正确采样。供电波动、CS 释放时机、上电复位延迟、SPI 模式切换时序——这些硬件级细节,C++ 封装层看不见,也救不了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











