OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 18581|回复: 43

【ALIENTEK 战舰STM32开发板例程系列连载+教学】第四十五章  FATFS实验

[复制链接]

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-4-5 22:48:42 | 显示全部楼层 |阅读模式
 

第四十五章  FATFS实验

上一章,我们学习了SD卡的使用,不过仅仅是简单的实现读扇区而已,真正要好好应用SD卡,必须使用文件系统管理,本章,我们将使用FATFS来管理SD卡,实现SD卡文件的读写等基本功能。本章分为如下几个部分:

45.1 FATFS简介

45.2 硬件设计

45.3 软件设计

45.4 下载验证


45.1 FATFS简介    

FATFS是一个完全免费开源的FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准C 语言编写,所以具有良好的硬件平**立性,可以移植到8051PICAVRSHZ80H8ARM 等系列单片机上而只需做简单的修改。它支持FATl2FATl6 FAT32,支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对8 位单片机和16 位单片机做了优化。

FATFS的特点有:

l  Windows兼容的FAT文件系统(支持FAT12/FAT16/FAT32

l  与平台无关,移植简单

l  代码量少、效率高

l  多种配置选项

?  支持多卷(物理驱动器或分区,最多10个卷)

?  多个ANSI/OEM代码页包括DBCS

?  支持长文件名、ANSI/OEMUnicode

?  支持RTOS

?  支持多种扇区大小

?  只读、最小化的APII/O缓冲区等

FATFS的这些特点,加上免费、开源的原则,使得FATFS应用非常广泛。FATFS模块的层次结构如图45.1.1所示:


45.1.1 FATFS层次结构图

最顶层是应用层,使用者无需理会FATFS的内部结构和复杂的FAT 协议,只需要调用FATFS模块提供给用户的一系列应用接口函数,如f_openf_readf_write f_close等,就可以像在PC 上读/写文件那样简单。

中间层FATFS模块,实现了FAT 文件读/写协议。FATFS模块提供的是ff.cff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。

需要我们编写移植代码的是FATFS模块提供的底层接口,它包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟。

FATFS的源码,大家可以在:http://elm-chan.org/fsw/ff/00index_e.html 这个网站下载到,目前最新版本为R0.09a。本章我们就使用最新版本的的FATFS作为介绍,下载最新版本的FATFS软件包,解压后可以得到两个文件夹:docsrcdoc里面主要是对FATFS的介绍,而src里面才是我们需要的源码。

其中,与平台无关的是:

ffconf.h                 FATFS模块配置文件

ff.h                       FATFS和应用模块公用的包含文件

ff.c                       FATFS模块

diskio.h                 FATFSdisk I/O模块公用的包含文件

interger.h               数据类型定义

option                   可选的外部功能(比如支持中文等)

与平台相关的代码(需要用户提供)是:

diskio.c                 FATFSdisk I/O模块接口层文件

FATFS模块在移植的时候,我们一般只需要修改2个文件,即ffconf.hdiskio.cFATFS模块的所有配置项都是存放在ffconf.h里面,我们可以通过配置里面的一些选项,来满足自己的需求。接下来我们介绍几个重要的配置选项。

1_FS_TINY。这个选项在R0.07版本中开始出现,之前的版本都是以独立的C文件出现(FATFSTiny FATFS),有了这个选项之后,两者整合在一起了,使用起来更方便。我们使用FATFS,所以把这个选项定义为0即可。

2_FS_READONLY。这个用来配置是不是只读,本章我们需要读写都用,所以这里设置为0即可。

3_USE_STRFUNC。这个用来设置是否支持字符串类操作,比如f_putcf_puts等,本章我们需要用到,故设置这里为1

4_USE_MKFS。这个用来定时是否使能格式化,本章需要用到,所以设置这里为1

5_USE_FASTSEEK。这个用来使能快速定位,我们设置为1,使能快速定位。

6_CODE_PAGE。这个用于设置语言类型,包括很多选项(见FATFS官网说明),我们这里设置为936,即简体中文(GBK码,需要c936.c文件支持,该文件在option文件夹)。

7_USE_LFN。该选项用于设置是否支持长文件名(还需要_CODE_PAGE支持),取值范围为0~30,表示不支持长文件名,1~3是支持长文件名,但是存储地方不一样,我们选择使用3,通过ff_memalloc函数来动态分配长文件名的存储区域。

8_VOLUMES。用于设置FATFS支持的逻辑设备数目,我们设置为2,即支持2个设备。

9_MAX_SS。扇区缓冲的最大值,一般设置为512

其他配置项,我们这里就不一一介绍了,FATFS的说明文档里面有很详细的介绍,大家自己阅读即可。下面我们来讲讲FATFS的移植,FATFS的移植主要分为3步:

     数据类型:在integer.h 里面去定义好数据的类型。这里需要了解你用的编译器的数

据类型,并根据编译器定义好数据类型。

     配置:通过ffconf.h配置FATFS的相关功能,以满足你的需要。

     函数编写:打开diskio.c,进行底层驱动编写,一般需要编写6 个接口函数,如

45.1.2 所示:


45.1.2 diskio 需要实现的函数

       通过以上三步,我们即可完成对FATFS的移植。

       第一步,我们使用的是MDK3.80a编译器,器数据类型和integer.h里面定义的一致,所以此步,我们不需要做任何改动。

       第二步,关于ffconf.h里面的相关配置,我们在前面已经有介绍(之前介绍的9个配置),我们将对应配置修改为我们介绍时候的值即可,其他的配置用默认配置。

第三步,因为FATFS模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FATFS的一部分,并且必须由用户提供。这些函数一般有6个,在diskio.c里面。

首先是disk_initialize函数,该函数介绍如图45.1.3所示:


 
45.1.3 disk_initialize函数介绍

       第二个函数是disk_status函数,该函数介绍如图45.1.4所示:

45.1.4 disk_status函数介绍

       第三个函数是disk_read函数,该函数介绍如图45.1.5所示:


45.1.5 disk_read函数介绍

       第四个函数是disk_write函数,该函数介绍如图45.1.6所示:


45.1.6 disk_write函数介绍

       第五个函数是disk_ioctl函数,该函数介绍如图45.1.7所示:


45.1.7 disk_ioctl函数介绍

       最后一个函数是get_fattime函数,该函数介绍如图45.1.8所示:


45.1.8 get_fattime函数介绍

       以上六个函数,我们将在软件设计部分一一实现。通过以上3个步骤,我们就完成了对FATFS的移植,就可以在我们的代码里面使用FATFS了。

       FATFS提供了很多API函数,这些函数FATFS的自带介绍文件里面都有详细的介绍(包括参考代码),我们这里就不多说了。这里需要注意的是,在使用FATFS的时候,必须先通过f_mount函数注册一个工作区,才能开始后续API的使用,关于FATFS的介绍,我们就介绍到这里。大家可以通过FATFS自带的介绍文件进一步了解和熟悉FATFS的使用。

45.2 硬件设计 

本章实验功能简介:开机的时候先初始化SD卡,初始化成功之后,注册两个工作区(一个给SD卡用,一个给SPI FLASH用),然后获取SD卡的容量和剩余空间,并显示在LCD模块上,最后等待USMART输入指令进行各项测试。本实验通过DS0指示程序运行状态。

本实验用到的硬件资源有:

1)  指示灯DS0 

2)  串口

3)  TFTLCD模块

4)  SD

5)  SPI FLASH

      这些,我们在之前都已经介绍过,如有不清楚,请参考之前内容。

45.3 软件设计

本章,我们将FATFS部分单独做一个分组,在工程目录下新建一个FATFS的文件夹,然后将FATFS R0.09a程序包解压到该文件夹下。同时,我们在FATFS文件夹里面新建一个exfuns的文件夹,用于存放我们针对FATFS做的一些扩展代码。设计完如图45.3.1所示:


45.3.1 FATFS文件夹子目录

然后,打开上一章的工程,新建一个FATFS分组,然后将图45.3.1src文件夹里面的ff.hdiskio.h以及option文件夹下的cc936.c3个文件加入到FATFS组下,并将src文件夹加入头文件包含路径。

    打开diskio.c,修改代码如下:

#include "mmc_sd.h"

#include "diskio.h"

#include "flash.h"

#include "malloc.h"                              

#define SD_CARD 0  //SD,卷标为0

#define EX_FLASH 1   //外部flash,卷标为1

#define FLASH_SECTOR_SIZE 512                 

//对于W25Q64

//6M字节给fatfs,6M字节后~6M+500K给用户用,6M+500K以后,用于存放字库,

//字库占用1.5M. 

u16      FLASH_SECTOR_COUNT=2048*6;   //6M字节,默认为W25Q64

#define FLASH_BLOCK_SIZE  8                //每个BLOCK8个扇区

//初始化磁盘

DSTATUS disk_initialize (

       BYTE drv                           /* Physical drive nmuber (0..) */

)

{    

       u8 res=0;    

       switch(drv)

       {

              case SD_CARD://SD

                     res = SD_Initialize();//SD_Initialize()

                    if(res)//STM32 SPIbug,sd卡操作失败的时候如果不执行下面的语句,

{    //可能导致SPI读写异常

                            SD_SPI_SpeedLow();

                            SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟

                            SD_SPI_SpeedHigh();

                     }

                    break;

              case EX_FLASH://外部flash

                     SPI_Flash_Init();

if(SPI_FLASH_TYPE==W25Q64)FLASH_SECTOR_COUNT=2048*6;

                     else FLASH_SECTOR_COUNT=2048*2;                                       //其他

                    break;

              default:

                     res=1;

       }           

       if(res)return  STA_NOINIT;

       else return 0; //初始化成功

}  

//获得磁盘状态

DSTATUS disk_status (

       BYTE drv             /* Physical drive nmuber (0..) */

)

{              

    return 0;

}

 //读扇区

 //drv:磁盘编号0~9

 //*buff:数据接收缓冲首地址

 //sector:扇区地址

 //count:需要读取的扇区数

DRESULT disk_read (

       BYTE drv,             /* Physical drive nmuber (0..) */

       BYTE *buff,         /* Data buffer to store read data */

       DWORD sector,     /* Sector address (LBA) */

       BYTE count          /* Number of sectors to read (1..255) */

)

{

       u8 res=0;

    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误                    

       switch(drv)

       {

              case SD_CARD://SD

                     res=SD_ReadDisk(buff,sector,count);  

                    if(res)     //STM32 SPIbug,sd卡操作失败的时候如果不执行下面的语句,

{            //可能导致SPI读写异常

                            SD_SPI_SpeedLow();

                            SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟

                            SD_SPI_SpeedHigh();

                     }

                     break;

              case EX_FLASH://外部flash

                     for(;count>0;count--)

                     {

                     SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);

                     sector++; buff+=FLASH_SECTOR_SIZE;

                     }

                     res=0;

                     break;

              default:

                     res=1;

       }

   //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值

    if(res==0x00)return RES_OK;     

    else return RES_ERROR;        

 //写扇区

 //drv:磁盘编号0~9

 //*buff:发送数据首地址

 //sector:扇区地址

 //count:需要写入的扇区数     

#if _READONLY == 0

DRESULT disk_write (

       BYTE drv,                    /* Physical drive nmuber (0..) */

       const BYTE *buff,         /* Data to be written */

       DWORD sector,            /* Sector address (LBA) */

       BYTE count                 /* Number of sectors to write (1..255) */

)

{

       u8 res=0; 

    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误                    

       switch(drv)

       {

              case SD_CARD://SD

                     res=SD_WriteDisk((u8*)buff,sector,count);

                     break;

              case EX_FLASH://外部flash

                     for(;count>0;count--)

                     {

SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,

FLASH_SECTOR_SIZE);

                            sector++;

                            buff+=FLASH_SECTOR_SIZE;

                     }

                     res=0;

                     break;

              default:

                     res=1;

       }

    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值

    if(res == 0x00)return RES_OK;   

    else return RES_ERROR;            

}

#endif /* _READONLY */

//其他表参数的获得

 //drv:磁盘编号0~9

 //ctrl:控制代码

 //*buff:发送/接收缓冲区指针

DRESULT disk_ioctl (

       BYTE drv,             /* Physical drive nmuber (0..) */

       BYTE ctrl,            /* Control code */

       void *buff             /* Buffer to send/receive control data */

)

{    

       DRESULT res;                                                                   

       if(drv==SD_CARD)//SD

       {

           switch(ctrl)

           {

                  case CTRL_SYNC:

                            SD_CS=0;

                      if(SD_WaitReady()==0)res = RES_OK;

                      else res = RES_ERROR;        

                            SD_CS=1;

                      break;    

                  case GET_SECTOR_SIZE:

                      *(WORD*)buff = 512; res = RES_OK;

                      break;    

                  case GET_BLOCK_SIZE:

                      *(WORD*)buff = 8; res = RES_OK;

                      break;    

                  case GET_SECTOR_COUNT:

                      *(DWORD*)buff = SD_GetSectorCount();res = RES_OK;

                      break;

                  default:

                      res = RES_PARERR;

                      break;

           }

       }else if(drv==EX_FLASH)   //外部FLASH 

       {

           switch(ctrl)

           {

                  case CTRL_SYNC:

                            res = RES_OK;

                      break;    

                  case GET_SECTOR_SIZE:

                      *(WORD*)buff = FLASH_SECTOR_SIZE;

                      res = RES_OK;

                      break;    

                  case GET_BLOCK_SIZE:

                      *(WORD*)buff = FLASH_BLOCK_SIZE;

                      res = RES_OK;

                      break;    

                  case GET_SECTOR_COUNT:

                      *(DWORD*)buff = FLASH_SECTOR_COUNT;

                      res = RES_OK;

                      break;

                  default:

                      res = RES_PARERR;

                      break;

           }

       }else res=RES_ERROR;//其他的不支持

    return res;

}  

//获得时间

//User defined function to give a current time to fatfs module      */

//31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */                                                                                                                                                                                                                                          

//15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */                                                                                                                                                                                                                                                

DWORD get_fattime (void)

{                         

       return 0;

}                  

//动态分配内存

void *ff_memalloc (UINT size)                 

{

       return (void*)mymalloc(SRAMIN,size);

}

//释放内存

void ff_memfree (void* mf)        

{

       myfree(SRAMIN,mf);

}

                                                                                                                                   

该函数实现了我们45.1节提到的6个函数,同时因为在ffconf.h里面设置对长文件名的支持为方法3,所以必须实现ff_memallocff_memfree这两个函数。本章,我们用FATFS管理了2个磁盘:SD卡和SPI FLASHSD卡比较好说,但是SPI FLASH,因为其扇区是4K字节大小,我们为了方便设计,强制将其扇区定义为512字节,这样带来的好处就是设计使用相对简单,坏处就是擦除次数大增,所以不要随便往SPI FLASH里面写数据,非必要最好别写,如果频繁写的话,很容易将SPI FLASH写坏。

保存diskio.c,然后打开ffconf.h,修改相关配置,并保存,此部分就不贴代码了,请大家参考光盘源码。

前面提到,我们在FATFS文件夹下还新建了一个exfuns的文件夹,该文件夹用于保存一些FATFS一些针对FATFS的扩展代码,本章,我们编写了4个文件,分别是:exfuns.cexfuns.hfattester.cfattester.h。其中exfuns.c主要定义了一些全局变量,方便FATFS的使用,同时实现了磁盘容量获取等函数。而fattester.c文件则主要是为了测试FATFS用,因为FATFS的很多函数无法直接通过USMART调用,所以我们在fattester.c里面对这些函数进行了一次再封装,使得可以通过USMART调用。这几个文件的代码,我们就不贴出来了,请大家参考光盘源码,我们将exfuns.cfattester.c加入FATFS组下,同时将exfuns文件夹加入头文件包含路径。

然后,我们打开test.c,修改main函数如下:

int main(void)

{           

      u32 total,free;

       u8 t=0;                    

      Stm32_Clock_Init(9);    //系统时钟设置

       delay_init(72);                     //延时初始化

       uart_init(72,9600);      //串口1初始化      

      exfuns_init();                //fatfs相关变量申请内存                     

       LCD_Init();                  //初始化液晶

       LED_Init();            //LED初始化

       usmart_dev.init(72);     

      mem_init(SRAMIN);     //初始化内部内存池      

      POINT_COLOR=RED;//设置字体为红色     

       LCD_ShowString(60,50,200,16,16,"WarShip STM32");   

       LCD_ShowString(60,70,200,16,16,"FATFS TEST"); 

       LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");

       LCD_ShowString(60,110,200,16,16,"Use USMART for test");   

       LCD_ShowString(60,130,200,16,16,"2012/9/18");         

       while(SD_Initialize())                                //检测SD

       {

              LCD_ShowString(60,150,200,16,16,"SD Card Error!");

              delay_ms(200);

              LCD_Fill(60,150,240,150+16,WHITE);//清除显示                   

              delay_ms(200);

              LED0=!LED0;//DS0闪烁

       }                                                          

      exfuns_init();                                            //fatfs相关变量申请内存                     

      f_mount(0,fs[0]);                                    //挂载SD

      f_mount(1,fs[1]);                                  //挂载FLASH.       

       while(exf_getfree("0",&total,&free))   //得到SD卡的总容量和剩余容量

       {

              LCD_ShowString(60,150,200,16,16,"Fatfs Error!");

              delay_ms(200);

              LCD_Fill(60,150,240,150+16,WHITE);//清除显示                   

              delay_ms(200);

              LED0=!LED0;//DS0闪烁

       }                                                                                        

      POINT_COLOR=BLUE;//设置字体为蓝色   

       LCD_ShowString(60,150,200,16,16,"FATFS OK!"); 

       LCD_ShowString(60,170,200,16,16,"SD Total Size:     MB");     

       LCD_ShowString(60,190,200,16,16,"SD  Free Size:     MB");       

      LCD_ShowNum(172,170,total>>10,5,16);          //显示SD卡总容量 MB

      LCD_ShowNum(172,190,free>>10,5,16);          //显示SD卡剩余容量 MB                    

       while(1)

       {

              t++;

              delay_ms(200);                                   

              LED0=!LED0;

       }

}

main函数里面,我们为SD卡和FLASH都注册了工作区(挂载),在初始化SD卡并显示其容量信息后,进入死循环,等待USMART测试。

最后,我们在usmart_config.c里面的usmart_nametab数组添加如下内容:

(void*)mf_mount,"u8 mf_mount(u8 drv)",

(void*)mf_open,"u8 mf_open(u8*path,u8 mode)",

(void*)mf_close,"u8 mf_close(void)",

(void*)mf_read,"u8 mf_read(u16 len)",

(void*)mf_write,"u8 mf_write(u8*dat,u16 len)",

(void*)mf_opendir,"u8 mf_opendir(u8* path)",

(void*)mf_readdir,"u8 mf_readdir(void)",

(void*)mf_scan_files,"u8 mf_scan_files(u8 * path)",

(void*)mf_showfree,"u32 mf_showfree(u8 *drv)",

(void*)mf_lseek,"u8 mf_lseek(u32 offset)",

(void*)mf_tell,"u32 mf_tell(void)",

(void*)mf_size,"u32 mf_size(void)",

(void*)mf_mkdir,"u8 mf_mkdir(u8*pname)",

(void*)mf_fmkfs,"u8 mf_fmkfs(u8 drv,u8 mode,u16 au)",

(void*)mf_unlink,"u8 mf_unlink(u8 *pname)",

(void*)mf_rename,"u8 mf_rename(u8 *oldname,u8* newname)",

(void*)mf_gets,"void mf_gets(u16 size)",

(void*)mf_putc,"u8 mf_putc(u8 c)",

(void*)mf_puts,"u8 mf_puts(u8*c)",

这些函数均是在fattester.c里面实现,通过调用这些函数,即可实现对FATFS对应API函数的测试。 至此,软件设计部分就结束了。

45.4 下载验证

在代码编译成功之后,我们通过下载代码到ALIENTEK战舰STM32开发板上,可以看到LCD显示如图45.4.1所示的内容(默认SD卡已经接上了):


45.4.1 程序运行效果图

打开串口调试助手,我们就可以串口调用前面添加的各种FATFS测试函数了,比如我们输入mf_scan_files("0:"),即可扫描SD卡根目录的所有文件,如图45.4.2所示:


45.4.2 扫描SD卡根目录所有文件

        其他函数的测试,用类似的办法即可实现。注意这里0代表SD卡,1代表SPI FLASH。另外,提醒大家,mf_unlink函数,在删除文件夹的时候,必须保证文件夹是空的,才可以正常删除,否则不能删除。

 

erweima.png

《STM32开发指南》第四十五章 FATFS实验.rar

1.24 MB, 下载次数: 3836

实验40 FATFS实验.rar

962.63 KB, 下载次数: 2843

我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

22

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2013-3-27
在线时间
0 小时
发表于 2013-4-6 17:25:48 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2013-4-16
在线时间
3 小时
发表于 2013-4-16 13:27:36 | 显示全部楼层
太感谢了!
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-5-3 08:45:26 | 显示全部楼层
原子哥,这两天看到汉字显示实验,对CC936看了一下,有点小问题,
汉字显示只需要 #define _CODE_PAGE 936
而要使用长文件名的话需要 cc936,使用它的两个转换数组
原文信息:
When enable LFN,
/  a Unicode handling functions ff_convert() and ff_wtoupper() must be added
/  to the project. */

我想请教下这里cc936到底做的什么工作啊?比如把gbk转换为unicode,或者把unicode码转为gbk?
为什么需要转换?FAT识别问题?

为什么短文件名的时候不需要转换啊?
回复 支持 反对

使用道具 举报

25

主题

683

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1351
金钱
1351
注册时间
2012-4-25
在线时间
195 小时
发表于 2013-5-3 09:39:08 | 显示全部楼层
回复【4楼】wwjdwy:
---------------------------------
fatfs 源码中有提到的自己看看就 明白了
1-1
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-5-3 10:43:24 | 显示全部楼层
回复【5楼】mygod:
---------------------------------
/  The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/  Unicode handling functions ff_convert() and ff_wtoupper() must be added
/  to the project. When enable to use heap, memory control functions
/  ff_memalloc() and ff_memfree() must be added to the project. */

我不明白为什么用到LFN时候需要cc936
回复 支持 反对

使用道具 举报

25

主题

683

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1351
金钱
1351
注册时间
2012-4-25
在线时间
195 小时
发表于 2013-5-3 10:55:27 | 显示全部楼层
回复【6楼】wwjdwy:
---------------------------------
Unicode 码表
1-1
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-5-3 11:15:30 | 显示全部楼层
回复【7楼】mygod:
---------------------------------
不用LFN时候为什么就不用啊。可否详细点告诉我啊哥们
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2013-5-30
在线时间
21 小时
发表于 2013-5-30 17:08:03 | 显示全部楼层
u16     FLASH_SECTOR_COUNT=2048*6;//6M字节,默认为W25Q64

应该是1024*6吧?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-5-30 20:35:08 | 显示全部楼层
是2048*6,不是1024!
因为sector大小是512,512*2048*6才等于6M字节
如果是1024,那就是3M字节了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2013-5-30
在线时间
21 小时
发表于 2013-5-31 10:33:13 | 显示全部楼层
回复【10楼】正点原子:
---------------------------------
谢谢原子哥的回复,以前把2048B当成2048KB了。为后续兄弟们少些弯路,稍微整理如下:
原8M 空间内 以4096B为一个物理扇区,共可分配2048个扇区
8MB=4096B*2048;

原子哥强制修改为512B为一个扇区,原来4096B扇区可拆分为4096/512=8,8M空间可分配8*2046个扇区;
8M=512*8*2048

因为文件系统只是用前6MB,所有512B为一个扇区,总共可以分6*2048个扇区
6M=512*6*2048;//FLASH_SECTOR_COUNT
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2013-5-30
在线时间
21 小时
发表于 2013-5-31 14:58:34 | 显示全部楼层
#define FLASH_BLOCK_SIZE   8     //每个BLOCK有8个扇区

1、按照物理分法:4096B一个扇区, 一个block,要么32K ,要么64k

2、根据注释理解,按楼主强制512B为一个扇区, 一个block为何是  8 呢???? block的划分原则是什么呢?

3、假如一个block 非要是8个扇区的话,那么BLOCK 大小应该是 8*512=4096B 才对啊,可宏定义中 FLASH_BLOCK_SIZE  为何是8而不是4096B呢??

还请原子哥能解答一下,小弟万分感激!!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-5-31 22:20:41 | 显示全部楼层
8个扇区,刚好是4096字节,刚好是W25Q系列的一个最少擦除单位.
愿意是想能够刚好擦除一个SECTOR(W25Q的最小擦除单位),但事实上fatfs没有这么整,所以你可以定义为其他值也无所谓.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-27 13:41:18 | 显示全部楼层


请教下 为啥不能直接通过usmart调用?
 
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-6-27 15:08:57 | 显示全部楼层
回复【14楼】charlieholy:
---------------------------------
比如要数组做为参数,那就不适合用usmart直接调用了,得封装一下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-6-27 15:09:36 | 显示全部楼层
f_read就很典型,你直接通过usmart调用,肯定不行,因为没地方存储读取到的数据.结果只能死机了...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-27 16:34:30 | 显示全部楼层
回复【16楼】正点原子:
---------------------------------
哦 这样啊= =谢谢
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-27 16:46:38 | 显示全部楼层
原子哥 这个flash 跟sd卡如何格式化 --
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-6-27 16:50:46 | 显示全部楼层
fatfs提供了函数.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2011-1-8
在线时间
2 小时
发表于 2014-7-22 21:01:24 | 显示全部楼层
回复【19楼】正点原子:
---------------------------------
原子,这款型号的FLASH不是每个Sector 4KB么?怎么是512B
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-7-22 23:47:45 | 显示全部楼层
回复【20楼】蓝杰:
---------------------------------
强制设置为512。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2011-1-8
在线时间
2 小时
发表于 2014-7-23 09:03:39 | 显示全部楼层
回复【21楼】正点原子:
---------------------------------
我f_mount成功了,但是f_open返回错误是FR_NOT_ENABLED,目标文件系统无效这个是什么原因?
这里返回的ff.c中
/* Check if the file system object is valid or not */
fs = FatFs[vol]; /* Get pointer to the file system object */
if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2011-1-8
在线时间
2 小时
发表于 2014-7-23 13:24:52 | 显示全部楼层
回复【13楼】正点原子:
---------------------------------我现在的问题是,flash驱动写是按照4096B一个扇区写的,移植的时候,SD卡是512B一个扇区。这样移植。该怎么分?
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2011-1-8
在线时间
2 小时
发表于 2014-7-23 13:25:46 | 显示全部楼层
回复【23楼】蓝杰:
---------------------------------
接上,我也是移植双磁盘
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-8-12
在线时间
1 小时
发表于 2014-11-13 18:39:00 | 显示全部楼层
回复【12楼】高阳:
---------------------------------
假如一个block 非要是8个扇区的话,那么BLOCK 大小应该是 8*512=4096B 才对啊,可宏定义中 FLASH_BLOCK_SIZE  为何是8而不是4096B呢??
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-8-12
在线时间
1 小时
发表于 2014-11-13 18:39:27 | 显示全部楼层
为什么?高阳
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-22
在线时间
0 小时
发表于 2014-12-22 10:23:13 | 显示全部楼层
这个硬件是基于什么平台,适用于ministm32的板子吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-12-22 19:41:22 | 显示全部楼层
回复【27楼】Eric_Neurosky:
---------------------------------
这个任意一个单片机都可以用,只要内存够多。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-22
在线时间
0 小时
发表于 2014-12-23 09:01:18 | 显示全部楼层
回复【28楼】正点原子:
---------------------------------
我现在把你代码加载到ministm32 有问题哦。
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2013-8-6
在线时间
2 小时
发表于 2015-1-7 10:00:25 | 显示全部楼层
---------------------------------
回复【28楼】正点原子:
---------------------------------
SD卡那个实验没有加fatfs吗? 我感觉这两章节都挺像的,我想请教的一个问题是:在动态内存里只是定义了一个FIL变量,那如果我要对sd卡根目录
下的多个文件操作的话,我是不是都可以用这一个变量。我的理解是每当我打开一个路径FIl变量就对应这个路径文件的所有信息,包括文件大小等。
不知道是不是这样子的??? 困惑已久,求教啊!!!

补充说明:假如我要长时间的写某个文件是不是要将该文件一直打开? 还有函数f_snyc() 是否具有关闭文件的作用?

在线等~~~
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2015-1-7 23:17:44 | 显示全部楼层
回复【30楼】lyricpoem1005:
---------------------------------
没加,后面的fatfs实验,才开始加入fatfs。
多个文件,必须要多个FIL变量。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2013-8-6
在线时间
2 小时
发表于 2015-1-8 11:46:31 | 显示全部楼层
回复【31楼】正点原子:
---------------------------------
对于多个文件,我是不是要申请多个FIL内存?
假如我想通过定时创建文件夹及文件来记录cpu的运行状态,该如何操作?
我目前的操作是,定义一个局部的FIL变量,每次要写数据时,打开相应的文件路径,再写数据,但是这样对堆栈影响
比较大,cpu运行比较吃力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2015-1-9 00:48:32 | 显示全部楼层
回复【32楼】lyricpoem1005:
---------------------------------
是的
软件的东西,你自己去写流程图分析即可。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

26

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2014-12-18
在线时间
13 小时
发表于 2015-1-13 16:02:32 | 显示全部楼层
回复【33楼】正点原子:
---------------------------------
disk_write 的时候需不需要擦一下?
回复 支持 反对

使用道具 举报

26

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2014-12-18
在线时间
13 小时
发表于 2015-1-13 16:05:06 | 显示全部楼层
回复【34楼】Zohey:
---------------------------------
如果写之前进行擦除、但还强制为512,有什么好的方案,原子哥
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2015-1-13 19:21:38 | 显示全部楼层
回复【34楼】Zohey:
---------------------------------
SD卡会自动处理擦除
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

26

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2014-12-18
在线时间
13 小时
发表于 2015-1-13 22:39:24 | 显示全部楼层
回复【36楼】正点原子:
---------------------------------
感谢原子哥、在研究一下源码
回复 支持 反对

使用道具 举报

7

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-2-19
在线时间
0 小时
发表于 2015-3-6 18:38:48 | 显示全部楼层
原子哥 求教
战舰实验40  FATFS实验(fatfsR0.09)  实验自带usmart 3.1这一版本中

SD用SDIO接口  从后续更新中的SDIO移植
W25X16 使用SPI1接口 只修改了引脚及flash初始化的引脚

#define SD_CARD  0 
#define EX_FLASH     1

   f_mount(0,fs[0]); 
  f_mount(1,fs[1]); 

可以正常读取设备0的容量
后无法读取到设备1的正确容量 (俩设备容量相同)


#define SD_CARD  0 
#define EX_FLASH     1

   f_mount(0,fs[1]); 
 
可以正常读取设备0的容量


#define SD_CARD  1
#define EX_FLASH     0

   f_mount(0,fs[0]); 
  f_mount(1,fs[1]); 

可以正常读取设备0的容量
后无法读取到设备1的正确容量(俩设备容量相同)


这是哪里的问题
w25x16底层都可以读ID等

单独挂载也正常
同时挂载就出问题
谁是设备1 谁出问题
挂载fmount 返回值12

求教啊  原子哥
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2015-3-6 22:37:43 | 显示全部楼层
回复【38楼】llnid:
---------------------------------
你的SDIO驱动移植好了没有啊?
我们的sdio例程就有带fatfs哦。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

18

主题

60

帖子

0

精华

初级会员

Rank: 2

积分
152
金钱
152
注册时间
2015-4-11
在线时间
0 小时
发表于 2015-5-16 06:53:02 | 显示全部楼层
dir_sdi(&picdir,picindextbl[curindex]);  //改变当前目录索引 回复【39楼】正点原子:
---------------------------------
dir_sdi(&picdir,picindextbl[curindex]);  //改变当前目录索引 原子哥,这段代码----始终编译不过怎么解决啊。。老是说没定义。。。。明明定义了,还是报警。。。
while{努力};
回复 支持 反对

使用道具 举报

2

主题

12

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2014-12-25
在线时间
0 小时
发表于 2015-6-9 13:43:46 | 显示全部楼层
拼命的学习中
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2016-2-17
在线时间
0 小时
发表于 2016-2-17 16:34:39 | 显示全部楼层
原子哥  我用的W25X64 单个扇区定义为什么还是512字节呢 ?#define FLASH_SECTOR_SIZE 512           @正点原子
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2016-2-17
在线时间
0 小时
发表于 2016-2-17 16:34:57 | 显示全部楼层
maclao 发表于 2016-2-17 16:34
原子哥  我用的W25X64 单个扇区定义为什么还是512字节呢 ?#define FLASH_SECTOR_SIZE 512           @正点 ...

不对  是你
回复 支持 反对

使用道具 举报

5

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2017-4-24
在线时间
7 小时
发表于 2017-5-3 11:14:00 | 显示全部楼层
原子哥你好 我现在想要把两个源代码合并(照相机实验的和ESP8266的)发现两个代码的exfuns.c文件不太一样 请问可以直接取其中的一个 还是有什么地方需要修改的 萌新刚学STM32不是很懂 希望指教 感激不!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-8-21 17:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表