X
تبلیغات
رایتل

آذر میکرو ( دنیای میکروکنترلرها )

برنامه نویس میکروکنترل ها

آموزش استفاده از FatFs در پروژه ها

اخرین ورژن این لایبرری FatFs R0.09 هست که میتونید از سایت این رفیق خوش ذوق ژاپنی مون دانلود کنید

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


که دارای کلا 32 تابع اصلی میباشد توی سایتش اگر دقت کنید توابع رو کاملا توضیح داده ولی اینجا توضیحات فارسی رو که من خودم ترجمه ویا از سطح اینترنت جمع آوری کردم قرار خواهم داد

 

 

برنامه ساده به عنوان رفرنس
ابن برنامه که فایل هگز و سورس برنامه و شماتیکش همه در این فایل فشرده هست یک فایل TXT به نام test.txt در داخل مموری ایجاد میکنه و داخل این فایل جمله Hello World رو مینویسه .  
در ضمن در این برنامه از لایبرری خود کدویژن استفاده نشده و فایل های مورد نیاز پروژه همه درکنار برنامه موجود هست!!!!!

در توابع بعضی جاها صحبت درایو هست شاید سوالی که به وجود بیاد اینکه مگر ما توی مموری درایو داریم باید بگم که این توابع کلی بوده و میتونید ازشون حتی در ارتباط با رید یا رایت یه هارد دیسک IDE یا کارت های حافظه CF استفاده کنید که در این صورت این قابلیت خیلی به درد میخوره و یا اینکه شما چند مموری داشته باشید و ....

 تابع disk_timerproc(); چیه که هر 10 میلی ثانیه باید فراخونی بشه ؟
این تابع وجود یا عدم وجود مموری و همچنین قفل بودن اون رو چک میکنه البته اگه پینهای مربوطه استفاده شده باشن

در اکثر موارد که دوستان نمیتونن از این کتابخونه جواب بگیرن دلیلش اینه که دو تا پین  CD یا (card detect) و WP یا (write   protected)   رو جدی نمیگیرند البته در برنامه چند تا متغیر (برای محاسبه زمان timeout  هم نیاز هست که در این تابع مقدارشون افزایش پیدا میکنه منطق فعال بودن این دو تا پایه صفره باید به زمین متصل بشن تا مدار عملکرد عادی داشته باشه
SPI در فایل mmc.c کانفیگ میشه و نیازی به فراخوانی توابع SPI نیست

file = malloc(sizeof(FIL));
 if (res || f_tell(file) != PRE_SIZE) 

این malloc  که یکی از توابع استاندارد سی هست 
malloc
  به اندازه ای که مشخص می کنید حافظه RAM بهتون تحویل میده، برای مواردی کاربرد داره که حافظه مورد نیاز بصورت ثابت مشخص نیست. پارامتری که بهش
تحویل می دهید طول حافظه بر حسب بایته و مقداری که بر می گردونه آدرس شروع اون حافظه ای است که تخصیص داده شده.
اما تایع f_tell اخرین ادرس خوانده یا نوشته شده فایل رو برمیگردونه


 چطور میشه توی فایل txt روی sd داده ها رو خط به خط نوشت یعنی هر بارتو یک خط جدید نه قطاری پشت سرهم........
کافیه در انتهای هر سطر کارکتر های
  r  /n/  یا کد اسکی 10 و 13 رو اظافه کنید همین
    10
یعنی سطر جدید 
    13
یعنی اینتر

حجم رم کم میداد ؟
اگر از متغیرهای محلی و با حجم بافر پایین مثل 256 استفاده کنید این مشکل رو نخواهید داشت درسته که سرعت پایین میاد ولی برای این
mega16  یا mega32 ما رم کم نخواهید اورد 
درضمن میتونید از فایل ffconf.h مقدار  (   ( #define   _FS_TINY      0 رو به یک تغییر بدین تا مشکل شما حل بشه 
یا اگر نیازی به نوشتن ندارین و فقط قراره از مموری خونده بشه مقدار(   ( #define _FS_READONLY   0 رو یک کنید که نه تنها در حجم رم بلکه در حجم فلش تغییرات ملموسی مشاهده خواهید کرد

f_mount(0, NULL);            //Unregister work area

این دستور یعنی از درایو 0 خارج شو یا ببندش

 

کلاک واحد spi حداقل و حداکثر  چقدر بایستی باشه؟
دوست من هرچقدر که میتونی بالاتر قرار بده تا سرعت رید و رایت بالاتری داشته باشی

سرعت SD یا MMC خیلی بالاتر از این هاست و میکروی ما خیلی محدوده البته بستگی به نوع و کلاس مموری داره ولی باز بیشتر از سرعت AVR هست حتی اگر اورکلاکش کرده باشید


 کله فایلهای مجموعه FatFs به قول خود جناب ChaN به قرار زیر هست

  ffconf.h        Configuration file for FatFs module.
  ff.h                Common include file for FatFs and application module.
  ff.c                FatFs module.
  diskio.h        Common include file for FatFs and disk I/O module.
  integer.h       Alternative type definitions for integer variables.
  option           Optional external functions.


چرا یک سری نوع جدید متغیر تعریف کرده است ؟  (
 مثل هدر integer )
این تعاریف بیشتر سلیقه ای هست و برنامه نویس برای این که از ترکیبای طولانی و بی مصما استفاده نکنه و به خوانایی برنامه کمک کنه ، میاد برای اون نوع داده یه اسم میزاره حالا اگه با این ها مشکل دارید میتونید تو هر جای برنامه که اینها رو دید برشون گردونید به حالت استانداردشون
.


میشه یکی در مورد فایل های توی پوشه
option در این مجموعه ی FATFS توضیح بده؟
توابع دیگه زیاد مهم نیستن یعنی اگر کسی بتونه با همین توابعی که توضیحاتشون داده شده به خوبی کار بکنه یعنی اینکه گوشی اومده دستش و یه راحتی میتونه با توابع دیگه (البته به ندرت ازشون استفاده میشه) بدون مشکل کار کنه ولی اگر بازم مشکلی داشته باشید بفرمایید تا بیشتر توضیح بدم

البته باید بگم که خود من هم زیاد با این توابه کار نکردم از اجمله این توابع میشه به 
تابع f_fdisk که معلومه دیگه همون دستور FDISK کامپیوتره یا
تابع f_mkfs که باز معلومه فایل های سیستمی درایو رو ایجاد میکنه یا
تابع f_rename هست که باز معلومه اسم فایل رو میشه باهاش تغییر داد یا فایل یا پوشرو جابجا کرد یا
تابع f_size که سایز فایل رو برمیگردونه و ......

اما در مورد پوشه option  باید بگم این فایل ها کدپیج ها مختلف هر زبان رو به برنامه اضافه میکنه مثلا اگر قراره شما فایلی با نامی به جز کاراکترهای استاندارد اسکی ایجاد کنید یا فایل رو ویرایش کنید به طوری که از کاراکترهایی به جز کاراکترهای اسکی در ویرایش فایل استفاده کنید باید کدپیج های اون زبان رو به لایبرری اضافه کنید که در این پوشه فایلهایی برای اضافه کردن این کد پیجها قرارداده شده است

برای انتخاب کد پیجهای مختلف باید از فایل ffconf.h مقدار دیفاین _CODE_PAGE رو به نصبت توضیحات زیرش تغییر بدید مثلا اگر قراره به زبان فارسی (عربی) کار بشه باید این دیفاین رو برابر 720 بگیرید 

   932  - Japanese Shift-JIS (DBCS, OEM, Windows)
   936  - Simplified Chinese GBK (DBCS, OEM, Windows)
   949  - Korean (DBCS, OEM, Windows)
   950  - Traditional Chinese Big5 (DBCS, OEM, Windows)
   1250 - Central Europe (Windows)
   1251 - Cyrillic (Windows)
   1252 - Latin 1 (Windows)
   1253 - Greek (Windows)
   1254 - Turkish (Windows)
   1255 - Hebrew (Windows)
   1256 - Arabic (Windows)
   1257 - Baltic (Windows)
   1258 - Vietnam (OEM, Windows)
   437  - U.S. (OEM)  720  - Arabic (OEM)
   737  - Greek (OEM)
   775  - Baltic (OEM)
   850  - Multilingual Latin 1 (OEM)
   858  - Multilingual Latin 1 + Euro (OEM)
   852  - Latin 2 (OEM)
   855  - Cyrillic (OEM)
   866  - Russian (OEM)
   857  - Turkish (OEM)
   862  - Hebrew (OEM)
   874  - Thai (OEM, Windows)
    1  - ASCII only (Valid for non LFN cfg.)


حالا میخوام در ادامه فایل بنویسم نه از ابتدا که دیتا های فایل از بین بره ؟
برای اینکار باید بعد از بازکردن فایل با دستور
f_lseek بریم به اخرین بایت فایل واز انجا شروع به نوشتن کنیم 

چطور میشه یکی از خطهای اول همین داده های یکسان رو پاک کرد؟
بهتره در ابتدای هر سطرتون یک کاراکتر اضافی در نظر بگیرین تا مشخص کنه که آیا این سطر حذف شده یا نه. در هنگام ثبت هم از سطر هایی استفاده کنین که قبلا حذف شده. برای مدیریت این کار هم میتونین براحتی با یک لیست پیوندی مبتنی بر فایل و یک هدر برای فایل این مورد رو انجام بدین
.


دوستان با
avr میشه رم رو فرمت کرد؟
اگر مد
  USE_MKFS_  فعال باشه در فایل ff.c به روتین زیر مراجعه کنید و در فایل main.c مثال آقای ChaN هم به قسمت File و    Create file system   یا همون fm مراجعه کنید. ( البته در ff.c جزئیات واضح تر معلومه! (

FRESULT f_mkfs (
   BYTE drv,      /* Logical drive number */
   BYTE sfd,      /* Partitioning rule 0:FDISK, 1:SFD */
   UINT au         /* Allocation unit size [bytes] */
)

چطور میشه فهمید به انتهای فایل رسیدیم ؟
کار ساده ای هست
 در توابع خوندن و نوشتن چهارمین ورودی تابع که میشه
4
  اشاره گر به متغیری که قراره تعداد بایت نوشته شده در اون قرار بگیره ByteRead و باید قبل از تابع از نوع UINT تعریف شده باشه
برای همین کار هست
در ضمن برای این کار به رم بالایی نیاز نیست شما میتونید با یه بافر 256 بایتی یا کمتر هم همین کار رو انجام بدی درسته راه درستی نیست و ممکن هست زمان زیادی طول بکشه ولی در برخی از کارها که نیاز داریم حتما ترتیب رو حفظ کنیم لازمه این راهی هم که اقای اقازاده پیشنهاد دادند خوبه و خیلی میتونه به درد بخوره 
اما بهترین راه ، استفاده از فرمت خاص هست و فقط با نوشتن یک  if  ساده در توابع خوندن دیتا مشکل رو حل میکنه

مموری ها چه SD باشه و چه MMC با 3.3 ولت کار میکنه اگر این ولتاژ بیشتر باشه یا یکی از پینهای ورودی مثل DI یا CS یا CLK بیشتر از 3.3 ولت باشه موجب کارکرد نادرستش شده و ارتباط برقرار نخواهد شد 
ولی راه حل این موضوع ساده است راه های مختلفی داره که من دو موردشو توضیح میدم
 
 _ 1
راهتترین راه اینه که تغذیه میکرو رو 3.3 بکنبم و به جای رگلاتور 5 ولت از یه رگلاتور 3.3 استفاده کنیم 
 - 2
میکروی ما 5 ولته و ما نمیتونیم ولتاژشو بیایم پایین  حالا برای تغذیه میتونیم از یه رگلاتور 3.3 استفاده کنیم که نمیسرفه ولی من یه راه دیگه دارم و با 2 تا دیود فقط 1 N4148 سری شده به جای رگلا تور استفاده میکنیم یعنی 5 ولت رو میدیم به دیود اول و بعد یه دیود دوم و بعد به مموری حالا برای اون سه تا دیتا باید با  یه تقسیم مقاومت ولتاژ رو به 3.3 برسونیم که برای این کار به سه تا 1.5 کیلو و سه تا 1 کیلو مقاومت نیاز داریم که چون ساده هست دیگه توضیح نمیدم


من میخوام با سریال از طریقه کامپیوتر یه فایل با تعداد بایت نامشخصو بریزم تو میکرو و اونجا تو
MMC ذخیره کنم؟
اول باید در وقفه اطلاعات رو در یک بافر مثل یک بافر حلقوی ذخیره کنین بعد در سیکل اصلی برنامه اون اطلاعات رو در فایلتون بریزین
.
وقفه برای اطلاع وقوع شرایط خاصی به برنامه هست. عمل سنگینی رو نباید در وقفه انجام داد.

 در همه فایل ها زمان modify و ... بعد هر عملیات ثبت میشه؟ درسته؟ در این کتابخانه هم این قابلیت وجود داره و در صورت بله چطور این کار صورت میگیره؟
حتما این قابلیت باید وجود داشته باشه در غیر این صورت که نوشتن و ایجاد کردن یک فایل مشکل خواهد داشت

در این توابع این امکان با یک تابع به نام get_fattime صورت میگیره که کاربر در صورت فعال کردن امکان رایت باید بنویستش
به این صورت که خروجی این تابع یه عدد 32 بیت باشه که اطلاعات RTC به این صورت درون این 32 بیت قرار میگیرند

   bit4:0         
ثانیه تقسیم بر دو است که مقدارش باید عددی از 0 تا 29 باشه
   bit10:5       
دقیقه است که باید عددی بین 0 تا 59 باشه
   bit15:11     
ساعته که باید عددی بین 0 تا 23 باشه
   bit20:16     
روزه که باید عددی بین 1 تا 31 باشه
   bit24:21     
ماهه که باید عددی بین 1 تا 12 باشه
bit31:25     
   هم ساله که باید عددی بین 0 تا 127 باشه ابتدا از سال 1980 یعنی برای سال 2011 باید عدد 31 رو بهش بدین

یعنی یه چیزی مثل این مثال

DWORD get_fattime (void)
                {
                RTC rtc;
                rtc_gettime(&rtc);
                return     ((DWORD)(rtc.year - 1980) << 25)
                                                | ((DWORD)rtc.month << 21)
                                                | ((DWORD)rtc.mday << 16)
                                                | ((DWORD)rtc.hour << 11)
                                                | ((DWORD)rtc.min << 5)
                                                | ((DWORD)rtc.sec >> 1);
                }


دستور
die چیکار میکنه ؟
  die()
یه چیز تو مایه های return() خودمونه که در java وجود داره، البته یه خورده پیشرفته تره، که میتونه یه کد خطا و یا حتی یک آبجکت رو پس از بروز خطا در اجرای روند عادی برنامه برگردونه دوستانی که چندتا زبان برنامه نویسی بلدند میدونند که توی بعضی از زبانهای برنامه نویسی برخی ار توابع و دستورات که خیلی به درد بخورند توی برخی از زبانها وجود ندارن و مخصوص اون زبان خاص میشوند  لذا وقتی کسی مثل اقای چان میاد یه برنامه را مینویسه و یه جاش قراره کاری مشابه یه دستور یا تابعی که در خود سی وجود نداره انجام بده میاد به نام همون تابع یه تابع مینویسه

مثل این تابع  die

void die (                             // Stop with dying message
                FRESULT  rc         // FatFs return value 
                )
                {
                printf("Failed with rc=%u.\n", rc);
                for (;;) ;
                }

حالا کارش چی هست ؟؟ 
این تابع خطای به وجود اومده رو  از طریق USART یا همون سریال خودمون ارسال میکنه و توی یه لوپ نا محدود میفته همین !!!

لایبرری ff همان FAT File System Module بوده و تقریبا کاملترین لایبرری فت 12 و 16 و 32 هست
لایبرری pff هم یعنی Petit FAT File System Module که ساده تر شده لایبرری ff هست با امکانات کمتر و برای استفاده در حافظه های کوچکتر و با کارایی ساده تر
به طور مثال شما وقتی دارین با Mega8 یه WAV Player میسازید نمیتونید از ff استفاده کنید چون دیگه جایی برای نوشتن کدهای دیگه نخواهید داشت پس اینجا pff به کمک میاد
اینجا دونوع
wave player با میکروی Mega16 هست که در هر دو مورد از این لایبرری pff استفاده شده

http://s1.picofile.com/file/7209315913/WAV_Player.rar.html

توابع pff برای کدویژن البته با توابع SD یا  MMC

برای استفاده توی برنامتون قبلش اینهارو دیفاین کنید

#define  set(port,pin)          port |= (1<<pin)
#define  reset(port,pin)        port &= ~(1<<pin)
#define  _BV(bit)               (1 << (bit))

بعد به ترتیب فایل های mmc.c و بعد pff.c رو انکلود کنید
در این توابع بنده از میکروی mega16 استفاده کردم ولی در صورت نیاز به میکروهای دیگه میتونید دیفاین پینهای مموری رو توی فایل     mmc.h   تغییر بدید

http://s2.picofile.com/file/7162094515/pff.rar.html



 توضیح در مورد این متغیر ها و استراکچرها

توی این توابع این دوست خوب چینیمون اومده و توی فایل integer.h  متغیر ها رو برای راحتی کار و تایپ سریع نامگزاری مجدد کرده

/* These types must be 16-bit, 32-bit or larger integer */
typedef int                   INT;
typedef unsigned int    UINT;

/* These types must be 8-bit integer */
typedef char                CHAR;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;

/* These types must be 16-bit integer */
typedef short               SHORT;
typedef unsigned short            USHORT;
typedef unsigned short            WORD;
typedef unsigned short            WCHAR;

/* These types must be 32-bit integer */
typedef long                LONG;
typedef unsigned long ULONG;
typedef unsigned long DWORD;


در فایل ff.h 5 تا استراکچر هست که  تعریف شده و یکی یکی یه توضیح مختصر میدم
ولی چون متغیر ها خوب نامگزاری شده و یه توضیح مختصر جلوی هرکدوم داره و معلومه برای چیه , پس من دیگه توضیح بیشتر نمیدم ولی اگر لازم بود بپرسید
استراکچر اول FATFS هست که اطلا عات فت درونش قرار میگیره
برای دسترسی به هر کدام از متغیر ها و مقادیر داخلی اونها باید بعد از نام استراکچر که تعریف کردید با قرار دادن نقطه (.)و نام متغیر داخلی استراکچر رو قرار بدید که میتونه یکی از متغیر های زیر باشه 

/* File system object structure (FATFS) */

typedef struct {
            BYTE  fs_type;                       /* FAT sub-type (0:Not mounted) */
            BYTE  drv;                              /* Physical drive number */
            BYTE  csize;                           /* Sectors per cluster (1,2,4...128) */
            BYTE  n_fats;                         /* Number of FAT copies (1,2) */
            BYTE  wflag;                          /* win[] dirty flag (1:must be written back) */
            BYTE  fsi_flag;                       /* fsinfo dirty flag (1:must be written back) */
            WORD id;                                            /* File system mount ID */
            WORD n_rootdir;                     /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
            WORD ssize;                            /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
            _SYNC_t         sobj;                             /* Identifier of sync object */
#endif
#if !_FS_READONLY
            DWORD          last_clust;                     /* Last allocated cluster */
            DWORD          free_clust;                    /* Number of free clusters */
            DWORD          fsi_sector;                    /* fsinfo sector (FAT32) */
#endif
#if _FS_RPATH
            DWORD          cdir;                             /* Current directory start cluster (0:root) */
#endif
            DWORD          n_fatent;                      /* Number of FAT entries (= number of clusters + 2) */
            DWORD          fsize;                            /* Sectors per FAT */
            DWORD          fatbase;                        /* FAT start sector */
            DWORD          dirbase;                        /* Root directory start sector (FAT32:Cluster#) */
            DWORD          database;                      /* Data start sector */
            DWORD          winsect;                       /* Current sector appearing in the win[] */
            BYTE  win[_MAX_SS];                      /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;


استراکچر بعدی FIL هست که اطلا عات فایل درونش قرار میگیره و ساختارش این شکلیه

/* File object structure (FIL) */

typedef struct {
            FATFS*           fs;                                /* Pointer to the owner file system object */
            WORD id;                                             /* Owner file system mount ID */
            BYTE  flag;                             /* File status flags */
            BYTE  pad1;
            DWORD          fptr;                             /* File read/write pointer (0 on file open) */
            DWORD          fsize;                            /* File size */
            DWORD          sclust;                          /* File start cluster (0 when fsize==0) */
            DWORD          clust;                            /* Current cluster */
            DWORD          dsect;                           /* Current data sector */
#if !_FS_READONLY
            DWORD          dir_sect;                       /* Sector containing the directory entry */
            BYTE*            dir_ptr;             /* Ponter to the directory entry in the window */
#endif
#if _USE_FASTSEEK
            DWORD*        cltbl;                            /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
            UINT   lockid;                         /* File lock ID (index of file semaphore table) */
#endif
#if !_FS_TINY
            BYTE  buf[_MAX_SS];                      /* File data read/write buffer */
#endif
} FIL;


استراکچر بعدی DIR هست که اطلاعات پوشه درونش هست و ساختارش این شکلیه


/* Directory object structure (DIR) */

typedef struct {
            FATFS*           fs;                                /* Pointer to the owner file system object */
            WORD id;                                /* Owner file system mount ID */
            WORD index;                          /* Current read/write index number */
            DWORD          sclust;                          /* Table start cluster (0:Root dir) */
            DWORD          clust;                            /* Current cluster */
            DWORD          sect;                             /* Current sector */
            BYTE*            dir;                               /* Pointer to the current SFN entry in the win[] */
            BYTE*            fn;                                /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _USE_LFN
            WCHAR*        lfn;                               /* Pointer to the LFN working buffer */
            WORD lfn_idx;                        /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;


استراکچر بعدی FILINFO هست که خصوصیات فایل درونش هست وساختارش اینطوریه


/* File status structure (FILINFO) */

typedef struct {
            DWORD fsize;                                    /* File size */
            WORD    fdate;                                    /* Last modified date */
            WORD   ftime;                         /* Last modified time */
            BYTE  fattrib;              /* Attribute */
            TCHAR           fname[13];                   /* Short file name (8.3 format) */
#if _USE_LFN
            TCHAR*         lfname;                                    /* Pointer to the LFN buffer */
            UINT   lfsize;                           /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;


و بعدی که استراکچر نیست ولی ساختار شمارشی یا انیوم هست  هم FRESULT نام داره که خطا های برگشتی توابع درونشه و به این صورته


/* File function return code (FRESULT) */

typedef enum {
            FR_OK = 0,                             /* (0) Succeeded */
            FR_DISK_ERR,                                   /* (1) A hard error occured 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,                        /* (6) The path name format is invalid */
            FR_DENIED,                           /* (7) Acces denied due to prohibited access or directory full */
            FR_EXIST,                              /* (8) Acces denied due to prohibited access */
            FR_INVALID_OBJECT,                     /* (9) The file/directory object is invalid */
            FR_WRITE_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,                       /* (13) There is no valid FAT volume */
            FR_MKFS_ABORTED,                       /* (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 shareing policy */
            FR_NOT_ENOUGH_CORE,               /* (17) LFN working buffer could not be allocated */
            FR_TOO_MANY_OPEN_FILES,                    /* (18) Number of open files > _FS_SHARE */
            FR_INVALID_PARAMETER             /* (19) Given parameter is invalid */
} FRESULT;



 

 

فایل ffconf.h

این فایل در واقع بخش کنترل تنظیمات این توابع هست

 فعال و یا غیر فعال کردن امکانات بواسطه دست بردن درون تابع کتابخانه ای ffcong.h صورت می گیرد و یا اینکه در طول برنامه ی جاری ، بسته به خواسته مان آنرا  تنظیم می کنیم؟

طور مثال شما میخواید با یک MEGA16 یک WAV Player  درست کنید در اینجا نیازی به نوشتن نیست و فقط امکانات خواندن کفایت میکند پس خیلی از این توابع به درد ما نمیخوره وچون نیاز به فلش داریم تا برنامه های دیگمون رو بنویسیم بنا بر این میایم 
FS_TINY_
رو یک میکنیم 
FS_READONLY_
رو یک میکنیم
FS_MINIMIZE_
رو هم یک میکنیم (اگر نیاز به باز کردن پوشه ها و خوندنشون هم نباشه میتونیم 2 کنیم)
اگر قراره نام کامل فایل رو مثلا توی LCD نشون بدیم USE_LFN_ رو هم یک میکنیم
و MAX_LFN_ رو هم برای ماکزیمم کاراکتر نام فایلمون تنظیم میکنیم
و به قسمت های بعدی دست نمیزنیم و چیزهای دیگه رو فعال نمیکنیم چون نیازی بهشون نداریم

این تغییرات رو قبل از کامپایل میدیم و تغییر این امکانات در داخل برنامه امکانش نیست 
اصلا یه سوال منظور از دیفاین چیه؟ مگه میشه داخل برنامه دیفاین رو تغییر داد ؟ مگه متغیر هست که بشه تغییرش داد؟
فقط به کامپایلر میگه کجا ها رو کامپایل کن کجارو هم نمیخواد کامپایل کنی یا مقدار فلان چیزها این عدد یا دستورهاست اون هم فقط جایگزین میکنه همین


این جا میتونید امکانات این توابع رو فعال یا غیر فعال کنید که بعضی جاهای مهمشو توضیح میدم

#define            _FS_TINY                   0          // 0:Normal or 1:Tiny 

برای کم کردن میزان بافر استفاده میشه و برای میکروهایی که رم پایینی دارند به درد میخوره مثل همین mega32 یا mega16

#define _FS_READONLY      0          // 0:Read/Write or 1:Read only

با یک کردنش میتونید حالت فقط خواندنی به درایوتون بدین موجب کاهش رم و حجم فلش میشه ( دیگه هرگونه نوشتن غیر فعال خواهد شد(

#define _FS_MINIMIZE          0          // 0 to 3

بعضی از توابع رو که نیاز نداریم حذف میکنه موجب پایین اومدن حجم فلش میشه چهار حالت داره
 0 :
تابع کامل 
 1 :
توابع  f_stat، f_getfree، f_unlink، f_mkdir، f_chmod، f_truncate و f_rename حذف میشه
 2 :
علاوه بر توابع یک f_opendir و f_readdir  هم حذف می شه
 3 :
علاوه بر توابع یک و دو f_lseek  هم حذف می شه

#define            _USE_STRFUNC        0          // 0:Disable or 1-2:Enable

برای فعال کردن توابع رشته ای به کار میره

#define            _USE_MKFS               0          // 0:Disable or 1:Enable

برای فعال کردن تابع f_mkfs هست در صورتی که  FS_READONLY_ صفر باشه

#define            _USE_FORWARD      0          // 0:Disable or 1:Enable

برای فعال کردن تابع f_forward هست در صورتی که FS_TINY_ یک باشه

#define            _USE_FASTSEEK       0          // 0:Disable or 1:Enable

برای بالا بردن سرعت SEEK به کار میره 

#define _CODE_PAGE           437 

انتخاب کد پیج فونت برای فایل هست که برای 10 12 تا زبان مختلف نوشته شده در صورت انتخاب نادرست امکان خراب شدن فایل های ادیت یا ایجاد شده وجود دارد

#define            _USE_LFN      0                      // 0 to 3   

حالت های مختلف LFN رو تنظیم میکنه این LFN همان مخفف Large File Name هست که برای استفاده از نام کامل فایل به درد میخوره که 4 حالت داره
  : غیر فعال کردن ویژگی LFN و  MAX_LFN_ و LFN_UNICODE_ موثر نخواهد بود در این حالت نام فایل از سیستم 6.3 استفاده میکنه 6 کاراکتر نام و یک دات(.) و 3 پسوند فایل 
1
  : فعال کردن LFN با بافر استاتیک بر روی BSS
 2
: فعال کردن LFN با بافر پویا یا داینامیک بر روی STACK
  :  3
فعال کردن LFN با بافر پویا یا داینامیک بر روی HEAP

#define            _MAX_LFN    255                  // Maximum LFN length to handle (12 to 255) 

ماکزیمم کاراکتر LFN رو تنظیم میکنه که میتونه از 12 کاراکتر تا 255 کارکتر باشه

#define            _LFN_UNICODE        0          // 0:ANSI/OEM or 1:Unicode 

ابن هم که تونی کد رو فعال میکنه البته اگر LFN فعال باشه 

#define _FS_RPATH               0          // 0 to 2 

 :  0 غیر فعال کردن ویژگی های مسیر و حذف توابع مربوط بهش
1
  : مسیر های نسبی را فعال میکند و توابع () f_chdrive  و ()f_chdir  در دسترس هستند
 :  2
علاوه بر توابع 1 () f_getcwd  هم در دسترس خواهد بود

#define _VOLUMES   1 

تعریف تعداد درایو 

#define            _MAX_SS                   512                  // 512, 1024, 2048 or 4096 

انتخاب میزان سایز سکتور
برای مموری و هارد دیسک از 512 استفاده بشه 
برای فلاپی درایو و دیسکهای نوری که دارای سکتورهای بزرگتی هستند مقدار های بالا تر

#define            _MULTI_PARTITION 0          // 0:Single partition, 1/2:Enable multiple partition 

0  برای فقط یک پارتیشن و 1 برای مولتی پارتیشن

#define            _USE_ERASE 0          // 0:Disable or 1:Enable 

برای فعال کردن بخش از ویژگی های پاک کردن به درد میخوره

 

 

 

 

تابع اول ( f_mount )

 

FRESULT f_mount (
  BYTE  Drive,                                       /* Logical drive number */
  FATFS*  FileSystemObject                 /* Pointer to the work area */
);

;( تعریف اشاره گر درایو - شماره درایو ) f_mount



حالا این تابع چیه و به چه درد میخوره؟

برای تعریف و یا پاک کردن پایه اطلاعات یا همان میز کار یا درایو در ماژول فت هست قبل از خوندن اطلاعات از یه درایو باید اون درایو رو در فت تعریف کرد. اگر درایو دیگری انتخاب بشه اون قبلیه پاک شده و این جدیده جایگزین خواهد شد مثل اینکه شما بری از My Computer یکی از درایو هارو انتخاب کنید و توش رو باز کنید

 تازمانی که شما با همان درایو کار دارید نیاز به تعریف یا فراخوانی مجدد نخواهد بود و فقط یک بار کفایت میکند.

شما توی مموری نمیتونی بیشتر از یه درایو داشته باشین مگر اینکه چند تا مموری داشته باشی
 عددی که به درایو اختصاص می دهیم از 0  تا 9 است آیا تفاوتی ندارد زمانی که یک مموری داریم از کدامیک از این 10 عدد استفاده کنیم؟
در صورتی که مولتی درایو فعال نباشه باید این عدد 0 باشه

کجا باید ازش استفاده کرد ؟
کلا قبل از هرنوع خوندن نوشتن و ..... باید این دستور استفاده بشه .

ورودی و خروجی هاش؟
دوتا ورودی داره
 _ 1
اشاره گر درایو FileSystemObject  یه اشاره گر به متغیری که باید قبل از این تابه از نوع استراکچر FATFS تعریف شده باشه
 _ 2
شماره درایو مورد نظر که یک عددی از 0 تا 9 میتونه باشه و یه خروجی خطا داره که دو حالت داره
                                       1- FR_OK
یعنی بدون مشکل انجام گرفت
              2- FR_INVALID_DRIVE
یعنی درایو مورد نظر موجود نبود

نکته: منظور از استراکچر اینه که یه تعداد متغیر در یک متغیر مثلا وقتی متغیری از نوع FATFS تعریف میکنید در واقع ایم متغیر ها ار تعریف کردید لذا دقت کنید چون به رم بالایی نیاز خواهید داشت

 استراکچر (معنی سادش میشه یه متغیر که توش یه تعداد متغیر از پیش تعریف شده هست) اون کسی که تابع رو مینویسه برای سهولت کار این استراکچر رو طراحی میکنه تا فقط با تعریف این متغیر به جای چند متغیر و فقط کار کردن با همین یک متغیر دسترسی راهتتری به همه متغیر های تعریف شده در استراکچر داشته باشه حالا کسی که از تابع استفاده میکنه میاد یه متغیر رو تعریف میکنه از نوع نامی که به استراکچر داده شده یعنی مثلا در char x ما متغیر x رو تعریف کردیم از نوع char ولی در استراکچر مینویسیم FATFS fs یعنی متغیر fs رو تعریف کردیم از نوع FATFS که میشه حدود 22 تا متغیر از انواع مختلف . این دوست ما برای اینکه اون استراکچر رو انتقال ندیم ادرسشو انتقال داده و از اشاره گر استفاده کرده

typedef struct {
    BYTE    fs_type;             /* FAT sub-type (0:Not mounted) */
    BYTE    drv;                    /* Physical drive number */
    BYTE    csize;                  /* Sectors per cluster (1,2,4...128) */
    BYTE    n_fats;                /* Number of FAT copies (1,2) */
    BYTE    wflag;                 /* win[] dirty flag */
    BYTE    fsi_flag;              /* fsinfo dirty flag */
    WORD    id;                     /* File system mount ID */
    WORD    n_rootdir;         /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
    WORD    ssize;                /* Sector size (512,1024,2048,4096) */
#endif
#if _FS_REENTRANT
    _SYNC_t sobj;                 /* Identifier of sync object */
#endif


#if !_FS_READONLY
    DWORD   last_clust;       /* Last allocated cluster */
    DWORD   free_clust;       /* Number of free clusters */
    DWORD   fsi_sector;       /* fsinfo sector (FAT32) */
#endif
#if _FS_RPATH
    DWORD   cdir;                /* Current directory cluster (0:root) */
#endif
    DWORD   n_fatent;          /* Number of FAT entries (= number of clusters +

2) */
    DWORD   fsize;        /* Sectors per FAT */
    DWORD   fatbase;      /* FAT area start sector */
    DWORD   dirbase;      /* Root directory area start sector (FAT32: cluster#) */
    DWORD   database;     /* Data area start sector */
    DWORD   winsect;      /* Current sector appearing in the win[] */
    BYTE    win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;

 

تابع دوم   () f_open

 

FRESULT f_open (
  FIL* FileObject,                        /* Pointer to the blank file object structure */
  const TCHAR* FileName,       /* Pointer to the file neme */
  BYTE ModeFlags                     /* Mode flags */
);


( نوع دسترسی , نام فایل , اشاره گر فایل ) f_open

کار این تابع باز کردن هر نوع تابعی هست ( البته خوندن اطلاعات فایل با باز کردن فرق میکنه )

حالا این تابع چیه به چه درد میخوره؟
برای ایجاد یا باز کردن فایل به کار میره

کجا باید ازش استفاده کرد؟
قبل از خوندن یا نوشتن فایل باید اون فایل حتما باز باشه یا ایجاد شده باشه و یا ایجاد شده و باز بشه

چند تا میشه فایل باز کرد؟
شدیدا به رم شما ارتباط داره هر فایل در حالت عادی حدود 100 بایت از رم رو اشغال میکنه البته بستگی به کانفیگ هم داره

این مقدار بدون مقدار بافر دیتا هست و میشه از بافر به صورت مشترک استفاده کرد 
این نکته هم یادتون باشه خیلی کم پیش میاد که نیاز به باز بودن بیش از 2 فایل باشه

اگر دو تا فایل رو باز کنیم ، موقع خواندن کدومشون خونده میشه ؟ می تونیم انتخاب کنیم که کدوم خونده بشه؟ یه سوال دیگه اینکه اگر یک فایل رو نصفه بخونیم از کجا بفهمیم که تا کجا خوندیم و بریم بقیشو بخونیم؟

اگر قرار باشه 2 یا چند تا فایل باز بشه باید دو یا چند FileObject از نوع استراکچر FIL تعریف بشه و با هرکدوم میتونید اون فایل رو بخونبد و بنویسید
در مورد ادرسش هم باید بگم تازمانی که فایل رو نبستید یا با همون FileObject فایل دیگه ای رو باز نکرده باشید ادرس دیتا رو نگه داشته میشه و اگر دوباره بخواید بخونید ادامه دیتا رو براتون خواهد داد ولی برای خوندن فایل مثلا از فلان ادرس هم تابعی هست که توضیح خواهم داد

 


ورودی و خروجی هاش؟
سه تا ورودی داره
 _ 1
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه
 _ 2
اشاره گر اسم فایل FileName یه اشاره گر به متغیری که باید قبل از این تابع از نوع TCHAR تعریف و مقدار دهی شده باشه البته میشه مستقیما هم نام فایل رو در فلش تعریفش کرد یا مثل مثال پایین بصورت مستقیم وارد تابع کرد
 _ 3
نوع دسترسی  ModeFlags یه متغیر از نوع بایت هست که میتونه 6 حالت مختلف داشته باشه
- FA_READ = 0x01
دسترسی برای فقط خواندن فایل 
- FA_WRITE = 0x02
دسترسی برای فقط نوشتن فایل
- FA_OPEN_EXISTING = 0x00
دسترسی فقط برای باز کردن فایل
- FA_OPEN_ALWAYS = 0x10
فایل را در صورتی که وجود ندارد ایجاد میکند در غیر این صورت از ادرس صفر فایل بازش میکند 
- FA_CREATE_NEW = 0x04
فقط فایل رو ایجاد میکند در غیر این صورت FR_EXIST  باز گردانده خواهد شد
- FA_CREATE_ALWAYS = 0x08
فقط فایل رو ایجاد میکند در صورت وجود فایل اطلاعات فایل پاک خواهد شد

و یک خروجی خطا داره که 17 حالت داره

FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, FR_NOT_ENABLED, FR_NO_FILESYSTEM, FR_TIMEOUT, FR_LOCKED, FR_NOT_ENOUGH_CORE, FR_TOO_MANY_OPEN_FILES 

در مورد این خطا ها باید بگم کلا 20 نوع مختلف داره و در توابع مشترک هستند و هر تابه یه تعداد خواصی شو برمیگردونه پس بعد از این برای خروجی توابع میتونید با چک کردن مقدارش بفهمید که تابع چه کاری کرده

- FR_OK = 0x00
عملکرد موفق ( مشکلی نبوده و تابع به درستی اجرا شده )
- FR_DISK_ERR = 0x01
خطا در توابع دیسک ( مشکلی در ارتباط با دیسک به وجود امده است )  دیسک وجود ندارد
- FR_INT_ERR = 0x02
خطا در ساختار فت یا سرریز شدن مقادیر متغیر های FATFS یا FIL یا دیگر متغیر های مرتبط
- FR_NOT_READY = 0x03
خطا در دیسک با  Level  پایین یا انیشیال نشدن درست دیسک با تابع disk_initialize منظور از Level  پایین یعنی دیسک وجود دارد ولی ارتباط درست نیست
- FR_NO_FILE = 0x04
فایل وجود ندارد
- FR_NO_PATH = 0x05
مسیر داده شده درست نیست
- FR_INVALID_NAME = 0x06
رشته داده به عنوان نام مسیر نامعتبر است 
- FR_DENIED = 0x07
دسترسی به مورد با توجه به یکی از موارد زیر محدود شده است
     +
برای فایلی با ویژگی فقط خواندنی حالت نوشتن یا باز را بنویسید
     +
حذف فایل یا دایرکتوری با ویژگی فقط خواندنی
     +
حذف دایرکتوری غیر خالی یا دایرکتوری جاری
     +
خواندن فایلی که بدون پرچم FA_READ باز شده باشه
     +
نوشتن یا تغییر فایلی که بدون پرچم FA_WRITE باز شده باشه
     +
ایجاد فایل یا دایرکتوری در درایو پر شده 
     +
حجم دایرکتوری ایجاد شده بیشتر از حجم خالی درایو باشد
- FR_EXIST = 0x08
این یعنی همنامی یا هر شی که دارای همین نام است و یا در حال حاضر موجود است
- FR_INVALID_OBJECT = 0x09
با توجه به ساختار فایل یا دایرکتوری شی نامعتبر است
- FR_WRITE_PROTECTED = 0x0A 
حفاظت شده در برابر هرگونه نوشتن
- FR_INVALID_DRIVE = 0x0B
شماره درایو انتخاب شده نا معتبر است
- FR_NOT_ENABLED = 0x0C
درایو مورد نظر توسط تابع f_mount تعریف نشده است
- FR_NO_FILESYSTEM = 0x0D
درایو پارتیشن بندی نشده یا فرمت نا معتبر است
- FR_MKFS_ABORTED = 0x0E
اندازه کلاستر برای این دیسک نامعتبر است و زمانی به وجود می اید که شماره کلاستر نزدیک 0xFF7 یا 0xFFF7 باشد
- FR_TIMEOUT = 0x0F
زمان پاسخ گویی به پایان رسید ولی جوابی نیامد
- FR_LOCKED = 0x10
دسترسی به فایل توسط کنترل به اشتراک گذاری فایل رد شده است
- FR_NOT_ENOUGH_CORE = 0x11
به یکی دلایل زیر حافظه به اندازه کافی برای عملیات وجود ندارد
     +
بافری برای LFN تعریف نشده است
     +
با توجه به اندازه جدول نیاز به اندازه کافی است
- FR_TOO_MANY_OPEN_FILES = 0x12
تعداد فایل های باز شده به حداکثر رسیده و فایل بیشتر نمی توان باز کرد
- FR_INVALID_PARAMETER = 0x13
پارامتر داده شده نامعتبر است

 

 

تابع سوم f_close() 

FRESULT f_close (
  FIL* FileObject                                     /* Pointer to the file object structure */
);


  ( اشاره گر فایل ) f_close

حالا این تابع چیه و به چه درد میخوره؟
برای بستن فایل هایی که قبلا باز کردیم به کار میره

کجا باید ازش استفاده کرد؟
اگر بعد از استفاده از فایل دیگه نیازی باهاش نباشه باید فایل رو ببندید
درصورت نبستن فایل مخصوصا زمان نوشتن احتمال از بین رفتن اطلاعات فایل وجود دارد

ورودی و خروجی هاش؟
یک ورودی داره
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

 

تابع چهارم f_read 

FRESULT f_read (
  FIL* FileObject,             /* Pointer to the file object structure */
  void* Buffer,                  /* Pointer to the buffer to store read data */
  UINT ByteToRead,       /* Number of bytes to read */
  UINT* ByteRead           /* Pointer to the variable to return number of bytes read */
);


 );
اشاره گر تعداد بایت خوانده شده , تعداد بایتی که قراره خونده بشه , اشاره گر بافر,اشاره گر فایلf_read ( 


حالا این تابع چیه و به چه درد میخوره؟
برای خوندن دیتای فایل هایی که قبلا باز کردیم به کار میره

کجا باید ازش استفاده کرد؟
اگر بخوایم دیتای فایل رو بخونیم باید از این تابع استفاده کنیم و حتما قبلش باید فایل رو بدون خطا باز کرده باشیم

ورودی و خروجی هاش؟
چهار تا ورودی داره
  1
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه
2
  اشاره گر بافر Buffer یه اشاره گر به متغیر یا تابعی که باید قبل از این تابع تعریف شده باشه 
  3
تعداد بایتی که قراره از فایل خونده بشه و در بافر قرار بگیره ByteToRead که باید یه متغیر از نوع UINT یا عدد ثابت باشه
  4
اشاره گر به متغیری که قراره تعداد بایت خونده شده در اون قرار بگیره ByteRead و باید قبل از تابع از نوع UINT تعریف شده باشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

 ByteRead
رو باید بعد از این تابع چک کنیم که برابر مقدار ByteToRead  باشه تا انتهای فایل رو تشخیص بدیم اگر مقدار ByteRead کوچکتر از ByteToRead باشه یعنی دیتای فایل به پایان رسیده است

مثال

void main (void)
        {
        FATFS fs;            // Work area (file system object) for the volume
        FIL fs;                              // file objects 
        BYTE buff[16];               // File read buffer
        UINT br;              // File read count
        FRESULT res;                  // Petit FatFs function common result code


        // Mount the volume
        f_mount(0, &fs);
        if (res) die(res);

        //در درایو 0  srcfile.dat   باز کزدن فایل 
        res = f_open(&fs, "0:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
        if (res) die(res); 
        // حلقه خواندن فایل و انجام کاری که قراره روی فایل انجام بدیم 
        do{
           
                // خوندن 16 بایت از فایل 
            res = f_read(&fs, buff, 16, &br);    
                // کارهایی که قراره روی دیتای خونده شده فایل انجام بدیم
                .
                .
                .
                . 
        // چک کردن مقدار خطا که بزرگتر از صفر نباشه و مقدار دیتای خونده شده تا کمتر از 16 نباشه
        }while (res || br != 16);  
        
        // بستن فایل
        f_close(&fs);
        // بستن درایو
        f_mount(0, NULL);
        }

 

تابع پنجم f_write 

FRESULT f_write (
  FIL* FileObject,     /* Pointer to the file object structure */
  const void* Buffer,  /* Pointer to the data to be written */
  UINT ByteToWrite,    /* Number of bytes to write */
  UINT* ByteWritten    /* Pointer to the variable to return number of bytes written */
);


 (اشاره گر تعداد بایت نوشته شده,تعداد بایتی که قراره نوشته بشه,اشاره گر بافر,اشاره گر فایل ) f_write


حالا این تابع چیه و به چه درد میخوره؟
برای نوشتن دیتای فایل هایی که قبلا باز کردیم به کار میره

کجا باید ازش استفاده کرد؟
اگر بخوایم دیتای فایل رو بنویسیم باید از این تابع استفاده کنیم و حتما قبلش باید فایل رو بدون خطا باز کرده باشیم

ورودی و خروجی هاش؟
چهار تا ورودی داره
1 :
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه
2 :
اشاره گر فافر Buffer یه یه اشاره گر به متغیر یا تابعی که باید قبل از این تابع تعریف شده باشه
3 :
تعداد بایتی که قراره از فایل نوشته بشه و در بافر قرار بگیره ByteToRead که باید یه متغیر از نوع UINT یا عدد ثابت باشه
4 :
اشاره گر به متغیری که قراره تعداد بایت نوشته شده در اون قرار بگیره ByteRead و باید قبل از تابع از نوع UINT تعریف شده باشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_READONLY_ باید صفر باشد

ByteWritten
رو باید بعد از این تابع چک کنیم که برابر مقدار ByteToWrite باشه تا انتهای فایل رو تشخیص بدیم اگر مقدار ByteWritten کوچکتر از ByteToWrite باشه یعنی دیتای فایل به پایان رسیده است

 

مثال
خوندن از یه فایل توی درایو 0 و نوشتنش توی فایل دیگه توی درایو 1 یا همان کپی فایل از درایو 0 به درایو 1


void main (void)
        {
        FATFS fs[2];         // Work area (file system object) for logical drives 
        FIL fsrc, fdst;      // file objects 
        BYTE buffer[4096];   // file copy buffer
        FRESULT res;         // FatFs function common result code 
        UINT br, bw;         // File read/write count 


        // Register work area for each volume (Always succeeds regardless of disk status) 
        f_mount(0, &fs[0]);
        f_mount(1, &fs[1]);

        // Open source file on the drive 1 
        res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
        if (res) die(res);

        // Create destination file on the drive 0 
        res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
        if (res) die(res);

        // Copy source to destination 
        for (;;) 
                {
                res = f_read(&fsrc, buffer, sizeof(buffer), &br);    // Read a chunk of src file 
                if (res || br == 0) break; // error or eof 
                res = f_write(&fdst, buffer, br, &bw);               // Write it to the dst file 
                if (res || bw < br) break; // error or disk full 
                }

        // Close open files 
        f_close(&fsrc);
        f_close(&fdst);

        // Unregister work area prior to discard it 
        f_mount(0, NULL);
        f_mount(1, NULL);
        }

 

 تابع ششم f_lseek

 

FRESULT f_lseek (
  FIL* FileObject,   /* Pointer to the file object structure */
  DWORD Offset       /* File offset in unit of byte */
);


 ( افست بایت,اشاره گر فایل ) f_lseek

حالا این تابع چیه و به چه درد میخوره؟
برای پرش به بایتی در دیتای فایلی که قبلا باز کردیم و قراره خونده یا نوشته بشه به کار میره

کجا باید ازش استفاده کرد؟
اگر بخواهیم دیتای فایلی رو از یه ادرس خاصی به جز ادرس جاری بنوسیم یا بخونیم از این تابع باید استفاده کنیم

ورودی و خروجی هاش؟
دو تا ورودی داره
1 :
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه
2 :
مقدار ادرس دیتایی که باید فایل از این ادرس خونده یا نوشته بشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع باید FS_MINIMIZE_ کوچکتر از 3 باشد

 


این هم سه تا مثال مختلف

مثال 1

    /* Open file */
    file = malloc(sizeof(FIL));
    if (!file) ...
    res = f_open(file, "file.dat", FA_READ|FA_WRITE);
    if (res) ...

    /* Move to offset of 5000 from top of the file */
    res = f_lseek(file, 5000);

    /* Move to end of the file to append data */
    res = f_lseek(file, f_size(file));

    /* Forward 3000 bytes */
    res = f_lseek(file, f_tell(file) + 3000);

    /* Rewind 2000 bytes (take care on overflow) */
    res = f_lseek(file, f_tell(file) - 2000);

مثال 2       -------------------------------------------------------------------------------------------------------------------------

    /* Cluster pre-allocation (to prevent buffer overrun on streaming write) */

    res = f_open(file, recfile, FA_CREATE_NEW | FA_WRITE); /* Create a file */

    res = f_lseek(file, PRE_SIZE);           /* Pre-allocate clusters */
    if (res || f_tell(file) != PRE_SIZE) ... /* Check if the file size has been increased correctly */

    res = f_lseek(file, DATA_START);         /* Record data stream without cluster allocation delay */
    ...

    res = f_truncate(file);                  /* Truncate unused area */
    res = f_lseek(file, 0);                  /* Put file header */
    ...

    res = f_close(file);

مثال 3       ---------------------------------------------------------------------------------------------------------------------------

    /* Using fast seek feature */

    DWORD lktbl[SZ_TBL];                   /* Link map table buffer */

    res = f_lseek(file, ofs1);                     /* This is normal seek (file.cltbl is nulled on file open) */

    file.cltbl = lktbl;                                 /* Enable fast seek feature */
    lktbl[0] = SZ_TBL;                            /* Set table size to the first item */
    res = f_lseek(file, CREATE_LINKMAP);   /* Create CLMT */
    ...

    res = f_lseek(file, ofs2);             /* This is fast seek (file.cltbl != NULL) */

 

تابع هفتم  f_truncate

FRESULT f_truncate (
  FIL* FileObject                       /* Pointer to the file object */
);


( اشاره گر فایل ) f_truncate

حالا این تابع چیه و به چه درد میخوره؟
فقط برای باز گرداندن حجم فایل به کار میره

کجا باید ازش استفاده کرد؟
اگر بخوایم حجم فایل رو  بفهمیم از تابع استفاده میشه

ورودی و خروجی هاش؟
یک ورودی داره
  1
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_READONLY_ و FS_MINIMIZE_ باید صفر باشد 

 


تابع هشتم f_sync

FRESULT f_sync (
  FIL* FileObject     // Pointer to the file object 
);


( اشاره گر فایل ) f_sync

حالا این تابع چیه و به چه درد میخوره؟
دقیقا مشابه تابع  f_close هست با این تفاوت که فایل رو نمیبنده و فقط اخرین تغییرات رو اعمال میکنه

کجا باید ازش استفاده کرد؟
این تابع برای برنامه های کاربردی که فایل های باز برای مدت طولانی در حالت نوشتن خواهد بود مانند انواع لاگر داده مناسب است بعد از هر بار نوشتن دیتا از این دستور استفاده میکنیم تا تغییرات به فایل اعمال بشه ولی فایل بسته نخواهد شد در واقع با این تابع خطر از دست رفتن اطلاعات به علت خاموشی ناگهانی و یا حذف دیسک ناخواسته را به حداقل میرسانید

ورودی و خروجی هاش؟
یک ورودی داره
1 :
اشاره گر  فایل FileObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FIL تعریف شده باشه

و یک خروجی خطا داره که 6 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT 
توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_READONLY_  باید صفر باشد 

 

تابع نهم f_opendir

FRESULT f_opendir (
  DIR* DirObject,       // Pointer to the blank directory object structure 
  const TCHAR* DirName  // Pointer to the directory name
);


( نام پوشه ، اشاره گر پوشه ) f_opendir

حالا این تابع چیه و به چه درد میخوره؟
برای باز کردن یک پوشه به کار میره

کجا باید ازش استفاده کرد؟
هر کجا نیاز به باز کردن یک پوشه باشه از این تابع استفاده میشه 
برای خوندن یا نوشتن فایل های داخل یک پوشه باید ان پوشه باز باشه یا اینکه نام فایل رو باید با مسیرهای پوشه ادغام شده باشه 

ورودی و خروجی هاش؟
دو ورودی داره
1
  اشاره گر  پوشه DirObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر DIR تعریف شده باشه
2
  اشاره گر یا نام پوشه ای که قراره باز بشه

و یک خروجی خطا داره که 11 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_NO_PATH, FR_INVALID_NAME, FR_INVALID_DRIVE, FR_NOT_ENABLED, FR_NO_FILESYSTEM, FR_TIMEOUT, FR_NOT_ENOUGH_CORE 

توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_MINIMIZE_  باید کوچکتر یا مساوی یک باشد

 

تابع دهم   f_readdir

FRESULT f_readdir (
  DIR* DirObject,    // Pointer to the open directory object 
  FILINFO* FileInfo  // Pointer to the file information structure 
);


( اشاره گر ساختار فایل ، اشاره گر پوشه باز شده ) f_opendir

حالا این تابع چیه و به چه درد میخوره؟
برای خواندن محتوای داخل یک پوشه به کار میره

کجا باید ازش استفاده کرد؟
هر کجا نیاز به خواندن محتوای فایل ها یا دایرکتری های داخل یک پوشه نیاز باشه از این تابع استفاده میشه
برای خوندن یا نوشتن فایل های داخل یک پوشه باید ان پوشه باز باشه

ورودی و خروجی هاش؟
دو ورودی داره
1
  اشاره گر  پوشه DirObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر DIR تعریف شده باشه
2
  اشاره گر  ساختار فایل FileInfo یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر FILINFO تعریف شده باشه

و یک خروجی خطا داره که 7 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_INVALID_OBJECT, FR_TIMEOUT, FR_NOT_ENOUGH_CORE 

توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_MINIMIZE_  باید کوچکتر یا مساوی یک باشد


جستجوی در فایلها


بعد از این تابع شما میتونید هر کاری رو بر روی هر فایلی انجام بدید توابع بعدی توابع متفرقه ای هستند و برای انجام برخی کارهای ساده و یا راحت تر شدن کار نوشته شده اند البته باز هم ادامه خواهم داد و همه توابع رو توضیخ خواهم داد
ولی فعلا با همین توابه براتون یه مثال میارم که برای جستجوی در فایلها به کار میره

به طور مثال میخواهیم در یک درایو فقط فایل های MP3 رو تشخیص داده و اونهارو پخش کنیم این گونه عمل خواهیم کرد
برای اینکه دستورات خواناتر باشند و به هم نریزه من توضیحات فارسی رو در سطر بعدی دستورات نوشتم

FRESULT scan_files (char* path)
                        {
            FRESULT res;
            FILINFO fno;
            DIR dir;
        pos_ts pos;
            int i;
            char *fn;
        char Cfile[128];
#if _USE_LFN
            static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
            fno.lfname = lfn;
            fno.lfsize = sizeof(lfn);
#endif
            res = f_opendir(&dir, path); 
        // باز کدن پوشه
            if (res == FR_OK) 
                        {
                        i = strlen(path);
                        for (;;) 
                                    {
                                                res = f_readdir(&dir, &fno);
                        // خواندن محتوای پوشه
                                                if (res != FR_OK || fno.fname[0] == 0) break;  
                        // تشخیص انتهای پوشه
                                                if (fno.fname[0] == '.') continue;             
                        // نادیده گرفتن نقطه
#if _USE_LFN
                                                fn = *fno.lfname ? fno.lfname : fno.fname;
#else
                                                fn = fno.fname;
#endif
                                                if (fno.fattrib & AM_DIR)
                        // در صورتی که محتوای پوشه یک پوشه باشد
                                                            {
                                //sprintf(&path[i], "/%s", fn);
                                if(strlen(path) > 0)strcatf(path, "/");
                                strcat(path, fn);
                                                            res = scan_files(path);
                                                            if (res != FR_OK) break;
                                                            path[i] = 0;
                                                                        } 
                        else
                        // در صورتی که محتوای پوشه یک فایل باشد
                                                {
                                strcpy(Cfile, path); 
                                strcatf(Cfile, "/");
                                strcat(Cfile, fn);
                                                            //sprintf(Cfile,"%s/%s", path, fn);
                                if(strstrf(Cfile, ".MP3") || strstrf(Cfile, ".mp3")) 
                                // باشد MP3 در صورتی که فایل
                                                {
                                                //..
                                        // فراخوانی توابعی که برای پخش فایل های پیدا شده نیاز هست
                                        }
                                                                        }
                                                }
                                    }
            return res;
                        }

 

همه فایل های داخل هر پوشه یا درایوی رو چک کنید

خروجی این تابع رو میتونید با سریال به PC وصل کرده و ترمینال کدویژن یه چیزی مثل دستور DIR داس رو داشته باشید
فقط کافیه نام پوشه یا درایو را در ورودی تابع بهش بدید

FRESULT scan_files (
    char* path        // Start node to be scanned (also used as work area)
)
{
    FRESULT res;
    FILINFO fno;
    DIR dir;
    int i;
    char *fn;   // This function is assuming non-Unicode cfg.
#if _USE_LFN
    static char lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof(lfn);
#endif

    res = f_opendir(&dir, path);                       // Open the directory
    if (res == FR_OK) {
        i = strlen(path);
        for (;;) {
            res = f_readdir(&dir, &fno);                   // Read a directory item
            if (res != FR_OK || fno.fname[0] == 0) break;  // Break on error or end of dir
            if (fno.fname[0] == '.') continue;             // Ignore dot entry
#if _USE_LFN
            fn = *fno.lfname ? fno.lfname : fno.fname;
#else
            fn = fno.fname;
#endif
            if (fno.fattrib & AM_DIR) {                    // It is a directory
                sprintf(&path[i], "/%s", fn);
                res = scan_files(path);
                if (res != FR_OK) break;
                path[i] = 0;
            } else {                                       // It is a file.
                printf("%s/%s\n", path, fn);
            }
        }
    }

    return res;
}

اگه میخواید درایو رو سرچ کنید فقط کافیه وردی تابع رو خالی بدید این یعنی دایرکتری یا درایو جاری
ولی اگه قراره یه پوشه رو چک کنید نام و ادرس پوش رو بهش بدید مثلا اگه قراره پوشه data رو در پوشه system چک بشه باید اینطور بنویسید "System/data"
این توابع محدود به یک یا چند نوع فایل نیست و باهاش هرنوع فایل و پوشه رو میتونید ویرایش یا ایجاد یا بخونید
در مورد فایل ها هم باید بگم هر نوع فایلی یه فرمت خاص و هدر خواصی داری که برای ایجادش حتما باید مد نظر باشه 
خود بنده با استفاده از این توابع برای برخی از کارهایی که انجام دادم فایل هایی ایجاد و ویرایش میکنم که فقط خودم از فرمتش خبر دارم و هیچ استانداردی ندارد حتی پسوندش هم خودم دادم و فقط خودم میدونم که فایل چیه و دیتاش کجاشه و ......

 

تابع یازدهم  f_stat

FRESULT f_stat (
  const TCHAR* FileName,  // Pointer to the file or directory name
  FILINFO* FileInfo       // Pointer to the FILINFO structure
);

 ( اشاره گر ساختار فایل ، نام فایل ) f_stat

حالا این تابع چیه و به چه درد میخوره؟
برای به دست اوردن وضعیت فایل یا پوشه به کار میره

ورودی و خروجی هاش؟
دو ورودی داره
1
  اشاره گر  یا نام فایل DirObject یه اشاره گر به متغیری که باید قبل از این تابع از نوع استراکچر DIR تعریف شده باشه
  2
اشاره گر اسم فایل FileName یه اشاره گر به متغیری که باید قبل از این تابع از نوع TCHAR تعریف و مقدا دهی شده باشه 

و یک خروجی خطا داره که 11 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, FR_INVALID_DRIVE, FR_NOT_ENABLED, FR_NO_FILESYSTEM, FR_TIMEOUT, FR_NOT_ENOUGH_CORE 

توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_MINIMIZE_  باید کوچکتر یا مساوی یک باشد

 

تابع دوازدهم f_mkdir

FRESULT f_mkdir (
  const TCHAR* DirName // Pointer to the directory name
);


( نام پوشه ) f_mkdir

حالا این تابع چیه و به چه درد میخوره؟
برای ایجاد یک پوشه جدید به کار میره

ورودی و خروجی هاش؟
یک ورودی داره
1-
اشاره گر اسم پوشه DirName یه اشاره گر به متغیری که باید قبل از این تابع از نوع TCHAR تعریف و مقدا دهی شده باشه 

و یک خروجی خطا داره که 14 حالت داره
FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_NOT_READY, FR_NO_PATH, FR_INVALID_NAME, FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, FR_NOT_ENABLED, FR_NO_FILESYSTEM, FR_TIMEOUT, FR_NOT_ENOUGH_CORE 

توضیح خطا ها هم مثل توابع قبلی هست

برای استفاده از این تابع FS_MINIMIZE_  و FS_READONLY_ باید مساوی صفر باشند

مثال

    res = f_mkdir("sub1");
    res = f_mkdir("sub1/sub2");
    res = f_mkdir("sub1/sub2/sub3");

 

 

تاریخ ارسال: پنج‌شنبه 31 مرداد 1392 ساعت 17:19 | نویسنده: شاپور جگرگوشه
نظرات (6)
سه‌شنبه 18 آبان 1395 03:25
ehsan.s [ ]
امتیاز: 0 0
لینک نظر
سلام خسته نباشید خیلی مفید بود. من یک مشکل دارم و راهنمایی میخوام. فرض کنیم تعداد زیادی فایل که نام هاشون عدد پشت سر هم هست و نیازه به ترتیب باز بشن و خونده بشن. میشه از یک متغیر مثلا i integer و یک حلقه for استفاده کنم و در دستور خواندن چطور باید اسم فایل رو بدم . از روی SD card فایل ها خونده میشن ایا این کتابخانه های توابع ff و pff و یا FatFS چنین دستوری دارند.
پنج‌شنبه 29 مهر 1395 03:50
Yaser [ ]
امتیاز: 0 0
لینک نظر
عالی بود ...
دستتون درد نکنه...
اگر امکان داره خرین ورژن این لایبرری FatFs R0.12b
اموزش بدید چون تغیراتی کرده ...
با کمال تشکر
جمعه 20 شهریور 1394 16:22
علی [ ]
امتیاز: 0 0
لینک نظر
سلام و تشکر بابت آموزش کامل این کتابخانه
چهارشنبه 5 شهریور 1393 18:52
محمد [ ]
امتیاز: 1 0
لینک نظر
با سلام و خسته نباشید
من یه چند روزی هست که میخوام یک wav player درست کنم
ولی نمیدونم چطوری اطلاعات آهنگ ذخیره شده با فرمت wav را
از طریق avr بخونم. اگر امکانش هست یه برنامه ساده جهت خواندن اطلاعات (کد هگز) آهنگ بنویسید .
یا حداقل منبعی معرفی کنید تا بتونم این اطلاعات را بخونم و به موج آنالوگ جهت پخش آهنگ تبدیل کنم.
با تشکر
پنج‌شنبه 15 خرداد 1393 02:41
صادق [ ]
امتیاز: 1 0
لینک نظر
سلام
واقعا دستتون درد نکنه
عالیه
از این کامل تر وجود نداره.
خیلی ممنون
چهارشنبه 20 شهریور 1392 11:57
ع.س [ ]
امتیاز: 2 0
لینک نظر
خیلی عالیه!
برای نمایش آواتار خود در این وبلاگ در سایت Gravatar.com ثبت نام کنید. (راهنما)
نام :
پست الکترونیک :
وب/وبلاگ :
ایمیل شما بعد از ثبت نمایش داده نخواهد شد