首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >STM32 SPI驱动SD NAND代码拆解:初始化、挂载、写入、格式化全流程

STM32 SPI驱动SD NAND代码拆解:初始化、挂载、写入、格式化全流程

原创
作者头像
用户11143476
发布2026-08-18 13:56:34
发布2026-08-18 13:56:34
1250
举报
文章被收录于专栏:SD NANDSD NAND

很多工程师第一次用SD NAND,卡住的不是硬件接线,而是软件驱动。SD NAND兼容SD协议,理论上用STM32的SDIO或SPI接口都能驱动,但SPI模式接线简单(四根线搞定),在引脚资源紧张的MCU上更常用。

本文以正点原子精英板(STM32F103)+ 米客方德MKDV4GIL-AS SD NAND为例,拆解SPI模式下从初始化到文件写入的完整代码流程。由于开发板上是TF卡接口,需要用一块TF-SD NAND转接板把LGA封装转成TF卡金手指形态。

SPI模式怎么进去的

SD NAND上电后默认处于SDIO模式。要切换到SPI模式,需要在发送CMD0(复位命令)的同时把CS片选信号拉低。这个动作一旦成功,SD NAND就锁定在SPI模式,后续所有通信都走SPI协议,不会再回到SDIO模式。

从引脚定义看,MKDV4GIL-AS在SD模式下DAT3是数据线,在SPI模式下变成CS片选线;CMD在SD模式下是命令线,SPI模式下变成MOSI(数据输入);DAT0在SD模式下是数据线,SPI模式下变成MISO(数据输出)。同一颗芯片,模式不同,引脚功能完全不同,接线时要对照规格书的引脚分配表来接。

初始化:SD_init + f_mount

代码入口在main函数,先完成HAL库初始化、时钟配置、GPIO/SPI1/FATFS/UART外设初始化,然后调用GetSDCardCapacity()获取容量信息,进入主循环调用WritetoSD()写入数据。

GetSDCardCapacity()函数里,第一步是SDinit()——这是SD NAND的底层初始化,内部完成上电延时、发送CMD0进入SPI模式、CMD8检查电压兼容性、ACMD41激活卡片、CMD58读取OCR寄存器等SD协议规定的初始化序列。SDinit()返回0表示成功,返回1表示失败。

初始化成功后,调用FatFs文件系统的f_mount(&FS, "0:", 1)挂载文件系统。第三个参数"1"表示立即挂载(0则延迟挂载,等到第一次文件操作时才挂载)。挂载成功后,SD NAND在软件层面就变成了一个带文件系统的磁盘,可以用标准的文件API操作。

获取容量:f_getfree

挂载成功后,调用fgetfree("0:", &freclust, &fs)获取空闲簇数量。这个函数返回的fs指针指向FATFS结构体,里面有文件系统的关键参数:n_fatent是总簇数,csize是每簇扇区数。

通过这两个参数可以算出总容量和可用容量:

// c TotalSpace = (uint16_t)(((fs->n_fatent - 2) * fs->csize) / 2 / 1024); AvailableSize = (uint16_t)((fre_clust * fs->csize) / 2 / 1024); UsedSize = TotalSpace - AvailableSize;

除以2是因为每扇区512字节,再除以1024换算成MB。最后通过串口打印出来,方便确认SD NAND的容量是否正常识别。

写入文件:f_open + f_write

WritetoSD()函数展示了完整的文件写入流程。函数开头再次调用SDinit()和fmount()——每次写入前都重新初始化和挂载,这种写法虽然不够高效(实际项目中初始化一次就够了),但在测试阶段能保证每次写入都是干净状态。

关键逻辑在f_mount的返回值判断上:

// c res = f_mount(&fs, "0:", 1); if(res == FR_NO_FILESYSTEM) // 没有文件系统 { res = f_mkfs("", 0, 0); // 格式化 if(res == FR_OK) { f_mount(NULL, "0:", 1); // 先取消挂载 f_mount(&fs, "0:", 1); // 重新挂载 } }

这段代码处理了一个常见场景:全新的SD NAND没有文件系统,fmount会返回FRNOFILESYSTEM。这时候需要先调用fmkfs()创建FAT文件系统,格式化完成后取消挂载再重新挂载,文件系统才能正常使用。

文件写入部分用fopen打开(或创建)文件,flseek把指针移到文件末尾确保追加写入而不覆盖已有数据,fwrite写入数据,fclose关闭文件,最后f_mount(NULL)取消挂载。整个流程跟在PC上操作文件没有本质区别——这就是SD NAND内建控制器和FatFs文件系统配合的好处,工程师不需要关心底层Flash的页编程和块擦除,只需要调文件API。

串口调试信息

代码中大量使用printf打印每一步的状态:初始化成功/失败、挂载结果、容量信息、格式化结果、文件打开/写入结果。这些串口输出在调试阶段非常关键——SD NAND的SPI驱动涉及多个协议层(SPI物理层→SD协议层→FatFs文件系统层),任何一层出问题都会导致操作失败,有了串口打印就能快速定位卡在哪一步。

程序下载后,串口助手能看到完整的初始化流程和容量信息,SD NAND内会生成一个写入测试数据的TXT文件,说明SPI模式驱动正常。

几个实操注意点

接线方面,SPI模式的四根线(CLK、MOSI、MISO、CS)对应STM32的SPI1外设引脚,MOSI接SD NAND的CMD(数据输入),MISO接DAT0(数据输出),CS接DAT3,CLK接CLK。如果用的是转接板,转接板已经帮你接好了,直接插TF卡槽就行。

FatFs配置方面,需要在ffconf.h中开启FFFSREADONLY = 0(允许写入)、FFUSEMKFS = 1(允许格式化)、FFCODEPAGE设置为支持中文的编码页(如果文件名含中文)。diskio.c中需要实现SPI模式下的SD卡读写底层函数(diskread、diskwrite、diskioctl等),这些函数对接STM32的HALSPI_TransmitReceive。

MKDV4GIL-AS在SPI模式下实测写入速度约10MB/s左右,读取速度约21MB/s,对于日志记录、参数存储这类嵌入式应用足够用了。如果对速度有更高要求,可以切到SDIO四线模式,带宽能翻几倍。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • SPI模式怎么进去的
  • 初始化:SD_init + f_mount
  • 获取容量:f_getfree
  • 写入文件:f_open + f_write
  • 串口调试信息
  • 几个实操注意点
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档