自己移植的SD卡的FATFS文件系统,FATFS R0.09 (MDK STM32f103)【转】

 2 E币 
成为会员,免费下载资料
文件大小:1.24 MB 上传者:ljc2010 时间:2013-08-26 14:10:55 下载量:10
【转载】

自己移植的SD卡的FATFS文件系统,采用最新版FATFS R0.09,并且有详细的中文注释,和操作测试程序,完整的MDK  STM32F103工程。下载即可使用。
/*----------------------------------------------------------------------------/
/  FatFs - FAT file system module  R0.09                  (C)ChaN, 2011
/-----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/  Copyright (C) 2011, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-----------------------------------------------------------------------------/


/*--------------File Info-------------------------------------------------------
** 文   件   名:  FATFS_Function.c
** 作        者:~风中的叶~    整理
** 最后修改日期:  2012.01.18
** 版        本:  V1.0
** 描        述:  FATFS常用功能测试函数 .连接PC机串口,观察超级终端输出
**------------------------------------------------------------------------------
** Created   by:  Dt.
** Created date:  
*******************************************************************************/
#include "TEST_FATFS.h"
#include "string.h"

#ifdef TEST_FATFS_EN



//检测磁盘是否插好
BOOL disk_detect_OK(void)
{
    if( disk_status(0)==STA_NODISK )/* Physical drive nmuber (0..) */
        {
            printf("\r\n\r\n%48s\r\n","<未检测到磁盘,请检查SD卡是否插好...>");
                return FALSE;
        }
        return TRUE;
}



//测试函数执行结果分析
void die(FRESULT res)
{
    switch(res)
        {
            case FR_OK:        //The function succeeded.
                {
                    printf("\r\nThe function succeeded!\r\n");
                        break;
                }
                case FR_NOT_READY://The disk drive cannot work due to no medium in the drive or any other reason
                {
                    printf("\r\nThe disk drive cannot work due to no medium in the drive or any other reason!\r\n");
                        break;
                }
                case FR_NO_FILE://Could not find the file.
                {
                    printf("\r\nCould not find the file!\r\n");
                        break;
                }
                case FR_NO_PATH://Could not find the path
                {
                    printf("\r\nCould not find the path!\r\n");
                        break;
                }
                case FR_INVALID_NAME://The path name is invalid
                {
                    printf("\r\nThe path name is invalid!\r\n");
                        break;
                }
                case FR_INVALID_DRIVE://The drive number is invalid
                {
                    printf("\r\nThe drive number is invalid!\r\n");
                        break;
                }
                case FR_DENIED://The directory cannot be created due to directory table or disk is full.
                {
                    printf("\r\nThe directory cannot be created due to directory table or disk is full!\r\n");
                        break;
                }
                case FR_EXIST://A file or directory that has same name is already existing
                {
                    printf("\r\nA file or directory that has same name is already existing!\r\n");
                        break;
                }
//                case FR_RW_ERROR://The function failed due to a disk error or an internal error
/*
                case FR_RW_ERROR://The function failed due to a disk error or an internal error
                {
                    printp("\r\nThe function failed due to a disk error or an internal error!\r\n");
                        break;
                }
*/
                case FR_WRITE_PROTECTED://The medium is write protected
                {
                    printf("\r\nThe medium is write protected!\r\n");
                        break;
                }
                case FR_NOT_ENABLED://The logical drive has no work area
                {
                    printf("\r\nThe logical drive has no work area!\r\n");
                        break;
                }
                case FR_NO_FILESYSTEM://There is no valid FAT partition on the disk
                {
                    printf("\r\nThere is no valid FAT partition on the disk!\r\n");
                        break;
                }
                case FR_INVALID_OBJECT://The file object is invalid
                {
                    printf("\r\nThe file object is invalid!\r\n");
                        break;
                }

            //The function aborted before start in format due to a reason as follows.
        //The disk size is too small.
        //Invalid parameter was given to any parameter.
        //Not allowable cluster size for this drive. This can occure when number of clusters becomes around 0xFF7 and 0xFFF7.
                case FR_MKFS_ABORTED://
                {
                    printf("\r\nThe function aborted before start in format!\r\n");
                        break;
                }
               
                default:
                {
                    printf("\r\nerror!\r\n");
                        break;
                }        
        }
        return;
}
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
    f_mount(0, &fs);//安装FATFS,就是给FATFS分配空间

    // Get free clusters
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0;"/"或者"0:/"
    if ( res==FR_OK )
    {
            // Get free space
        printf("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",
                (DWORD)(pfs->n_fatent - 2) * pfs->csize /2/1024,//总的磁盘空间M        =(总簇数-2)*每簇的扇区数/2/1024=可用簇数*每簇的扇区数/2/1024
                 clust * pfs->csize /2/1024);//空闲的磁盘空间M=剩余簇数*每簇的扇区数/2/1024
        }
        else die(res);//测试函数执行结果分析
        
        // Unregister a work area before discard it
    f_mount(0, NULL);//卸载FATFS,就是释放FATFS结构体所占空间
}

void Test_f_read(void)//读文件的数据,如果没有此文件则返回错误
{
    FATFS fs;            // Work area (file system object) for logical drive
    FIL fsrc;            // file objects
    BYTE buffer[512];     // file copy buffer
    FRESULT res;         // FatFs function common result code
    UINT br;             // File R count
        u16 i;
        

        char path[20];

        //检测磁盘是否插好
        if( disk_detect_OK()==FALSE ) return;

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

        printf("\r\nread file:>");
        USART_Scanf_Name(path);//通过串口输入文件路径名/dir/file.txt或者0:dir/file.txt或者0:/dir/file.txt

        //Open source file
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);//打开存在的文件,如果没有则返回错误
        die(res);
        
        //buffer空间设大一点,会提高读的速度。
        //如果文件实际大小512byte,
        //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。
        //下面两行主要是去除1s误差。

        for (;;)
        {
                for(i=0;i='\0';//清除缓存

                res = f_read(&fsrc, buffer, sizeof(buffer), &br);
        if (res ||(br == 0)) break;   // error or eof        
               
                printf("%s",buffer);        
    }

                           
    // Close all files
    f_close(&fsrc);
    // Unregister a work area before discard it
    f_mount(0, NULL);
}

void Test_f_write(void)//写数据到文件,如果没有此文件则创建文件
{
    FATFS fs;            // Work area (file system object) for logical drive
    FRESULT res;         // FatFs function common result code
        FIL Make_file;
    char file_name[20];
    char Storage_buffer[] ="0";
        
        UINT bw;
        //检测磁盘是否插好
        if( disk_detect_OK()==FALSE ) return;
         printf("\r\n inaert_ok:>");
    // Register a work area for logical drive 0
    f_mount(0, &fs);

        printf("\r\n Make file Name:>");
        USART_Scanf_Name(file_name);//通过串口输入源文件路径名/dir/file.txt或者0:dir/file.txt或者0:/dir/file.txt

    res = f_open(&Make_file, file_name,  FA_OPEN_ALWAYS | FA_WRITE); //可写方式打开 没有文件则创建
         printf("\r\n open_ok:>");
         die(res);
    res = f_lseek(&Make_file, Make_file.fsize); //指针移到文件最后  
      printf("\r\n seek_ok:>");
         die(res);
        res = f_write(&Make_file, Storage_buffer, (sizeof (Storage_buffer))-1 , &bw); //每次需要写入的数据字节数,去掉最后的\0所以-1  
     printf("\r\n write_ok:>");
         die(res);
        res = f_lseek(&Make_file, Make_file.fsize); //指针移到文件最后  
        f_close(&Make_file);//关闭文件
        printf("\r\n close_ok:>");

        printf("\r\n写文件测试OK!\r\n");

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

//The f_read function reads data from a file.
//在RAM里面调试这个程序的时候,总出现莫名其妙的错误,最后怀疑是堆寨溢出了,证明果然是这样
//把Stack_Size   EQU   0x00000400  改为 Stack_Size   EQU  0x00000800就正常了
//所以以后要特别注意这个问题。

u8 StrToData(u8 * data, u8 len)
{
        u8 ltemp;
        if(len == 1)
        {
                ltemp = data[0]-0x30;

        }
        else if(len == 2)
        {
                ltemp = (data[0]-0x30)*10 + (data[1]-0x30);

         }
        //else if(len == 3)
                //ltemp = (data[0]-0x30)*100 + (data[1]-0x30)*10 + [data[2] - 0x30];

        return ltemp;
        
}


#endif


/*
int main(void)
{
///////////////////////////////////////////////////////////
UART1GPIO_config();//串口IO口配置
USART1_config();//串口初始化波特率为19200
//UART1NVIC_config();//配置中断
///////////////////////////////////////////////////////////
SDCard_SpiInit();//SD卡的IO口及SPI模块初始化,PA2插入检测(H—>L);PA3 CD_CS片选;PA5 SCK;PA6 MISO;PA7 MOSI;低速模式
//SD_Init();//SD卡初始化,如果使用的FATFS则可以不用这句,因为FATFS在打开文件等操作时已经调用了它
Test_f_getfree();//获取SD卡的容量和剩余容量
Test_f_read();//SD卡读文件测试
Test_f_write();//SD卡写文件测试
///////////////////////////////////////////////////////////
    while (1)
    {
        //printf("好的");
    }
}*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_mkfs(BYTE drv)//对卡进行格式化,驱动器号一般为0
{
    FATFS fs;            // Work area (file system object) for logical drive
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(drv, &fs);
        res=f_mkfs(drv, 0, 0);/* Create a file system on the drive 在驱动器创建一个文件系统(驱动器号,分区规则(0:FDISK, 1:SFD),分配的单元大小)*/
        //die(res);
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_mkdir(const TCHAR* path)//创建一个新目录,输入目录的路径Test_f_mkdir("/dir");只能一级一级的建立目录        
{
    FATFS fs;            // Work area (file system object) for logical drive
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(0, &fs);
        res=f_mkdir(path);//创建一个新目录
        //die(res);
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_deldir(const TCHAR* path)//删除一个目录,输入目录的路径;目录里的内容是空的才能删除Test_f_deldir("/dir");        
{
    FATFS fs;            // Work area (file system object) for logical drive
        //DIR        dir;
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(0, &fs);
        //f_opendir (&dir,path);
        res=f_unlink(path);//删除一个目录
        //die(res);
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_readdir(const TCHAR* path,char (*filename)[13])//获取目录中的文件,输入目录的路径;输出文件名和文件夹名Test_f_readdir("/DIR",name);char name[5][13]        
{
    FATFS fs;            // Work area (file system object) for logical drive
        DIR        dir;
        FILINFO finf;
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(0, &fs);
        f_opendir (&dir,path);

        while(((res=f_readdir(&dir,&finf))==FR_OK)&&(finf.fname[0]))//获取目录中的文件        
        {strcpy(*(filename++),finf.fname);
        //printf("%s",finf.fname);
        }
        //die(res);
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_creat(const TCHAR* path)//建立文件,输入文件路径和文件名
{
    FATFS fs;            // Work area (file system object) for logical drive
        FIL file;
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(0, &fs);
        res=f_open(&file,path,FA_CREATE_NEW); //创建一个新文件。如果文件已存在,则创建失败//FA_CREATE_NEW创建一个新文件。如果文件已存在,则创建失败。
                                                                                      //FA_CREATE_ALWAYS        //创建一个新文件。如果文件已存在,则它将被截断并覆盖。
                                                                                      //FA_OPEN_ALWAYS    //如果文件存在,则打开;否则,创建一个新文件。
        //die(res);
        f_close(&file);//关闭文件
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_delfile(const TCHAR* path)//删除一个文件,输入文件的路径;Test_f_delfile("/dir");        
{
    FATFS fs;            // Work area (file system object) for logical drive
        //DIR        dir;
    FRESULT res;         // FatFs function common result code

        //检测磁盘是否插好
        //if(disk_detect_OK()==FALSE ) return ;
        //printf("\r\n inaert_ok:>");
        // Register a work area for logical drive 0
        f_mount(0, &fs);
        //f_opendir (&dir,path);
        res=f_unlink(path);//删除一个文件
        //die(res);
        f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_readfile(const TCHAR* path,char *buff,DWORD ofs,UINT strl)//读文件的数据,如果没有此文件则返回错误;输入文件的路径名,内容缓存,读取开始偏移指针,读取的字节数
{                                                                                                                                                  //Test_f_readfile("/dir/r.txt",str,0,sizeof(strr));
    FATFS fs;            // Work area (file system object) for logical drive
    FIL file;            // file objects
    FRESULT res;         // FatFs function common result code
    UINT br;             // File R count 文件读回的字节计数
        //u16 i;
        //检测磁盘是否插好
        //if( disk_detect_OK()==FALSE ) return;
    // Register a work area for logical drive 0
        //for(i=0;i='\0';
    f_mount(0, &fs);
        //Open source file
    res = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);//打开存在的文件,如果没有则返回错误
        //die(res);
        res = f_lseek(&file,ofs); //指针移到文件ofs个字节处
        //buffer空间设大一点,会提高读的速度。
        //如果文件实际大小512byte,
        //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。
        //for (;;)
        {
                //for(i=0;i='\0';//清除缓存

                res = f_read(&file, buff, strl, &br);
        //if (res ||(br == 0)) break;   // error or eof如果错误或者到文件末尾则退出
               
                //printf("%s",buff);        
    }                    
    // Close all files
    f_close(&file);
    // Unregister a work area before discard it
    f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_writefile(const TCHAR* path,char *buff,DWORD ofs,UINT strl)//写数据到文件,如果没有此文件则创建文件;输入文件的路径名,内容缓存,写开始偏移指针,写的字节数
{                                                                                                                                                  //Test_f_writefile("/dir/r.txt",strw,0,strlen(strw));
    FATFS fs;            // Work area (file system object) for logical drive
    FRESULT res;         // FatFs function common result code
        FIL file;
        UINT bw;             //文件写入的字节计数
        //检测磁盘是否插好
        //if( disk_detect_OK()==FALSE ) return;
    // Register a work area for logical drive 0
    f_mount(0, &fs);
    res = f_open(&file, path,  FA_OPEN_ALWAYS | FA_WRITE); //可写方式打开 没有文件则创建
         //die(res);
    res = f_lseek(&file, ofs); //指针移到文件ofs处;输入file.fsize指针移到文件最后
         //die(res);
        res = f_write(&file, buff, strl, &bw); //每次需要写入的数据字节数;如果btr为strlen(buff)则写入所有的字符
         //die(res);
        //res = f_lseek(&file, Make_file.fsize); //指针移到文件最后,一边再一次的写入  
        f_close(&file);//关闭文件
        // Unregister a work area before discard it
    f_mount(0, NULL);
        return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FRESULT Test_f_getfreem(DWORD *freem)//获取卡的剩余容量单位为M
{
    FATFS fs;
        FATFS *pfs;
        FRESULT res;         // FatFs function common result code
        //检测磁盘是否插好
        //if( disk_detect_OK()==FALSE ) return;
        // Register a work area for logical drive 0
        pfs=&fs;//指向
    f_mount(0, &fs);//安装FATFS,就是给FATFS分配空间
    // Get free clusters
    res = f_getfree("/",freem,&pfs);//必须是根目录,默认磁盘0;"/"或者"0:/"
        //die(res);
        if ( res==FR_OK )
    {
            // Get free space
        //printf("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",
               //(DWORD)(pfs->n_fatent - 2) * (pfs->csize) /2/1024,//总的磁盘空间M        =(总簇数-2)*每簇的扇区数/2/1024=可用簇数*每簇的扇区数/2/1024
                 //(*freem)*(pfs->csize)/2/1024);//空闲的磁盘空间M=剩余簇数*每簇的扇区数/2/1024
         *freem=((*freem)*pfs->csize)/2/1024;
        }
        //else die(res);//测试函数执行结果分析
        // Unregister a work area before discard it
    f_mount(0, NULL);//卸载FATFS,就是释放FATFS结构体所占空间
        return res;
}



/ Feb 26,'06 R0.00  Prototype.
/
/ Apr 29,'06 R0.01  First stable version.
/
/ Jun 01,'06 R0.02  Added FAT12 support.
/                   Removed unbuffered mode.
/                   Fixed a problem on small (<32M) partition.
/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
/
/ Sep 22,'06 R0.03  Added f_rename().
/                   Changed option _FS_MINIMUM to _FS_MINIMIZE.
/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.
/                   Fixed f_mkdir() creates incorrect directory on FAT32.
/
/ Feb 04,'07 R0.04  Supported multiple drive system.
/                   Changed some interfaces for multiple drive system.
/                   Changed f_mountdrv() to f_mount().
/                   Added f_mkfs().
/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive.
/                   Added a capability of extending file size to f_lseek().
/                   Added minimization level 3.
/                   Fixed an endian sensitive code in f_mkfs().
/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
/                   Added FSInfo support.
/                   Fixed DBCS name can result FR_INVALID_NAME.
/                   Fixed short seek (<= csize) collapses the file object.
/
/ Aug 25,'07 R0.05  Changed arguments of f_read(), f_write() and f_mkfs().
/                   Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
/                   Fixed f_mkdir() on FAT32 creates incorrect directory.
/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().
/                   Fixed off by one error at FAT sub-type determination.
/                   Fixed btr in f_read() can be mistruncated.
/                   Fixed cached sector is not flushed when create and close without write.
/
/ Apr 01,'08 R0.06  Added fputc(), fputs(), fprintf() and fgets().
/                   Improved performance of f_lseek() on moving to the same or following cluster.
/
/ Apr 01,'09 R0.07  Merged Tiny-FatFs as a configuration option. (_FS_TINY)
/                   Added long file name feature.
/                   Added multiple code page feature.
/                   Added re-entrancy for multitask operation.
/                   Added auto cluster size selection to f_mkfs().
/                   Added rewind option to f_readdir().
/                   Changed result code of critical errors.
/                   Renamed string functions to avoid name collision.
/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
/                   Added multiple sector size feature.
/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.
/                   Fixed wrong cache control in f_lseek().
/                   Added relative path feature.
/                   Added f_chdir() and f_chdrive().
/                   Added proper case conversion to extended char.
/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.
/                   Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
/                   Fixed name matching error on the 13 char boundary.
/                   Added a configuration option, _LFN_UNICODE.
/                   Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
/
/ May 15,'10 R0.08  Added a memory configuration option. (_USE_LFN = 3)
/                   Added file lock feature. (_FS_SHARE)
/                   Added fast seek feature. (_USE_FASTSEEK)
/                   Changed some types on the API, XCHAR->TCHAR.
/                   Changed fname member in the FILINFO structure on Unicode cfg.
/                   String functions support UTF-8 encoding files on Unicode cfg.
/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
/                   Added sector erase feature. (_USE_ERASE)
/                   Moved file lock semaphore table from fs object to the bss.
/                   Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
/                   Fixed f_mkfs() creates wrong FAT32 volume.
/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
/                   f_lseek() reports required table size on creating CLMP.
/                   Extended format syntax of f_printf function.
/                   Ignores duplicated directory separators in given path names.
/
/ Sep 06,'11 R0.09  f_mkfs() supports multiple partition to finish the multiple partition feature.
/                   Added f_fdisk(). (_MULTI_PARTITION = 2)
/---------------------------------------------------------------------------*/
展开
折叠
945
评论
共 0 个
内容存在敏感词
    易百纳技术社区暂无数据
相关资料
关于作者
易百纳技术社区
ljc2010
贡献资料 74
易百纳技术社区 我上传的资料
登录查看
我赚取的积分
登录查看
我赚取的收益
登录查看
上传资料 赚取积分兑换E币
易百纳技术社区
删除原因
广告/SPAM
恶意灌水
违规内容
文不对题
重复发帖
置顶时间设置
结束时间
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-资料模块

审核失败

失败原因
备注
易百纳技术社区