STM32CubeMX教程28 SDIO - 使用FatFs文件系统读写SD卡

本文详细介绍了如何在STM32F407开发板上利用STM32CubeMX配置SDIO接口,配合FatFs库实现SD卡的轮询读写和DMA读写功能,包括配置步骤、代码生成和烧录验证过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、准备材料

2、实验目标

3、FatFs轮询读取SD卡流程

3.0、前提知识

3.1、CubeMX相关配置

3.1.0、工程基本配置

3.1.1、时钟树配置

3.1.2、外设参数配置

3.1.3、外设中断配置

3.2、生成代码

3.2.0、配置Project Manager页面

3.2.1、外设初始化调用流程

3.2.2、外设中断调用流程

3.2.3、添加其他必要代码

4、烧录验证

5、FatFs DMA读写SD卡流程简述

5.1、CubeMX相关配置

5.2、生成代码

5.3、烧录验证

6、常用函数

参考资料


读者可访问 GitHub - lc-guo/STM32CubeMX-Series-Tutorial 获取原始工程代码


1、准备材料

正点原子stm32f407探索者开发板V2.4

STM32CubeMX软件(Version 6.10.0

keil µVision5 IDE(MDK-Arm

ST-LINK/V2驱动

野火DAP仿真器

XCOM V2.6串口助手

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板SDIO使用FatFs中间件读写4线SD卡,并实现以轮询方式读写SD卡或以DMA方式读取SD卡

3、FatFs轮询读取SD卡流程

3.0、前提知识

FatFs文件系统相关知识请读者阅读STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验”3.0、前提知识“、"3.2.1、外设初始化调用流程"和"3.2.3、添加其他必要代码"三个小节内容

SD卡及SDIO接口相关知识请读者阅读STM32CubeMX教程27 SDIO - 读写SD卡实验”3.0、前提知识“小节内容

3.1、CubeMX相关配置

3.1.0、工程基本配置

打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号),选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示

开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示

详细工程建立内容读者可以阅读“STM32CubeMX教程1 工程建立

3.1.1、时钟树配置

按照STM32CubeMX教程27 SDIO - 读写SD卡实验配置,主锁相环参数Q配置为7,48MHz时钟频率配置为48MHz,其余时钟频率均设置为其能达到的最高频率,具体如下图所示

3.1.2、外设参数配置

本实验需要初始化开发板上WK_UP、KEY2、KEY1和KEY0用户按键,具体配置步骤请阅读“STM32CubeMX教程3 GPIO输入 - 按键响应注意两个实验使用的开发板不同,但配置步骤原理相同

本实验需要初始化USART1作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信

本实验对SDIO的初始化配置与上一实验STM32CubeMX教程27 SDIO - 读写SD卡3.1小节一致,无需做任何修改,只需要增加本实验需要的中间件FatFs即可

单击Pinout & Configuration页面左边功能分类栏目最下面的Middleware and SoftwarePacks,单击其中FatFs,在右侧模式设置中选择SD卡,下方的Configuration中参数大多保持默认即可,需要使用到的时候可以再修改

对Set Defines页面的参数不理解的读者,请阅读STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验"3.1.2、外设参数配置"小节,这里只需将 CODE_PAGE 参数配置为简体中文即可,具体配置如下图所示

在Advanced Settings配置页面中,参数 SDIO instance 只可选SDIO,无SPI选项,因为STM32F407的SDIO接口不支持SPI;当SDIO配置了DMA时,如果希望FatFs使用SDIO的DMA,那么可以将参数 Use dma template 配置为Enable;参数 BSP code for SD 不可选,只能为通用模式

在Platform Settings配置页面中,需要配置SD卡的插入检测引脚 Detect SDIO ,如果不配置该参数,则默认认为SD卡插在SD卡槽中,并且在生成工程代码时也会出现警告,这里由于硬件上并不支持插入检测因此并未配置该选项,警告内容如下图所示

3.1.3、外设中断配置

FatFs轮询读取SD卡无需配置任何中断

3.2、生成代码

3.2.0、配置Project Manager页面

单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示

详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节

3.2.1、外设初始化调用流程

SDIO外设初始化调用流程请读者阅读STM32CubeMX教程27 SDIO - 读写SD卡实验对应小节

FatFs文件系统初始化调用流程请阅读STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验对应小节

在之前STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验中笔者提到过,对于Extemal SRAM、SD Card和USB Disk这三种固定类型的存储,则无需用户在App文件夹和Target文件夹中重新实现FatFs的底层IO读写等操作函数,CubeMX生成的工程代码中会自动实现

将本实验生成的工程代码与STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验做对比,可以发现,FatFs在Target目录下多生成了一个名为bsp_driver_xxx.c的文件,如下图所示

该bsp_driver_xxx.c文件就是将对应内存设备底层读写等操作函数进行了封装,同时在sd_diskio.c文件中,本该在移植FatFs时由用户自己手动实现的初始化、状态、读/写和IO控制等函数也被直接调用了bsp_driver_xxx.c里的函数进行了自动实现,无需用户的任何操作,极为方便

这部分实现的原始代码读者可以自行生成工程查看,也可以和STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验中笔者手动实现的几个函数做对比,更加容易发现其中共性

3.2.2、外设中断调用流程

FatFs轮询读取SD卡无配置任何中断

3.2.3、添加其他必要代码

STM32CubeMX工程生成工程代码后,读者应注意手动修改MX_SDIO_SD_Init()函数中SD卡数据总线宽度从默认的4位手动修改为1位,否则SD卡将初始化失败

在生成的工程代码中增加使用FatFs库中API进行文件操作的函数,包括挂载文件系统、显示SD卡信息、读/写TXT文件、获取文件信息、扫描文件列表和删除文件等函数,笔者将其封装在了file_operate.c / file_operate.h文件中,具体的源代码如下所示

file_operate.c文件

STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验中实现的file_operate.c文件一致,除了测试写的函数FatFs_WriteTXTFile()中写入SD卡的内容修改为了“Line1: Hello, FatFs***\n”

file_operate.h文件

STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验中实现的file_operate.h文件一致,除了下面三个宏定义需要修改为本实验的SD卡相关内容,修改内容如下所示

/*定义自己的存储设备*/
/*用户存储设备扇区字节数*/
#define User_Sector 512
/*用户存储设备FatFs对象*/
#define User_FatFs 	SDFatFS
/*用户存储设备卷路径*/
#define User_SDPath SDPath
/*用户存储设备初始化类型*/
#define User_FatType FM_FAT32

向工程中添加.c/.h文件的步骤请阅读“STM32CubeMX教程19 I2C - MPU6050驱动”实验3.2.3小节

在main.c文件中添加 ”file_operate.h“ 头文件,然后在主函数 main() 中添加文件系统挂载函数及按键控制逻辑函数,具体源代码与STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验中实现的一模一样,无需任何修改

4、烧录验证

烧录程序,开发板上电后会尝试在SD卡上挂载文件系统,挂载成功后会输出读取到的SD卡的信息,接下来按照下面几个步骤使用FatFs文件系统对SD卡进行读写等测试

  1. 按下开发板上的WK_UP按键,扫描SD卡根目录下所有文件,并通过串口将文件列表输出
  2. 按下开发板上的KEY2按键,在SD卡根目录创建一个”test.txt“文件,将一个字符串”Line1: Hello, FatFs***“写入该文件中,该字符串大小为24个字节(该字符串中有2个空格,末尾包括一个’\n‘和一个‘\0')
  3. 按下开发板上的KEY1按键,读取SD卡根目录下名为”test.txt“的文件,将其中的内容通过串口输出,然后读取该文件的信息(大小,属性,名称),并通过串口输出
  4. 按下开发板上的KEY0按键,删除SD卡根目录下名为”test.txt“的文件

整个实验过程串口具体的输出情况如下图所示

5、FatFs DMA读写SD卡流程简述

5.1、CubeMX相关配置

参考上一实验STM32CubeMX教程27 SDIO - 读写SD卡的”6.1、CubeMX相关配置“小节对SDIO的DMA进行配置,具体如下图所示

在System Core/NVIC中勾选SDIO全局中断、DMA2 stream3 全局中断和 DMA2 stream6 全局中断,然后选择合适的中断优先级即可,如下图所示

最后只需在FatFs的Configuration页面Advanced Settings选项卡中将参数 Use dma template 修改为Enable即可,具体如下图所示

5.2、生成代码

修改STM32CubeMX工程重新生成工程代码后,读者应注意再次手动修改MX_SDIO_SD_Init()函数中SD卡数据总线宽度从默认的4位手动修改为1位

除了上述修改外,在轮询读取SD卡基础上生成的代码无需做任何改动,可以直接编译后烧录到开发板上,程序应该直接可以运行,不需要额外添加任何代码

启用SDIO的DMA之后,对应生成的bsp_driver_xxx.c文件中所有的以轮询方式读写等操作SD卡的底层驱动函数都将被相应的替换为以DMA的方式对SD卡进行读写等操作的底层驱动函数,如下图所示以sd_diskio.c文件中的读函数为例简单展示区别

5.3、烧录验证

FatFs DMA读写SD卡的实验现象与FatFs 轮询读取SD卡的实验现象一致,只不过底层SDIO读写SD卡的方式由轮询读写修改为了以DMA方式的读写,对上层FatFs应用无任何影响

6、常用函数

请读者阅读STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写实验 ”常用函数“ 小节

参考资料

STM32Cube高效开发教程(高级篇)

<think>嗯,用户想了解如何使用STM32FatFS实现SD读写操作。首先,我需要回忆一下STM32开发中常用的库和工具,比如HAL库和STM32CubeMXSTM32CubeMX是配置外设的好帮手,可以生成初始化代码,节省时间。接下来是SDIO外设,这是STM32连接SD的主要接口,需要正确配置时钟和引脚。然后,FatFS文件系统,它是一个开源的文件系统模块,支持FAT格式,适合嵌入式系统使用。 用户提到了几个引用,比如引用[1]到[4],里面涉及SDIO初始化、FatFs的集成、代码示例等。需要结合这些资料来组织回答。步骤可能包括硬件准备、CubeMX配置、代码编写、文件操作函数的使用以及示例代码。 首先,硬件部分需要STM32开发板、SD模块和正确连接的引脚。CubeMX配置SDIO为4位模式,正确设置时钟分频,避免超过SD的时钟限制。然后生成代码,添加FatFs中间件,可能需要修改部分配置以适应项目需求。 在代码部分,初始化SDFatFs,挂载文件系统。然后使用f_open、f_write、f_read等函数进行文件操作。要注意返回值的检查,处理可能出现的错误。示例代码需要展示如何创建文件、写入数据、读取数据以及关闭文件。 用户可能遇到的问题包括SD初始化失败、挂载文件系统返回错误,这些需要检查硬件连接、SD格式是否正确(FAT32)、时钟配置是否合适。另外,文件路径和名称的处理也很重要,避免使用中文或特殊字符。 还需要考虑性能优化,比如使用DMA传输减少CPU负载,或者通过适当的缓冲区提高读写速度。此外,错误处理机制,比如重试机制或状态反馈,能增强系统的稳定性。 最后,生成相关问题,帮助用户深入理解,比如如何优化读写性能、处理大文件、兼容不同容量SD,以及结合其他模块如以太网的应用。</think>### 使用STM32FatFS实现SD读写的分步指南 #### 一、硬件与开发环境准备 1. **硬件需求**: - STM32F4/F7/H7系列开发板(需支持SDIO接口) - SD模块(建议使用Class 10以上速度等级) - 正确连接SDIO引脚:CLK、CMD、D0-D3(参考芯片手册) 2. **开发环境配置**: - 安装STM32CubeMX(版本≥6.0) - 集成开发环境:Keil MDK/IAR/STM32CubeIDE - 确保FatFs版本为R0.14c(最新兼容版本) #### 二、STM32CubeMX配置步骤 1. **SDIO配置**: ```c /* 选择4位总线宽度模式 */ hsd.Instance = SDIO; hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; hsd.Init.BusWide = SDIO_BUS_WIDE_4B; // 关键配置项[^1] ``` 2. **FatFs中间件设置**: - 启用`USE_FATFS`选项 - 设置代码页为`Simplified Chinese (DBCS)` - 选择长文件名存储方式(建议使用_LFN=1) #### 三、核心代码实现 1. **SD初始化与挂载**: ```c FATFS fs; // 文件系统对象 FRESULT res; void sd_fatfs_init(void) { res = f_mount(&fs, "0:", 1); // 强制挂载 if(res == FR_NO_FILESYSTEM) { // 创建新文件系统 MKFS_PARM opt = {FM_FAT32, 0, 0, 0, 0}; res = f_mkfs("0:", &opt, work, sizeof(work)); if(res == FR_OK) res = f_mount(&fs, "0:", 1); } } ``` 2. **文件写入示例**: ```c void write_file(void) { FIL fil; UINT bw; char buffer[] = "STM32 FatFs测试数据\r\n"; res = f_open(&fil, "0:/test.txt", FA_WRITE | FA_CREATE_ALWAYS); if(res == FR_OK) { f_write(&fil, buffer, sizeof(buffer)-1, &bw); f_close(&fil); } } ``` 3. **数据读取实现**: ```c void read_file(void) { FIL fil; char buffer[128]; UINT br; res = f_open(&fil, "0:/test.txt", FA_READ); if(res == FR_OK) { f_read(&fil, buffer, f_size(&fil), &br); buffer[br] = 0; // 添加字符串终止符 printf("读取内容:%s\n", buffer); f_close(&fil); } } ``` #### 四、典型问题排查 1. **挂载失败(FR_NOT_READY)**: - 检查SDIO时钟频率(建议≤24MHz初始化阶段) - 确认SD格式为FAT32(簇大小建议32KB) - 验证SD检测引脚配置正确 2. **写入速度优化**: ```c /* 启用DMA传输模式 */ hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; hsd.Init.ClockDiv = 2; // 调整时钟分频提升速度[^3] ``` 3. **多文件操作技巧**: ```c /* 使用FIL结构体池管理多个文件 */ #define MAX_FILES 3 FIL file_pool[MAX_FILES]; ``` #### 五、进阶应用场景 1. **数据日志记录**: ```c void log_data(float temperature) { FIL fil; static DWORD wr_ptr = 0; res = f_open(&fil, "0:/log.csv", FA_OPEN_APPEND | FA_WRITE); if(res == FR_OK) { f_printf(&fil, "%lu,%.2f\r\n", HAL_GetTick(), temperature); f_close(&fil); } } ``` 2. **大文件处理**: ```c #define BUFFER_SIZE 4096 // 4KB缓存优化性能 uint8_t file_buffer[BUFFER_SIZE]; void process_large_file(void) { FIL fil; UINT br; res = f_open(&fil, "0:/bigfile.bin", FA_READ); while(res == FR_OK && !f_eof(&fil)) { f_read(&fil, file_buffer, BUFFER_SIZE, &br); // 处理数据块 } f_close(&fil); } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OSnotes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值