你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码  

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习
详细内容请看附件

本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
         

最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需

要调用FatFs Module 提供给用户的一系列应用接口函数,如f_openf_readf_write f_close

等,就可以像在PC 上读/写文件那样简单。

中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c

ff.h,简化版Tiny-FatFs 提供的是tff.ctff.h。除非有必要,使用者一般不用修改,使用时将

需要版本的头文件直接包含进去即可。

需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写

接口Disk I/O 和供给文件创建修改时间的实时时钟。


                        本例程的程序结构图
                  

RTC_time.c

Diskio.c

SD_driver.c

ff.c

fatfs.c


程序的编写

下面我们开始代码的编写:

1、  主函数的编写

int main(void)

{

  RCC_Configuration();

  GPIO_Configuration();

  USART_Configuration();

  SPI_Configuration();

  FATFS_TEST();   //FATFS常用功能测试函数

  while (1)

  {

  }

}

这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:

void SPI_Configuration(void)

{

  SPI_InitTypeDef   SPI_InitStructure;

/* SPI3 Config */

    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写

这里使用文件SD_driver.cSD_driver.h来写出SD读写的一些驱动函数。

函数列表如下:

/* Private define ------------------------------------------------------------*/

/* SD卡类型定义 */

#define SD_TYPE_MMC     0

#define SD_TYPE_V1      1

#define SD_TYPE_V2      2

#define SD_TYPE_V2HC    4


/* SPI总线速度设置*/

#define SPI_SPEED_LOW   0

#define SPI_SPEED_MID   1

#define SPI_SPEED_HIGH  2

/* SD传输数据结束后是否释放总线宏定义 */

#define NO_RELEASE      0

#define RELEASE         1


/* SD卡指令表 */

#define CMD0    0       //卡复位

#define CMD9    9       //命令9 ,读CSD数据

#define CMD10   10      //命令10,读CID数据

#define CMD12   12      //命令12,停止数据传输

#define CMD16   16      //命令16,设置SectorSize 应返回0x00

#define CMD17   17      //命令17,读sector

#define CMD18   18      //命令18,读Multi sector

#define ACMD23  23      //命令23,设置多sector写入前预先擦除Nblock

#define CMD24   24      //命令24,写sector

#define CMD25   25      //命令25,写Multi sector

#define ACMD41  41      //命令41,应返回0x00

#define CMD55   55      //命令55,应返回0x01

#define CMD58   58      //命令58,读OCR信息

#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00


/* Private macro -------------------------------------------------------------*/

//SDCS片选使能端操作:

#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD

#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD

#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电

#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电

#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡

                                                                    //1- 0-


/* Private function prototypes -----------------------------------------------*/

//void SPI_Configuration(void);

void SPI_SetSpeed(u8 SpeedSet);


u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节

u8 SD_WaitReady(void);                          //等待SD卡就绪

u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令

u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);

u8 SD_Init(void);                               //SD卡初始化

                                                //

u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据

u8 SD_GetCID(u8 *cid_data);                     //SDCID

u8 SD_GetCSD(u8 *csd_data);                     //SDCSD

u32 SD_GetCapacity(void);                       //SD卡容量


u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector

u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector

u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector

u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector


3、  文件系统的移植

FatFs文件系统主要有以下函数:

/*-函数详细的解释请查阅附录,点击链接也可以到----*/

/* FatFs module application interface                  */


FRESULT f_mount (BYTE, FATFS*);                                  /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const char*, BYTE);                         /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*);                        /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*);  /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD);                                           /* Move file pointer of a file object */
FRESULT f_close (FIL*);                                                                      /* Close an open file object */
FRESULT f_opendir (DIR*, const char*);                              /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*);                                             /* Read a directory item */
FRESULT f_stat (const char*, FILINFO*);                             /* Get file status */
FRESULT f_getfree (const char*, DWORD*, FATFS**);     /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*);                                                                /* Truncate file */
FRESULT f_sync (FIL*);                                                              /* Flush cached data of a writing file */
FRESULT f_unlink (const char*);                                             /* Delete an existing file or directory */
FRESULT    f_mkdir (const char*);                                                    /* Create a new directory */
FRESULT f_chmod (const char*, BYTE, BYTE);                    /* Change file/dir attriburte */
FRESULT f_utime (const char*, const FILINFO*);               /* Change file/dir timestamp */
FRESULT f_rename (const char*, const char*);                 /* Rename/Move a file or directory */
FRESULT f_mkfs (BYTE, BYTE, WORD);                       /* Create a file system on the drive */


4、  底层接口I/O函数的编写

底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:

/* Prototypes for disk control functions */

DSTATUS disk_initialize (BYTE);

DSTATUS disk_status (BYTE);

DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);

DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);

DRESULT disk_ioctl (BYTE, BYTE, void*);

DWORD get_fattime (void);

6 个接口函数的详细信息如下图所示。

Disk I/O 函数结构图

因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。

1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime

5、  应用层函数的编写

我们这个例程要实现的8个功能如下:


每一个功能都对应一个函数,各个函数如下:

// 0  读取磁盘容量 The f_getfree function gets number of the free clusters

void Test_f_getfree(void);

//1   读磁盘目录 The f_readdir function reads directory entries.

void Test_f_readdir(void);

//2    创建目录   The f_mkdir function creates a new directory

void Test_f_mkdir(void);

//3    读取文件   The f_read function reads data from a file.

void Test_f_read(void);

//4    文件拷贝   The f_write writes data to a file.

void Test_f_write(void);

//5    重命名    Rename file or directory

void Test_f_rename(void);

//6    删除文件   The f_unlink removes file or directory

void Test_f_unlink(void);

//7    格式化     The f_mkfs fucntion creates a file system on the drive.

void Test_f_mkfs(void);



8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:

void *FATFS_Function[][2]=

{

    (void*)Test_f_getfree, "磁盘容量",

    (void*)Test_f_readdir, "读目录  ",

    (void*)Test_f_mkdir,   "创建路径",

    (void*)Test_f_read,    "读文件  ",

    (void*)Test_f_write,   "文件拷贝",

    (void*)Test_f_rename,  "重命名  ",

    (void*)Test_f_unlink,  "删除文件",

    (void*)Test_f_mkfs,    "格式化  ",

    0x00,0x00

};

8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:

0//The f_getfree function gets number of the free clusters

void Test_f_getfree(void)

{

    FATFS fs;

    FATFS *pfs;

    DWORD clust;

    FRESULT res;         // FatFs function common result code


    //检测磁盘是否插好

    if( disk_detect_OK()==FALSE )

      return;


    pfs=&fs;//指向

// Register a work area for logical drive 0

//温馨提示:该函数是文件系统FatFs里的函数,详细说明请查阅本章节最后的附录,可以用Ctrl+F快捷键,弹出搜索框,输入该函数名,找到该函数。以下类似函数均可以这样找到详细说明,不再赘述。该类函数我们会标记红色,并加粗,请留意。比如f_mount, 解释如下:



f_mount(0, &fs);


// 获取空闲簇Get free clusters 空闲簇的值存在clust

    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0


    if ( res==FR_OK )

    {

        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小

              //计算方法:

//   总空间大小   最大簇数×每簇的扇区数÷2÷1024

//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024

        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",

        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,

        clust * pfs->csize /2/1024);

    }

    else

      die(res);//测试函数执行结果分析


    // Unregister a work area before discard it

    f_mount(0, NULL);

}




//1  读取目录 The f_readdir function reads directory entries.

void Test_f_readdir(void)

{

    FATFS fs;        // Work area (file system object) for logical drive

    char path[20];


    //检测磁盘是否插好

    if( disk_detect_OK()==FALSE )

      return;


    f_mount(0, &fs); // Register a work area for logical drive 0


    printp("\r\nread directory:>/");//默认输出主目录下的文件


    USART_Scanf_Name(path);//通过串口输入路径名


    //扫描当前路径下子文件夹,并输出到串口

    scan_current_folder(path);      

    //扫描当前路径下文件,并输出到串口

    scan_current_files(path);


    f_mount(0, NULL);// Unregister a work area before discard it         

}




//2  读取目录  The f_mkdir function creates a new directory

void Test_f_mkdir(void)

{

    FATFS fs;       // Work area (file system object) for logical drive

    FRESULT res;     // FatFs function common result code

    char path[20];

    //检测磁盘是否插好

    if( disk_detect_OK()==FALSE )

      return;

    f_mount(0, &fs); // Register a work area for logical drive 0

    printp("\r\nmake directory:>");

    USART_Scanf_Name(path);//通过串口输入路径名

    res = f_mkdir(path);

    die(res);//测试函数执行结果分析

    f_mount(0, NULL);// Unregister a work area before discard it

}



//3   读文件 The f_read function reads data from a file.

void Test_f_read(void)

{

    //用来记录读文件起始时间、结束时间

    struct tm time_start,time_end ;

    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。

    time_t unix_start,unix_end,interval;

    char path[20];

    //检测磁盘是否插好

    if( disk_detect_OK()==FALSE )

      return;

    //printp("\r\nread filebbbb:>");

    // Register a work area for logical drive 0

    f_mount(0, &fs);


    printp("\r\nread file:>");

    USART_Scanf_Name(path);//通过串口输入文件路径名

    //Open source file

    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);

    die(res);

    //buffer空间设大一点,会提高读的速度。

    //如果文件实际大小512byte

    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。

    //下面两行主要是去除1s误差。

    //Read_File_Flag = 0;

    //while( Read_File_Flag==0 );


    //time_start=Time_GetCalendarTime();//记录开始读时间

    //unix_start=Time_ConvCalendarToUnix(time_start);



    //输出提示..

    if( res==FR_OK )

      printp("\r\nread file start time :%02d:%02d:%02d\r\nplease waiting...\r\n", time_start.tm_hour, time_start.tm_min, time_start.tm_sec);

    for (;;)

    {

        //清除缓存

<span lang="EN-US">        for(i=0;iRTC函数的编写

15科星F107开发板学习笔记—SD卡上文件系统FatFs的学习.pdf

下载

2.25 MB, 下载次数: 949

1 收藏 9 评论38 发布时间:2013-11-20 09:57

举报

38个回答
hhhhhhhaa 回答时间:2018-10-18 09:48:43
ren0zhe 发表于 2013-11-20 09:59
 SD卡读写数据,FatFS文件系统 源码

求助一个STM32F103VCT6与AT45DB081芯片通讯添加文件管理系统FATFS,SPI2的接口的示例
lusonghua 回答时间:2015-6-4 12:25:01
不是很确定FatFS使用SPI-FLASH是否合适,对于NorFlash和NandFlash,损耗平衡什么的也应该注意一下吧。
alvin_ 回答时间:2015-4-10 13:40:38
感谢分享~!支持!最近准备试下,不知道这个能否移植到STM8S003上?
ren0zhe 回答时间:2013-11-20 09:59:14

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

 SD卡读写数据,FatFS文件系统 源码

15科星F107开发板学习笔记源码—SD卡上文件系统FatFs的学习.rar

下载

863.7 KB, 下载次数: 886

沐紫 回答时间:2013-11-20 10:11:23

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

支持支持!
qinkaiabc 回答时间:2013-11-23 15:55:38

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

支持支持!
JohnsonJiang 回答时间:2013-11-27 09:43:25

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

不错,看起来写的很详细。。支持!
boldchild123 回答时间:2013-11-27 17:48:04

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

来学习,取经中,,
少韶 回答时间:2014-3-19 20:49:35

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

,学习学习
1942-406215 回答时间:2014-4-22 10:21:12

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

学习了
xuyp188-265233 回答时间:2014-6-2 13:51:17

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

好东西!
caizhiwei 回答时间:2015-4-10 10:09:00
学习了~~~
stary666 回答时间:2015-4-10 10:22:55
支持一下,学习。。。
木木鱼 回答时间:2015-4-15 23:44:05
必须顶下!
stary666 回答时间:2015-4-16 09:32:05
学习一下。。
eurphan 回答时间:2015-4-16 13:06:19
好人一生平安
123下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版