اخرین
ورژن این لایبرری 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 حالت داره
0 : غیر فعال کردن ویژگی 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");
سلام خسته نباشید خیلی مفید بود. من یک مشکل دارم و راهنمایی میخوام. فرض کنیم تعداد زیادی فایل که نام هاشون عدد پشت سر هم هست و نیازه به ترتیب باز بشن و خونده بشن. میشه از یک متغیر مثلا i integer و یک حلقه for استفاده کنم و در دستور خواندن چطور باید اسم فایل رو بدم . از روی SD card فایل ها خونده میشن ایا این کتابخانه های توابع ff و pff و یا FatFS چنین دستوری دارند.
عالی بود ...
دستتون درد نکنه...
اگر امکان داره خرین ورژن این لایبرری FatFs R0.12b
اموزش بدید چون تغیراتی کرده ...
با کمال تشکر
سلام و تشکر بابت آموزش کامل این کتابخانه
با سلام و خسته نباشید
من یه چند روزی هست که میخوام یک wav player درست کنم
ولی نمیدونم چطوری اطلاعات آهنگ ذخیره شده با فرمت wav را
از طریق avr بخونم. اگر امکانش هست یه برنامه ساده جهت خواندن اطلاعات (کد هگز) آهنگ بنویسید .
یا حداقل منبعی معرفی کنید تا بتونم این اطلاعات را بخونم و به موج آنالوگ جهت پخش آهنگ تبدیل کنم.
با تشکر
سلام
واقعا دستتون درد نکنه
عالیه
از این کامل تر وجود نداره.
خیلی ممنون
خیلی عالیه!