使用Cubemx 创建SD的文件系统工程

  • Post author:
  • Post category:其他




使用Cubemx 创建SD的文件系统工程



软件工具

1、 STM32CubeMX 6.2.1

2、 Keil MDK5.35

3、 CubeMX 引用固件库版本 STM32Cube_FW_F1_V1.8.4



创建 CubeMX 工程



SDIO 配置

SDIO 配置,如果通信出现 IO 层的错误,可以尝试增大分频系数来减小时钟

在这里插入图片描述



FATFS配置

选择 SD 卡

1、 长文件夹名存储位置 我们设置在栈空间 STACK(在生成工程是需要调整栈空间大小)

2、 文件夹名的长度

3、 FS_RPATH 该参数与部分函数使能有关 详细查看 ffconf.h 文件中的注释

在这里插入图片描述



创建工程

在这里插入图片描述

在这里插入图片描述




引用 Middlewares 的 FatFs 分析



Fatfs 概述

在 CUbeMX 中引用的文件系统版本为 0.11

官方 0.11 版本中的内容

文件名 文件内容 修改需求
00readme.txt 当前文件
history.txt 修订历史
ffconf.h FatFs 模块的配置文件
ff.h FatFs 和应用程序模块的通用包含文件
ff.c FatFs 模块
diskio.h FatFs 和磁盘 I/O 模块的通用包含文件
diskio.c 将现有磁盘 I/O 模块附加到 FatFs 的粘合函数示例
integer.h FatFs 的整数类型定义
option 可选的外部函数 支持简体中文的cc963.c文件

在 CubeMX 的引用中多的文件

文件名 文件内容 修改需求
ff_gen_drv



关键结构体与枚举数据



文件系统对象结构体(FATFS)

typedef struct {
  union{
	UINT	d32[_MAX_SS/4];     /* 强制32位对齐 */     
	BYTE	d8[_MAX_SS];    	/*磁盘访问窗口的目录,FAT(和文件数据在微型cfg) */ 
  }win;
	BYTE	fs_type;		/* FAT子类型(0:不安装) */
	BYTE	drv;			/* 物理驱动器号 */
	BYTE	csize;			/* 每个集群(1,2,4,…128) */
	BYTE	n_fats;			/* FAT拷贝数(1或2) */
	BYTE	wflag;			/* win[] flag (b0:dirty) */
	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
	WORD	id;				/* 文件系统挂载ID */
	WORD	n_rootdir;		/* 根目录条目数(FAT12/16) */
#if _MAX_SS != _MIN_SS
	WORD	ssize;			/* 每个扇区的字节数 (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
	_SYNC_t	sobj;			/* 同步对象的标识符 */
#endif
#if !_FS_READONLY
	DWORD	last_clust;		/* 最后分配的集群 */
	DWORD	free_clust;		/* 空闲集群数 */
#endif
#if _FS_RPATH
	DWORD	cdir;			/* 当前目录启动集群(0:root) */
#endif
	DWORD	n_fatent;		/* FAT条目数,=集群数+ 2 */
	DWORD	fsize;			/* 每个FAT的扇区 */
	DWORD	volbase;		/* 卷开始扇区 */
	DWORD	fatbase;		/* FAT启动扇区 */
	DWORD	dirbase;		/* 根目录启动扇区 (FAT32:Cluster#) */
	DWORD	database;		/* 数据开始扇区 */
	DWORD	winsect;		/* 当前扇区出现在 win[] */
	
} FATFS;



文件对象结构体(FIL)

typedef struct {
#if !_FS_TINY
  union{  
	UINT	d32[_MAX_SS/4]; /* 强制32位对齐 */     
	BYTE	d8[_MAX_SS];    /* 文件数据读/写缓冲区 */
  }buf;
#endif
	FATFS*	fs;				/* 指向相关文件系统对象的指针(**不要更改顺序**) */
	WORD	id;				/* 所有者文件系统的挂载ID(**不改变顺序**) */
	BYTE	flag;			/* 状态标志 */
	BYTE	err;			/* /*中止标志(错误代码) */
	DWORD	fptr;			/* 文件读/写指针(在文件打开时置零) */
	DWORD	fsize;			/* 文件大小 */
	DWORD	sclust;			/* 文件启动集群(0:没有集群链,当fsize为0时总是0) */
	DWORD	clust;			/* 当前的fpter集群(当fprt为0时无效) */
	DWORD	dsect;			/* buf[]中出现扇区号(0:无效) */
#if !_FS_READONLY
	DWORD	dir_sect;		/* 包含目录条目的扇区号 */
	BYTE*	dir_ptr;		/* 指向win[] 中的目录项 */
#endif
#if _USE_FASTSEEK
	DWORD*	cltbl;			/*指向集群链接映射表的指针(在文件打开时为空)*/
#endif
#if _FS_LOCK
	UINT	lockid;			/*文件锁ID来源于1(文件信号表的索引Files[]) */
#endif

} FIL;



目录对象结构体(DIR)

typedef struct {
#if !_FS_TINY
  union{  
            UINT     d32[_MAX_SS/4];      /*强制32位对齐*/
            BYTE   d8[_MAX_SS];           /*文件数据读/写缓冲区*/
  }buf;
#endif   
	FATFS*	fs;				/*指向文件系统对象所有者的指针(**不改变顺序**)*/
	WORD	id;				/*所有者文件系统的挂载ID(**不改变顺序**)*/
	WORD	index;			/*当前读写索引号*/
	DWORD	sclust;			/*表启动集群(0:根目录)*/
	DWORD	clust;			/*当前集群*/
	DWORD	sect;			/*当前扇区*/
	BYTE*	dir;			/*指向win的当前SFN表项[]*/
	BYTE*	fn;				/*指向SFN的指针(in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCK
	UINT	lockid;			/*文件锁ID(文件信号表的索引Files[]) */
#endif
#if _USE_LFN
	WCHAR*	lfn;			/*指向LFN工作缓冲区的指针*/
	WORD	lfn_idx;		/*最后匹配的LFN索引号(0xFFFF:没有LFN) */
#endif
#if _USE_FIND
	const TCHAR*	pat;	/*指向匹配模式的名称*/
#endif
} DIR;

文件信息结构体(FILINFO)

typedef struct {
	DWORD	fsize;			/* 文件大小 */
	WORD	fdate;			/* 最后修改日期 */
	WORD	ftime;			/* 最后修改时间 */
	BYTE	fattrib;		/* 属性 */
	TCHAR	fname[13];		/*短文件名(8.3格式)*/
#if _USE_LFN
	TCHAR*	lfname;			/*指向LFN缓冲区的指针*/
	UINT 	lfsize;			/* LFN缓冲区的大小在TCHAR */
#endif
} FILINFO;



文件函数返回码(FRESULT)

typedef enum {
	FR_OK = 0,				        /* (0) 成功 */
	FR_DISK_ERR,			        /* (1) 低级磁盘I/O层发生硬错误 */
	FR_INT_ERR,				        /* (2) 断言失败 */
	FR_NOT_READY,			        /* (3) 物理驱动器无法工作 */
	FR_NO_FILE,				        /* (4) 找不到文件 */
	FR_NO_PATH,			        	/* (5) 找不到路径 */
	FR_INVALID_NAME,		        /* (6) 路径名格式无效 */
	FR_DENIED,				        /* (7)  由于禁止访问或目录已满而拒绝访问  */
	FR_EXIST,				        /* (8)  由于禁止访问而拒绝访问*/
	FR_INVALID_OBJECT,		        /* (9) 文件/目录对象无效 */
	FR_WRITE_PROTECTED,	        	/* (10) 物理磁盘被写保护 */
	FR_INVALID_DRIVE,		        /* (11) 逻辑驱动器号无效 */
	FR_NOT_ENABLED,		        	/* (12) 卷无工作区 */
	FR_NO_FILESYSTEM,		        /* (13) 没有有效的FAT卷 */
	FR_MKFS_ABORTED,		        /* (14) f_mkfs()由于任何参数错误而中止 */
	FR_TIMEOUT,				        /* (15) 在指定的时间内无法获得访问卷的授权 */
	FR_LOCKED,				        /* (16) 根据文件共享策略,操作被拒绝 */
	FR_NOT_ENOUGH_CORE,				/* (17) LFN工作缓冲区无法分配 */
	FR_TOO_MANY_OPEN_FILES,			/* (18) 打开的文件数> _FS_SHARE */
	FR_INVALID_PARAMETER	        /* (19) 给出的参数是无效的 */
} FRESULT;



使用注意事项

如果对文件进行了任何更改之后未关闭文件或掉电前未关闭文件,会导致数据写入失败 在电脑上查看不存在写入数据

可以使用 f_write 函数与 f_sync 函数配合将数据刷新到文件对象中

// f_sync函数刷新写入文件的缓存信息。
FRESULT f_sync ( FIL* fp );		/* 输入参数:文件对象 */



版权声明:本文为qq_39567970原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。