STM32利用FATFS文件系统给SD卡读写数据

STM32利用FATFS文件系统给SD卡读写数据

注:FATFS文件系统官方网址(内含各种函数具体功能及参数配置):
FATFS文件系统官方网址

1. 所需.c和.h文件

FATFS中的文件的作用如下:

ffconf.h FatFs模块的配置文件
ff.h FatFs的头文件,定义了几个关键的数据结构,并声明了很多函数
ff.c FatFs模块的实现,包括f_open()、f_read()、f_write()和f_close()等函数的实现
diskio.h 底层磁盘I/O模块的头文件
diskio.c 这个文件实现了一个操作底层存储设备的接口层,ff.c会调用这个文件中提供的接口,实现文件的读写,我们在移植过程中的重点工作就是实现这个文件中的几个接口
integer.h 数据类型的定义

2. 操作步骤

准备工作:
1:给SD卡注册工作区
FATFS fs; //SD 卡逻辑驱动器的工作区
f_mount(&fs,“0:”,1); //为SD卡逻辑驱动器注册工作区
2:创建文件夹
f_mkdir(“0:\\shiyan”);//创建 (shiyan) 文件夹

2.1 写入数据

第一步:创建文件
FIL File;
f_open(&File, “0:\\Shiyan\\tianqi.dat”, FA_OPEN_ALWAYS | FA_WRITE);//在文件夹 (shiayn) 下创建 (tianqi.dat) 文件
第二步:索引文件内部数据存储位置指针
f_lseek(&File, 0+i);//i为第i个数据存储位置,将数据指针指向数据要存储的位置//并提前扩展好需要的文件空间
第三步:写入数据
f_write(&File,data+i,1 , &bw);//写入数据
第四步:关闭文件
f_close(&File);

例:连续写入6个数据

void write_data(uint8_t *data)
{
	FIL File;
	UINT bw;
	int ret;
	char i;
	ret = f_open(&File, "0:\\Shiyan\\tianqi.dat", FA_OPEN_ALWAYS | FA_WRITE);    
	for(i=0;i<6;i++)
	{
		ret |= f_lseek(&File, 0+i);
		ret |= f_write(&File,data+i,1 , &bw);
	}
	ret |= f_close(&File);
}

或者

void write_data(uint8_t *data)
{
	FIL File;
	UINT bw;
	int ret;
	ret = f_open(&File, "0:\\Shiyan\\tianqi.dat", FA_OPEN_ALWAYS | FA_WRITE);
	ret |= f_lseek(&File, 6);//先扩展出6个字节的存储区
	ret |= f_lseek(&File, 0);//将数据指针移到文件起始位置
	ret |= f_write(&File,data,6 , &bw);//自动移动数据指针
	ret |= f_close(&File);
}

2.2 读出数据

第一步:打开文件
FIL File;
f_open(&File, “0:\Shiyan\tianqi.dat”, FA_OPEN_ALWAYS | FA_READ);//在文件夹 (shiayn) 下打开 (tianqi.dat) 文件
第二步:索引文件内部数据存储位置指针
f_lseek(&File, 0+i);//i为第i个数据存储位置,将数据指针指向数据要读取的位置
第三步:读取数据
f_read(&File,data+i,1 , &bw); //读出数据
第四步:关闭文件
f_close(&File);

例:连续读出6个数据

void read_data(uint8_t *data)
{
	FIL File;
	UINT bw;
	int ret;
	char i;
	ret = f_open(&File, "0:\\Shiyan\\tianqi.dat", FA_OPEN_ALWAYS | FA_READ);
	for(i=0;i<6;i++)
	{
		ret |= f_lseek(&File, 0+i);
		ret |= f_read(&File,data+i,1 , &bw); 
	}
	ret |= f_close(&File); 
}

或者

void read_data(uint8_t *data)
{
	FIL File;
	UINT bw;
	int ret;
	ret = f_open(&File, "0:\\Shiyan\\tianqi.dat", FA_OPEN_ALWAYS | FA_READ);
	ret |= f_lseek(&File, 0);
	ret |= f_read(&File,data,6 , &bw); //自动移动数据指针
	ret |= f_close(&File); 
}

写读数据

对SD卡进行数据写读

uint8_t data_wr[6]={1,2,3,4,5,6},data_re[6];
f_mount(&fs,"0:",1);     //为SD卡逻辑驱动器注册工作区
f_mkdir("0:\\shiyan");//创建 (shiyan) 文件夹
write_data(data_wr);//将数组data[6]中的数写入到shiyan文件夹下的tianqi.dat
read_data(data_re);//从shiyan文件夹下的tianqi.dat 读出刚才存入到SD卡的数据到data1[6]

3. 参考函数功能:

FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);				/* Open or create a file */
//打开或创建一个文件
FRESULT f_close (FIL* fp);											/* Close an open file object */
//关闭文件
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);			/* Read data from a file */
//从文件里面读取数据
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);	/* Write data to a file */
//向文件里面写入数据
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);	/* Forward data to the stream */
FRESULT f_lseek (FIL* fp, DWORD ofs);								/* Move file pointer of a file object */
//移动文件内部数据指针到指定位置,或者扩展存储区
FRESULT f_truncate (FIL* fp);										/* Truncate file */
FRESULT f_sync (FIL* fp);											/* Flush cached data of a writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path);						/* Open a directory */
FRESULT f_closedir (DIR* dp);										/* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno);							/* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);	/* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno);							/* Find next file */
FRESULT f_mkdir (const TCHAR* path);								/* Create a sub directory */
//创建一个子文件夹
FRESULT f_unlink (const TCHAR* path);								/* Delete an existing file or directory */
//删除存在的文件或文件夹
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);	/* Rename/Move a file or directory */
//重命名或移动文件(文件夹)
FRESULT f_stat (const TCHAR* path, FILINFO* fno);					/* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);			/* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno);			/* Change times-tamp of the file/dir */
FRESULT f_chdir (const TCHAR* path);								/* Change current directory */
FRESULT f_chdrive (const TCHAR* path);								/* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len);							/* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);	/* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);	/* Get volume label */
FRESULT f_setlabel (const TCHAR* label);							/* Set volume label */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);			/* Mount/Unmount a logical drive */
//创建逻辑工作区
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au);				/* Create a file system on the volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work);			/* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp);										/* Put a character to the file */
//写入一个字符型数据
int f_puts (const TCHAR* str, FIL* cp);								/* Put a string to the file */
//写入字符串
int f_printf (FIL* fp, const TCHAR* str, ...);						/* Put a formatted string to the file */
//写入标准化字符串
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the file */
//从文件中获取字符串

参考资料

博客参考了以下博文和网站:
链接: https://blog.csdn.net/wangzhiqin365/article/details/107520906.
链接: http://elm-chan.org/fsw/ff/00index_e.html.

<think>嗯,用户想了解如何使用STM32FatFS实现SD读写操作。首先,我需要回忆一下STM32开发中常用的库和工具,比如HAL库和STM32CubeMX。STM32CubeMX是配置外设的好帮手,可以生成初始化代码,节省时间。接下来是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); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值