1、STM32 之 FATFS 文件系统(SPI 方式)笔记BY:T7Date:20171202At:YSU_B307开发环境:uVision : V5.12.0.0 STM32F103V8T6库版本 : STM32F10x_StdPeriph_Lib_V3.5.0FATSF : ff13a 工程版本:FATFS_V1 日期:20171130硬件连接:SPI1_CS - PA4 SPI1_CLK - PA5 SPI1_MISO - PA6 SPI1_MOSI - PA7工程功能:建立在 SPI_SD 的基础上,完成文件系统的初步接触。1、FATFS 文件系统1.使用开源的 FAT 文件系统模块,其
2、源代码的获取从官网:目前最新版本是:ff13a2. 解压后得到两个文件:其中,documents 相当于 STM32 的固件库使用手册,介绍 FATFS 系统的函数使用方法,source 中则是需要用到的源代码。因为 FATFS 使用 SD 卡,所以 FATFS 的基础是 SD 卡的正常读写,这里采用 SPI 模式。2、STM32 之 SD 卡_SPI 模式1. 硬件连接:SPI1_CS - PA4 SPI1_CLK - PA5 SPI1_MISO - PA6 SPI1_MOSI - PA72. SPI 模式下 STM32 读写 SD 卡的工程结构在确定 STM32 使用 SPI 模式读写 S
3、D 卡没有问题后,进入 FATSF 文件系统的实验,另源代码在文档最后。3、FATSF 文件系统移植1. 配置工程环境1) STM32 读写 SD 卡-SPI 模式成功2) 将解压后的 ff13a 整个文件夹赋值到工程目录下,如图:3) 返回到 MDK 界面下,添加 ff13a 项目组,并把 ff13asource目录下ff.c,diskio.c ,ffunicode.c ,ffsystem.c 添加到项目组中,如下图:4) 在 Target Options 的 C+编译器选项中添加文件包含路径,如下图4、为 FATSF 文件系统添加底层驱动(一)在 diskio.c 中添加函数代码1. DS
4、TATUS disk_status (BYTE pdrv); 添加完成后如下图2. DSTATUS disk_initialize (BYTE pdrv); 添加完成后如下图3. DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 4. DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);5. DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);6. DWOR
5、D get_fattime (void);注意:在 diskio.c 中 DEV_MMC 的宏定义要为 0,如下图(2)打开 Ffconf.h 函数1. 改变 FF_CODE_PAGE 的值如下2. 改变 FF_USE_LFN 的值如下5、Main 主函数Main.c 函数如下代码:#include “main.h“#define ONE_BLOCK 512#define TWO_BLOCK 1024uint8_t sd_RxBufTWO_BLOCK;/SD 卡数据 j 接收缓存区uint8_t sd_TxBufTWO_BLOCK = 0;/SD 卡数据 j 接收缓存区FRESULT res;
6、/读写文件的返回值FIL FileSyatemSrc,FileSystemDst; /文件系统结构体,包含文件指针等成员UINT br,bw; /Fil R/W countBYTE FileRxBufferONE_BLOCK; /FILE COPY BUFFER/BYTE TxFileBuffer = “This is the FATFS System!rn“;BYTE TxFileBuffer = “中文文件系统实验!rn“;static const char * FR_Table= “FR_OK:成功“, /* (0) Succeeded */“FR_DISK_ERR:底层硬件错误“, /
7、* (1) A hard error occurred in the low level disk I/O layer */“FR_INT_ERR:断言失败“, /* (2) Assertion failed */“FR_NOT_READY:物理驱动没有工作“, /* (3) The physical drive cannot work */“FR_NO_FILE:文件不存在“, /* (4) Could not find the file */“FR_NO_PATH:路径不存在 “, /* (5) Could not find the path */“FR_INVALID_NAME:无效文件
8、名“, /* (6) The path name format is invalid */“FR_DENIED:由于禁止访问或者目录已满访问被拒绝“, /* (7) Access denied due to prohibited access or directory full */“FR_EXIST:由于访问被禁止访问被拒绝“, /* (8) Access denied due to prohibited access */“FR_INVALID_OBJECT:文件或者目录对象无效 “, /* (9) The file/directory object is invalid */“FR_WR
9、ITE_PROTECTED:物理驱动被写保护“, /* (10) The physical drive is write protected */“FR_INVALID_DRIVE:逻辑驱动号无效 “, /* (11) The logical drive number is invalid */“FR_NOT_ENABLED:卷中无工作区“, /* (12) The volume has no work area */“FR_NO_FILESYSTEM:没有有效的 FAT 卷“, /* (13) There is no valid FAT volume */“FR_MKFS_ABORTED:由
10、于参数错误 f_mkfs()被终止“, /* (14) The f_mkfs() aborted due to any parameter error */“FR_TIMEOUT:在规定的时间内无法获得访问卷的许可“, /* (15) Could not get a grant to access the volume within defined period */“FR_LOCKED:由于文件共享策略操作被拒绝“, /* (16) The operation is rejected according to the file sharing policy */“FR_NOT_ENOUGH_
11、CORE:无法分配长文件名工作区“, /* (17) LFN working buffer could not be allocated */“FR_TOO_MANY_OPEN_FILES:当前打开的文件数大于_FS_SHARE“, /* (18) Number of open files _FS_SHARE */“FR_INVALID_PARAMETER:参数无效“ /* (19) Given parameter is invalid */;int main(void)int i = 0;FATFS fs; /记录文件系统盘符信息的结构体LED_Init();USARTx_Init();/*
12、 调用 f_mount()创建一个工作区,另一个功能是调用了底层的disk_initialize()函数,进行 SDIO 借口的初始化 */res = f_mount(if (res != FR_OK)printf(“挂载文件系统失败 (%s)rn“, FR_Tableres);elseprintf(“挂载文件系统成功 (%s)rn“, FR_Tableres);/* 调用 f_open()函数在刚刚开辟的工作区的盘符 0 下打开一个名为Demo.TXT 的文件,以创建新文件或写入的方式打开(参数“FA_CREATE_NEW | FA_WRITE“),如果不存在的话则创建这个文件。同意见 De
13、mo.TXT 这个文件关联到 FileSyatemSrc 这个结构指针,以后操作文件就是听过这个结构指针来完成,可以理解为文件指针。*/res = f_open( /* 对 f_open()函数的返回值进行检查 */if( res = FR_OK )printf(“File Open SUCCESS! nt“);/* 将缓冲区的数据写到文件中,创建文件成功,调用 f_write()将缓冲区的数组变量TxFileBuffer 的内容写到刚刚打开的 Demo.TXT 文件中,写完之后必须调用 f_close()函数关闭已经打开的文件,否则前面写入的数据无效,甚至可能导致其他错误*/res = f_
14、write( if(res)printf(“File Write ERROR! nt“);elseprintf(“File Write SUCCESS! nt“);/* 关闭文件 */f_close(else if(res = FR_EXIST)printf(“File is already exist n“);elseprintf(“Dont know the error! rn“);/*-将刚刚新建的文件里面的内容打印到串口-*/ /* 以只读的方式打开刚刚创建的文件 */res = f_open( if(res)printf(“File Open ERROR! nt“);elseprin
15、tf(“File Open SUCCESS! nt“);/* 打开文件 */br = 1;for(;)/* 清缓冲区 */for(i = 0; i ONE_BLOCK; i+)FileRxBufferi = 0;/* 将文件里面的内容读到缓冲区,调用函数 f_read()将文件的内容读到缓冲区 FileRxBuffer 数组变量中,然后打印到串口*/res = f_read( if(res)printf(“File Read ERROR! nt“);elseprintf(“File Read SUCCESS! nt“);printf(“ rn %s “,FileRxBuffer );if(res | br = 0)break; /错误或者到了文件尾/*关闭打开的文件 当被打开的文件操作完成之后都要调用 f_close()将它关闭,如同一块动态分配的内存在用完之后都要调用 free()来将它释放*/f_close(while(1) /* */* (C) COPYRIGHT 2017 TIMEANDSPACE7*END OF FILE*/6、下载及实验现象编译无误后下载,下载会很慢。1. 串口现象“首行的乱码是字符编码的问题,在这里不做解决”2. SD 卡使用读卡器,读取 SD 卡:百度云链接:链接:https:/ 密码:4hkc