FATFS移植——STM32+SDCARD

来自:http://flying-in-rain.blog.163.com/blog/static/131868594201206111953388/

(测试环境:IAR540 + STM32F103VBT6 + SDC(SPI方式) + ucOS-II + TFT(ILI9325) )

  FATFS官网:http://elm-chan.org/fsw/ff/00index_e.html

  下载最新版本FatFs R0.09 (November 14,2011)

  解压缩后有两个文件夹doc和src,把src拷贝到工程中,其中包括diskio.h、ff.c、ff.h、integer.h、ffconf.h。

  diskio.h、ff.c、ff.h、integer.h四个文件都不需要修改,移植需要做的:(1)配置ffconf.h。(2)创建底层驱动diskio.c文件。

 

一、根据系统类型配置ffconf.h

_FFCONF是代表了版本号,不做处理。

  • 函数和缓冲区配置
    • _FS_TINY设置缓冲区的位置,假如设置为0,也就是每个文件(FIL结构体)中带一个buf,否则的话,整个文件系统公用一个buf。内存还是够的,所以选择为0。
    • _FS_READONLY设置是否文件只读,系统需要可读写的,设置为0。
    • _FS_MINIMIZE设置为0,因为以下的那些函数要用到,不简化。
    • _USE_STRFUNC设置是否使用字符串函数,主要有f_gets, f_putc, f_puts, f_printf四个函数,暂时不用,因为我们的数据都是自定义结构体的存储方式,为了节省空间这个设置为0。
    • _USE_MKFS设置是否实现f_mkfs函数。我们需要在设备初始化时完全格式化Flash,所以此函数需要。
    • _USE_FORWORD设置
    • _USE_FASTSEEK设置是否支持文件快速定位,它主要采用缓冲区来存储簇链映射图,以空间换时间,对于我们系统不合算,还是采用普通定位方式好。
  • 本地化和命名空间配置
    • _CODE_PAGE设置目标系统的本地化设置,本系统有ASCII支持就足够了,支持本地化的情况下,模块的大小将大幅增加,反而不符合我们选择FatFs的初衷,所以选择1。
    • _USE_LFN设置长文件名,我们系统不支持,设为0。
    • _MAX_LFN不用设置,因为不支持长文件名。
    • _LFN_UNICODE设置长文件名是否支持Unicode,我们选择不支持,因为不支持长文件名。
    • _FS_RPATH设置相对路径支持。相对路径在编程的时候特别方便,但是为了先移植成功,暂不支持。
  • 物理驱动器配置
    • _VOLUMES设置逻辑驱动器的个数,默认为1。
    • _MULTI_PARTITION设置是否多个分区。不分区,设为0。
    • _USE_ERASE设置擦除扇区。在f_mkfs和remove_chain两个函数中添加擦除的代码,设置为0。
  • 系统配置
    • _WORD_ACCESS设置是否支持字访问。不支持。
    • _FS_REENTRANT设置是否重入。因为我们的系统文件访问不是很频繁,而且都是在一个任务中访问,所以不支持重入。
    • _FS_TIMEOUT超时设置。
    • _SYNC_t访问重入时的同步句柄。
    • _FS_SHARE设置文件共享,能同时被几个文件同时打开。设置为0。

     

    二、配置完成后,编译一下程序。此时编译是不会成功的,从错误提示中可见,缺少六个函数disk_initialize,disk_write,disk_read,get_fattime,disk_ioctl,disk_status。这几个函数在diskio.h中有声明,是底层驱动的接口,需要创建diskio.c并自己编写这几个函数。

     

    三、创建diskio.c。

      该次测试的SDCARD用的是SPI方式,关于SDCARD的读写和SPI的应用在该博客其它文章中有详细说明,这里就不多讲了,只对FATFS相关文件作说明。

    (1)get_fattime——得到系统时间。可以从RTC中获取时间,作为测试,此处只是随便返回一个数。
    DWORD get_fattime (void)
    {
      return   ((DWORD)(2010 - 1980) << 25) /* Fixed to Jan. 1, 2010 */
         | ((DWORD)1 << 21)
         | ((DWORD)1 << 16)
         | ((DWORD)0 << 11)
         | ((DWORD)0 << 5)
         | ((DWORD)0 >> 1);
    }

    (2)disk_initialize——磁盘初始化。这里只用了一个卡,驱动器号为0即可。

    DSTATUS disk_initialize (BYTE drv)
    {
      while(SD_Init()!=0);  // SD_Init为SD卡初始化
      return 0;
    }

    (3)disk_status——获取磁盘状态。这里直接返回0,表示状态OK,以后再写

    DSTATUS disk_status (
     BYTE drv   /* Drive number (always 0) */
    )
    {
      return 0;
    }

    (4)disk_ioctl——实现控制I/O的特性设置。这里直接返回0表示OK,以后再写
    DRESULT disk_ioctl (
     BYTE drv,  /* Physical drive nmuber (0) */
     BYTE ctrl,  /* Control code */
     void *buff  /* Buffer to send/receive control data */
    )
    {
      return RES_OK; 
    }

    (5)disk_read——磁盘读
    DRESULT disk_read (
     BYTE drv,   /* Physical drive nmuber (0) */
     BYTE *buff,   /* Pointer to the data buffer to store read data */
     DWORD sector,  /* Start sector number (LBA) */
     BYTE count   /* Sector count (1..128) */
    )
    {  
      if(count>1)
        SD_ReadMultiBlock(sector, buff, count); 
      else
        SD_ReadSingleBlock(sector, buff);    
      return RES_OK; 
    }

    (6)disk_write——磁盘写
    DRESULT disk_write (
     BYTE drv,   /* Physical drive nmuber (0) */
     const BYTE *buff, /* Pointer to the data to be written */
     DWORD sector,  /* Start sector number (LBA) */
     BYTE count   /* Sector count (1..128) */
    )

      if(count>1)
        SD_WriteMultiBlock(sector, buff, count); 
      else
        SD_WriteSingleBlock(sector, buff); 
      return RES_OK;
    }

     

    四、编译程序成功。开始FATFS的API。
     FRESULT res;   /* Result code */
     FATFS fatfs;   /* File system object */
     FIL fil;    /* File object */
     DIR dirs;    /* Directory object */
     FILINFO finfo;   /* File information object */
     UINT br;
     BYTE buff[128];
     char  diskname[20] = {"newdir"};

    disk_initialize(0);
    f_mount(0, &fatfs);
    res = f_mkdir(diskname);                                    // 新建文件夹,名为newdir
    res = f_open(&fil, "123.txt", FA_OPEN_EXISTING | FA_READ);      // 打开123.txt 文件
    if(res==FR_OK)
    {
      res = f_read(&fil,buff,sizeof(buff),&br);  // 读文件
      for(i=0;i<br;i++)
        send_data(buff[i]);        // 通过串口把读到的数据送到PC,校验正确性
      f_close(&fil);             // 关闭文件
    }
    f_mount(0, NULL);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值