标题: [资料] 自己移植的SD卡的FATFS文件系统,FATFS R0.09 (MDK STM32f103) [打印本页] 作者: Gegu 时间: 2016-4-28 10:03 标题: [资料] 自己移植的SD卡的FATFS文件系统,FATFS R0.09 (MDK STM32f103) 自己移植的SD卡的FATFS文件系统,采用最新版FATFS R0.09,并且有详细的中文注释,和操作测试程序,完整的MDK STM32F103工程。下载即可使用。 ( C: v, y' d* d. R9 C. y+ d/*----------------------------------------------------------------------------/ 9 Y: |6 A) G+ L q/ FatFs - FAT file system module R0.09 (C)ChaN, 2011 . y8 P7 K% j. x. l4 Y6 ?/-----------------------------------------------------------------------------/3 `2 c8 k# b1 u8 d
/ FatFs module is a generic FAT file system module for small embedded systems." u5 }8 \' O' v3 L l. }: T
/ This is a free software that opened for education, research and commercial3 }2 `- }# {# N( U
/ developments under license policy of following terms.& Z4 R" L$ \8 b4 E* v
/ 0 _; }& U- z' T6 t) b$ `/ Copyright (C) 2011, ChaN, all right reserved. ! A/ a; r: c( G/ V& F/ ( a+ H0 n. }7 @ s) k- @( u7 ^/ * The FatFs module is a free software and there is NO WARRANTY.! q: |4 Z+ F0 e9 Q( [' q
/ * No restriction on use. You can use, modify and redistribute it for % v' p# q& V1 j2 u/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.( C6 U- b1 f$ h# B$ @$ D
/ * Redistributions of source code must retain the above copyright notice.( z$ @8 ], r8 v# t$ i, {
/ & u( `8 y3 ^6 ?! f4 e/-----------------------------------------------------------------------------/ $ n) p$ I) }! h6 Z( y1 Z* d0 n2 p8 _: f
# }3 Q4 L9 q4 C$ n: P//检测磁盘是否插好5 \ D/ E% T) }7 g( v2 b ~
BOOL disk_detect_OK(void) ! i0 i" s, x4 H& R{5 R# M% ]) T. s* D k2 V
if( disk_status(0)==STA_NODISK )/* Physical drive nmuber (0..) */' V" [+ M6 G8 S9 t
{5 |7 b9 j1 Z0 w; z% C2 V
printf("\r\n\r\n%48s\r\n","<未检测到磁盘,请检查SD卡是否插好...>"); ( ^1 t7 j" G7 _$ U8 R2 ^ return FALSE; & _, A: j7 D1 B5 ?9 t- [6 W, A0 k } E% h. T. z8 j+ @9 Q; l return TRUE; . I% Y, b; B) d4 ^! F- F, w+ E7 t} + N Y) v3 O5 F( F7 l # S+ e: ^1 e( S x4 H L/ o2 l: I6 n
) K' ]/ y& i; m
//测试函数执行结果分析& { W* w; ], B0 ^
void die(FRESULT res), h# v4 b5 }/ D; X& S; Y
{ 9 L6 a$ u$ e3 C: `& @ switch(res)) @, j9 @7 d4 H; Q6 ^
{+ k3 x; {- ^& g; C; X- ~# h. V
case FR_OK: //The function succeeded. 7 T F! N" B; ~7 A5 h, D5 E/ K4 L) S {* {+ k. z' t% R) z- c: K
printf("\r\nThe function succeeded!\r\n"); 2 \& @4 H4 \- O break; 5 U% ~7 v0 l9 X: `) {, ^- r' H } : ?# S- d [! U6 \+ Z0 n5 D case FR_NOT_READY://The disk drive cannot work due to no medium in the drive or any other reason1 \4 g$ g8 M9 I1 b
{1 i( _7 w! B! i: ~9 H8 e
printf("\r\nThe disk drive cannot work due to no medium in the drive or any other reason!\r\n");1 `* ?. |0 t( F4 _( }7 C4 @
break;, s$ ^3 a, ^* p$ S# S3 A7 ?3 X
}: `# j) G8 Y+ N1 O3 N
case FR_NO_FILE://Could not find the file. # ^. L8 N! d0 q- T1 R c2 Z. }# V { 6 t0 G6 v/ X: \# @$ A; y printf("\r\nCould not find the file!\r\n");7 D6 z% \7 S* G5 ^
break;, {& X! q; b* ^1 E t
}% n5 Z# X5 V6 f
case FR_NO_PATH://Could not find the path1 F! B# E% f i1 U; c2 y
{ - S7 d/ `3 ~" F) P% s; V ~ printf("\r\nCould not find the path!\r\n"); - ]2 r4 s5 h! B' q3 U break;9 E: Q9 C; h1 f
}5 n( `- F- R- d0 Q% q' Z j
case FR_INVALID_NAME://The path name is invalid ( ^5 b. W* o3 i$ [ { + Y0 x7 D* e0 Y printf("\r\nThe path name is invalid!\r\n"); + t9 O' _7 ]% Y7 D) e Q break;6 b' u6 V, ]! h; B
} 2 B3 g$ a a5 Q! { p3 x case FR_INVALID_DRIVE://The drive number is invalid % [8 S2 G! J4 w5 s9 g( b0 S7 }3 y { / @ |* @8 M/ T* }% b printf("\r\nThe drive number is invalid!\r\n");$ r' X7 ^" e& g3 b
break; & T3 }; A) o4 `; g# z7 A5 w }; c5 `3 _+ g) X3 [
case FR_DENIED://The directory cannot be created due to directory table or disk is full. 8 S* s% N) P- T# I& h { 4 |" s8 C. l+ b* Z printf("\r\nThe directory cannot be created due to directory table or disk is full!\r\n"); ' \9 X9 ?: l2 k break;1 n. l! j, ] w2 Y. v2 ~% w) }
}2 A! q( |( s, [
case FR_EXIST://A file or directory that has same name is already existing' ^$ N+ I4 N6 H! `
{ ( |8 @. N# b/ U6 |$ `6 M) w( X& P printf("\r\nA file or directory that has same name is already existing!\r\n"); a& y/ m' B8 Z" K) R" K k break; # j+ O3 i# W! w0 _& ~ }/ G# U7 B" G" \% @4 s, W3 z
// case FR_RW_ERROR://The function failed due to a disk error or an internal error: Y/ o2 W7 Y( f1 ^2 {
/*+ m3 a9 _ G" l, j% @7 {/ {! V
case FR_RW_ERROR://The function failed due to a disk error or an internal error 2 V: F9 p8 J& C$ i3 ]7 ]5 e7 X) q {8 y, z. `: f- w3 u+ V
printp("\r\nThe function failed due to a disk error or an internal error!\r\n"); # V9 a( H/ m- ^4 e0 l2 f! W break;' r! n$ m% s8 F+ _4 V
} 9 ^' P$ s" k+ }5 h6 \, r8 g1 K8 c*/) S( d! K8 A6 M' T( F
case FR_WRITE_PROTECTED://The medium is write protected % `5 j; W- a4 Q" A6 D {, k$ g" |2 X8 W0 I. z; h* k# m0 b
printf("\r\nThe medium is write protected!\r\n");/ E6 K5 e& D! ?+ P4 ~5 k
break; % p2 Q( v3 M, N: `! i% \3 O } Z3 o, A2 ]1 B/ V
case FR_NOT_ENABLED://The logical drive has no work area $ x) d- b& H7 o6 S* \ { 9 E8 j7 o5 Q1 {/ x( |( X printf("\r\nThe logical drive has no work area!\r\n"); # K* j; e' U# V. C break; # o$ l) B6 h6 s; @, k }9 P* g5 t% G+ B3 d
case FR_NO_FILESYSTEM://There is no valid FAT partition on the disk3 t4 R, {* f6 e/ q7 M
{" R( j# \5 {7 b! I+ U
printf("\r\nThere is no valid FAT partition on the disk!\r\n");" ~" D0 D4 s. I% O i- I
break; 5 D m! S9 |( w% s+ W: E } 2 l+ q, x; M7 m6 e3 t3 e7 o case FR_INVALID_OBJECT://The file object is invalid9 r8 f9 z! R, ]( u2 Q) G8 g9 L
{ ) Q: N. e2 B7 r printf("\r\nThe file object is invalid!\r\n");! \8 _6 d2 V+ m; _
break; 9 S8 v, y' s2 d' O }9 u7 C } 8 F1 X! Q, h& o1 ^5 A/ S4 X- \ 2 v6 a! F# R9 {2 m/ W //The function aborted before start in format due to a reason as follows. 6 _. s L9 [( X6 R& [
//The disk size is too small. ! m1 q. O0 I J0 H( _! V# \
//Invalid parameter was given to any parameter. ' v' ^! S) I- n# c0 j4 p //Not allowable cluster size for this drive. This can occure when number of clusters becomes around 0xFF7 and 0xFFF7. - D, `: v0 _; H( R
case FR_MKFS_ABORTED://" E s# ~! V- R; F% i- [
{ & t+ N, L. z$ e3 R1 r. Q( V printf("\r\nThe function aborted before start in format!\r\n");" h8 {5 H: o6 P' l, O5 Q
break;8 R6 S& w; c( M" C3 c) }* w: W$ A
}& S8 D0 H# p1 I7 D
" w- `1 D' S9 T6 X0 d default:% i- |0 V, X; Z6 w! a
{8 q* ?7 k& {( S2 C) i
printf("\r\nerror!\r\n");( }( I+ r `& K" d; K* C
break;+ ?8 ?# B( e e+ |: e
} 5 {; t+ _/ C/ y5 y& s3 H
} / C# v# O) L/ s return; 0 E; M' g9 g6 R3 z} . }' Y; K/ c8 h) k4 evoid Test_f_getfree(void)//获取卡的总容量及剩余容量 ' \& H r( B0 f# N2 `{ * |; Z! \1 D# L- h; z9 x. C0 j FATFS fs; 2 Q1 N# S5 f5 [" Q/ A% j FATFS *pfs; ) O; S. `6 R* T) l4 r( l9 v DWORD clust; 9 {0 s7 j( `3 T, t9 F" K FRESULT res; // FatFs function common result code - J N3 a- X) f/ m* ~8 _( i + b! Y ^0 z+ q" W+ W3 ?; \ //检测磁盘是否插好& {9 k7 ]: y6 `8 d* q
if( disk_detect_OK()==FALSE ) return;+ [9 D- f2 f0 ~& ~+ C( Y
2 J0 k* g; \- ^) j F; J
pfs=&fs;//指向. n! m1 P) `2 p! m. X
// Register a work area for logical drive 0 ) ]+ C; v0 |( F2 D6 [7 j f_mount(0, &fs);//安装FATFS,就是给FATFS分配空间 ! v- Z0 l( ?; ?) Y4 y- @' C G+ ^. N& d3 v' c
// Get free clusters * I2 }0 J% G* G( h! g: ~ res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0;"/"或者"0:/" 4 a1 }& W" N5 r$ R" r7 N9 L! V6 g if ( res==FR_OK ) # @5 `/ x8 {: R {3 P$ R. @, I; {/ q
// Get free space2 T# h+ J$ a$ c) x& m3 {, w6 _8 h
printf("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",' P, b, x+ E5 d0 X
(DWORD)(pfs->n_fatent - 2) * pfs->csize /2/1024,//总的磁盘空间M =(总簇数-2)*每簇的扇区数/2/1024=可用簇数*每簇的扇区数/2/1024( Y9 K2 y' `( O q) p
clust * pfs->csize /2/1024);//空闲的磁盘空间M=剩余簇数*每簇的扇区数/2/1024 " j @; R7 Z* H, n } ! V- q* l1 A3 ~- p. T8 N else die(res);//测试函数执行结果分析 6 x6 C7 c2 D. l7 a+ Y 0 ^$ i$ g5 g5 ^/ I. {8 C // Unregister a work area before discard it 2 J! X6 }, c, ]) ^& s f_mount(0, NULL);//卸载FATFS,就是释放FATFS结构体所占空间% m3 ?2 G! B ]- D
}* {" w% c4 Q% Q/ J% h3 X5 v" A/ R
% d: ?4 X y+ J0 d9 B- L+ Svoid Test_f_read(void)//读文件的数据,如果没有此文件则返回错误, D6 O/ b7 p6 N( U7 ]
{* k: U- a% R- U) j6 u& I7 B* q
FATFS fs; // Work area (file system object) for logical drive / t# B/ B4 ^' K* @9 P3 m+ o4 P FIL fsrc; // file objects1 D) f# g6 k/ s7 ?9 n3 X& M f9 S
BYTE buffer[512]; // file copy buffer! U1 F( ~* M3 ~6 G2 H
FRESULT res; // FatFs function common result code! i$ D7 [' x" _! f, M* r# [8 |
UINT br; // File R count- W& @4 b: N+ z# }6 }- i7 I
u16 i;' r3 s( `- }1 e% P" p
" H6 a5 j2 a8 A% ?/ T* Q0 V* i2 V1 D: c$ C$ f. E( K3 W
char path[20];& l- O# {% \4 F& P9 W
$ ] E9 l& s, d# b //检测磁盘是否插好 9 E5 M! y! h7 c1 I if( disk_detect_OK()==FALSE ) return;7 Q8 U3 `1 \: Z- U$ x
" J2 r3 F1 R! Q3 H: j: p- ]( L
// Register a work area for logical drive 0 , y. ^" Y) t: S7 A# R f_mount(0, &fs);9 w% Y5 l! A8 w- z/ i
! ?0 ]% {' A$ \+ _* I+ J3 O, f printf("\r\nread file:>"); ; w3 z) X& l% K, s6 O USART_Scanf_Name(path);//通过串口输入文件路径名/dir/file.txt或者0:dir/file.txt或者0:/dir/file.txt 5 D4 b! H+ m7 q: q3 Q. ^/ y M2 m1 x, W4 t, z* h
//Open source file - ~. _: i4 _& }0 B$ ~' k' F! t res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);//打开存在的文件,如果没有则返回错误( }, q# q5 Y6 i. _
die(res);) a2 W0 S9 I: p: X) I% o
5 \1 w. H6 O! D* e. D1 L, ` //buffer空间设大一点,会提高读的速度。8 e# [( a, o/ X* E% N; g
//如果文件实际大小512byte,9 Q# {/ H+ a/ s* S4 `- x$ Y
//设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。 8 d" a4 c# s" I% E0 @ //下面两行主要是去除1s误差。# Z* x7 h0 r( x% G
6 g* x9 t6 |/ }
for (;;) $ f9 e+ M* N/ d/ z8 W4 u
{ . }. G J) q1 e4 V9 S for(i=0;i<sizeof(buffer);i++) buffer[i]='\0';//清除缓存 2 Y) `3 q7 d, k; a% B& a# E9 I! W6 Q$ a. W- P& ^" s1 t
res = f_read(&fsrc, buffer, sizeof(buffer), &br);4 n# r0 V* H A2 H
if (res ||(br == 0)) break; // error or eof 0 @6 ]; s! Y( M: | `( S) @$ `0 w , `+ [. K3 p" C+ }* u1 A P printf("%s",buffer); 3 R: n; @/ U0 o5 r& Y9 g
} 2 I- Y4 v: r( A! w: D0 A# h% }/ |' j0 h4 s- e1 r2 ^
$ z. L: [2 d& r // Close all files" ?% [/ U# `# n
f_close(&fsrc); c" v% C& p; f8 |: u
// Unregister a work area before discard it c. u* @' C q& A
f_mount(0, NULL); 6 ? d* g: K0 }& d$ x3 D( K}$ ?* f6 w/ I ]" j
% u3 l6 R# [" ]2 S0 Pvoid Test_f_write(void)//写数据到文件,如果没有此文件则创建文件 ! A* E/ b. @" M9 Y9 [7 K0 p{3 q% k# L/ ^$ ]
FATFS fs; // Work area (file system object) for logical drive 9 O* z5 L9 O: {' i/ _ J FRESULT res; // FatFs function common result code, [! a, d( X. M6 o
FIL Make_file; ( n" b3 O c! S( ^* e% @2 ?; O" j char file_name[20];1 T8 R: L$ Q: E/ U8 A& u, k% u
char Storage_buffer[] ="0";* I0 I9 e3 x" Q; ]" e
- c; D8 m& n1 n! R+ A UINT bw;( \- a) z6 ^1 D ^8 o
//检测磁盘是否插好$ ^' m4 s6 P* @" m0 F
if( disk_detect_OK()==FALSE ) return;; o/ O/ @+ z# f8 \2 j/ Q, _: Z
printf("\r\n inaert_ok:>"); , a1 v7 _& b O% R5 e& T // Register a work area for logical drive 0 ( n2 I* f* E" R% g1 @( I f_mount(0, &fs);. g; y3 m6 m' B- Z3 ` j
/ L+ _% m* S. Z; S/ U- R
printf("\r\n Make file Name:>");) G, \1 P5 Q( k- M) _
USART_Scanf_Name(file_name);//通过串口输入源文件路径名/dir/file.txt或者0:dir/file.txt或者0:/dir/file.txt6 @) ? M0 t: g: }0 u7 v( S* _
* X7 {# O7 ]) Q+ W) J5 S res = f_open(&Make_file, file_name, FA_OPEN_ALWAYS | FA_WRITE); //可写方式打开 没有文件则创建 / f! X* J: V. n: C+ L+ w2 G5 u
printf("\r\n open_ok:>");1 K3 Q9 B, Z- k+ }6 L7 ]7 \: \5 n
die(res);' t1 V0 t0 u( e3 I
res = f_lseek(&Make_file, Make_file.fsize); //指针移到文件最后 ) Y8 ?# y; b- J k printf("\r\n seek_ok:>");; e/ Y7 G6 K/ z; N" k
die(res); 6 ?2 S; M" D1 m: p! y3 V res = f_write(&Make_file, Storage_buffer, (sizeof (Storage_buffer))-1 , &bw); //每次需要写入的数据字节数,去掉最后的\0所以-1 # c6 }3 F6 Q5 V2 T$ b* K' x% [ printf("\r\n write_ok:>");& B. j( y4 E; N7 r" T4 |
die(res);& X1 s7 I' M) k! r) [. ]
res = f_lseek(&Make_file, Make_file.fsize); //指针移到文件最后 5 F, L- }! l$ y, p2 N5 @; T) b
f_close(&Make_file);//关闭文件 ! ]$ |; Q6 \0 t- o7 O' f) N5 m printf("\r\n close_ok:>"); + |7 A! w7 r9 _) H% @2 z# U7 ~1 Y7 x& G 8 ]! B3 f, V. i; D, w printf("\r\n写文件测试OK!\r\n"); y; N9 _/ E. [* |% Y+ l+ R: _* [, h9 D0 F3 |* D! F7 l! {
// Unregister a work area before discard it& n; ~* U; G% ~+ `& s' _% B; f
f_mount(0, NULL); 1 p% x8 D' r/ [' H; _" K$ a} : T' m5 I9 e% d( ~8 {0 Z% G6 l, ^/ g* {5 D2 I- g% C z1 a
//The f_read function reads data from a file. - }4 H( Y n: r) R7 w* g) }3 E//在RAM里面调试这个程序的时候,总出现莫名其妙的错误,最后怀疑是堆寨溢出了,证明果然是这样' r {- t/ ]* H2 H+ z0 ^
//把Stack_Size EQU 0x00000400 改为 Stack_Size EQU 0x00000800就正常了 ; Z7 P! g) R! _& Z" f% a1 t//所以以后要特别注意这个问题。 / T+ n9 z: M# J9 P9 K; y( S& R. e$ V# M! e+ O# ^* o! {
u8 StrToData(u8 * data, u8 len)- ?* F+ C0 B% ~/ C" F
{ " k/ V9 p5 f; d* L+ b9 r u8 ltemp; % v: `4 I% o( v0 O) Z, c1 [ if(len == 1)+ T' y' g. T" B- j
{; \4 D4 E3 G" p( W
ltemp = data[0]-0x30; + k) @7 ?8 h6 l+ b! E0 ~+ y+ Z, {
} ) R$ E' h: z4 D! R! L else if(len == 2)1 I" r( e1 J- P' V" m# h
{! O* A3 Q" l7 ?, L7 |$ r
ltemp = (data[0]-0x30)*10 + (data[1]-0x30);9 y2 c2 ]4 a2 U$ x3 \0 A
* l3 z: t5 p' B8 q: _4 v
}$ m& l2 H9 o# G9 J z: C b6 |1 R/ Z
//else if(len == 3)5 H% O% z! G, W: }) L6 h5 `) h
//ltemp = (data[0]-0x30)*100 + (data[1]-0x30)*10 + [data[2] - 0x30];! E, w' S2 M0 K# Z8 Q
" g4 s6 x" |' ~4 S4 M4 b, H5 X ] return ltemp;/ R2 z m% s$ O2 A4 n
' a3 I; O+ h$ [+ X" P2 d% k} / `. j; s1 v# m5 f 2 c8 G/ q" N. H9 Q: r! k) { 2 } x+ u2 D0 b* a# o# S#endif ) |" I, [% y% h2 X7 B5 ~( f1 j8 f; G" t) _! r
" t" D# l, e( V4 i; O4 c/*8 C) b6 b9 r5 i b& p8 m/ U
int main(void)* l; _9 [% P5 S8 U3 o
{7 m- e# y. R$ I! o6 s2 M3 M
/////////////////////////////////////////////////////////// ! T# f/ z( y/ I# @- V0 ZUART1GPIO_config();//串口IO口配置( O% K. T# @# U7 h3 I* d
USART1_config();//串口初始化波特率为192008 s3 `3 E& N" g5 Y1 n( c- L
//UART1NVIC_config();//配置中断1 z7 [6 L! o9 c) l& p1 D' ]
///////////////////////////////////////////////////////////( ]0 a2 q/ k3 Z' D8 O C7 R2 \) X
SDCard_SpiInit();//SD卡的IO口及SPI模块初始化,PA2插入检测(H—>L)A3 CD_CS片选;PA5 SCK;PA6 MISO;PA7 MOSI;低速模式 " O2 w/ W6 j9 s" k2 \2 `4 ?- N- ?//SD_Init();//SD卡初始化,如果使用的FATFS则可以不用这句,因为FATFS在打开文件等操作时已经调用了它 7 ^2 K* f% u4 W/ C+ ?4 q. \Test_f_getfree();//获取SD卡的容量和剩余容量; I9 L+ v4 k6 L6 R: z' ~
Test_f_read();//SD卡读文件测试 ; \; m2 u+ t0 N: B2 n" Y4 bTest_f_write();//SD卡写文件测试4 z7 Z) u0 k1 b9 b8 t
/////////////////////////////////////////////////////////// G: s$ R- n5 y) k
while (1) 7 T7 }9 B& y7 s' B ]' E {5 I" Q; W! r+ ~4 Q- h, A
//printf("好的"); ' t( E2 I3 n; I8 A8 d" y; _* v } 8 A/ m G$ H) V9 n5 e5 |& k}*/, p# d8 a" v* n7 t" y' d( \
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////- P7 E- m: p. b; X
FRESULT Test_f_mkfs(BYTE drv)//对卡进行格式化,驱动器号一般为0 . r2 K; M: V) [: T& t{1 }" ~, w$ G! g$ E% a
FATFS fs; // Work area (file system object) for logical drive 1 e/ m7 {& C8 ]3 \" W FRESULT res; // FatFs function common result code* _$ j- C7 U9 J4 z
5 ?# c" J6 `, k- S
//检测磁盘是否插好 - y% {0 S7 H5 d% Y; z% }5 i //if(disk_detect_OK()==FALSE ) return ; / i: m4 \. r ~- O: V" S //printf("\r\n inaert_ok:>"); 0 I% m- {/ R0 h, T* Y6 j // Register a work area for logical drive 0 8 W) x! V' I% t f_mount(drv, &fs); . q5 k# |2 p H3 ~ res=f_mkfs(drv, 0, 0);/* Create a file system on the drive 在驱动器创建一个文件系统(驱动器号,分区规则(0:FDISK, 1:SFD),分配的单元大小)*/ 0 q* L# _0 G7 W5 e) j //die(res); ; J# R/ `+ b! t; ^% o f_mount(0, NULL);, m' U. u/ W4 g2 R
return res; 0 Y& S7 G8 O" M' V} ' x1 e/ L' Q" K+ H//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ) W) T4 u# I4 t* Q3 Y! }3 b( mFRESULT Test_f_mkdir(const TCHAR* path)//创建一个新目录,输入目录的路径Test_f_mkdir("/dir");只能一级一级的建立目录 8 S) X+ s* V% i$ J' r1 W{ : O% Q/ X: r8 g6 V* T; C$ J3 z FATFS fs; // Work area (file system object) for logical drive 6 o6 P5 A) _% [) O+ i& ] FRESULT res; // FatFs function common result code* y- u: ~, K/ m$ _' q4 n+ A
F. _5 h1 J6 y' A" ^. J& V/ L; [ //检测磁盘是否插好 & X0 K; R9 _* Z1 T9 R //if(disk_detect_OK()==FALSE ) return ;: [; v" Y* _; h- u4 s
//printf("\r\n inaert_ok:>"); ) p: v' u3 F( U3 F H // Register a work area for logical drive 0 ! P X$ s$ {$ W7 M% X9 x2 q/ d, t f_mount(0, &fs); * h% x8 ` a, @9 T res=f_mkdir(path);//创建一个新目录 - `7 d) E5 \7 H1 Y% x R& I //die(res);$ c0 u R7 }3 k6 f- U* g& M
f_mount(0, NULL); - w. R9 A. V7 N9 c return res; 8 \: e7 o0 x$ m4 f# C}" C+ p& p" O# \
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////5 m1 k: q' J5 W8 O- p
FRESULT Test_f_deldir(const TCHAR* path)//删除一个目录,输入目录的路径;目录里的内容是空的才能删除Test_f_deldir("/dir"); ( A" J1 a! {* M N( t{5 q2 R T" U- Y3 Q. w/ G) _% s
FATFS fs; // Work area (file system object) for logical drive! E: C# e/ A6 s5 y" }/ @$ x
//DIR dir;* e9 a/ N- n2 f( N1 N+ w7 b0 C! U
FRESULT res; // FatFs function common result code ; j8 O4 t6 d. X$ p- M% D9 J0 X! V
//检测磁盘是否插好 . X8 M+ r' W5 a" Y9 A+ O7 J1 A! T* j //if(disk_detect_OK()==FALSE ) return ;2 }7 u' v$ `4 c6 y
//printf("\r\n inaert_ok:>"); 2 [' ?$ G; ^& p; @( `/ [7 c% W- T6 |8 O // Register a work area for logical drive 0 . [$ X- }$ o- [# J; y( `( M f_mount(0, &fs);' k9 M E3 L: ~4 K& H# n
//f_opendir (&dir,path); - c! ~8 `/ V/ i1 n( ?& U res=f_unlink(path);//删除一个目录 # h: \1 @7 K- C3 v //die(res); ! h6 |/ P1 q$ `9 u p+ I0 d f_mount(0, NULL); / X. G3 T6 G8 y7 \" ~/ b/ f; l return res; # p( l8 n# \4 Y5 J; b3 c} " \' ^" Z$ U- c; a+ ? p7 d0 T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8 Q. M& A+ ~2 D, j" i
FRESULT Test_f_readdir(const TCHAR* path,char (*filename)[13])//获取目录中的文件,输入目录的路径;输出文件名和文件夹名Test_f_readdir("/DIR",name);char name[5][13] ' w# j; k- v, u0 h{ d+ m& d9 n7 |9 Y& {, u U5 i J FATFS fs; // Work area (file system object) for logical drive % [: w2 W2 P- q" F% A) U DIR dir;3 @/ [0 ]. E5 l* V& b# g
FILINFO finf; 2 B$ |% n2 { `1 P) e. e FRESULT res; // FatFs function common result code 0 {4 f% j+ z8 U) c9 b7 ]9 R' e; P. n. g/ Q3 G
//检测磁盘是否插好% E- T0 d( L: J: O: G* ]
//if(disk_detect_OK()==FALSE ) return ;0 b" D; p# ^- Z
//printf("\r\n inaert_ok:>"); 6 D; f" U3 O: [( a // Register a work area for logical drive 0; ?, x: g% B4 z* Z
f_mount(0, &fs);7 d+ l. f" {3 l- v& n
f_opendir (&dir,path); ( [6 ~4 C2 g" h7 a5 c% T - z; N4 ?1 v- U1 { while(((res=f_readdir(&dir,&finf))==FR_OK)&&(finf.fname[0]))//获取目录中的文件 " ~! M, ^% x( T; |; A- f {strcpy(*(filename++),finf.fname); 8 @( H4 C( V. }8 J: p) E% W$ Q9 R //printf("%s",finf.fname); 5 j" b8 Z; y: i" j3 c }' k9 M" c2 D4 Z5 n, {4 W' F
//die(res); ( r8 p I6 y! i/ T- h' M: w f_mount(0, NULL); Q0 z7 |* E& \% G5 H, O return res;- n. o8 K. f& {9 Y
} 9 O5 b1 k" F {- |1 N& w////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////, j5 s- k: `- M( V+ U3 M
FRESULT Test_f_creat(const TCHAR* path)//建立文件,输入文件路径和文件名 4 a+ l3 z0 P; h S( Q: ~) n& F/ G{' ^- j3 T" ]% V% ~. a3 ]1 y
FATFS fs; // Work area (file system object) for logical drive( F/ n9 L) Y7 B5 ~7 i' R/ E
FIL file; % u! w) i: c- S6 r$ f7 L4 z$ g FRESULT res; // FatFs function common result code a# d: `0 D7 t6 A0 O
) @9 a$ {5 j; j5 D R1 p9 v
//检测磁盘是否插好( j6 `, @' t& `" Y
//if(disk_detect_OK()==FALSE ) return ; ( V, x! L1 Q, b* `5 D0 \4 A //printf("\r\n inaert_ok:>"); - R' E; i9 U) B Q // Register a work area for logical drive 05 @0 e8 X# m1 ~& V d: }# G$ N
f_mount(0, &fs); ; z0 f2 A5 o0 F8 Z% w res=f_open(&file,path,FA_CREATE_NEW); //创建一个新文件。如果文件已存在,则创建失败//FA_CREATE_NEW创建一个新文件。如果文件已存在,则创建失败。' l8 u6 x; |3 f0 [; M4 _
//FA_CREATE_ALWAYS //创建一个新文件。如果文件已存在,则它将被截断并覆盖。 9 @: q" w5 [! W+ L; _1 @) A //FA_OPEN_ALWAYS //如果文件存在,则打开;否则,创建一个新文件。% }' U# C$ ~+ I6 _: y
//die(res); - T4 M/ R; }: O f_close(&file);//关闭文件 ; M1 D8 k8 o0 E9 {! k* f7 ? f_mount(0, NULL);& B, u, S, ?4 C- c
return res;& y q# r. @. b- z: n$ g+ r
}3 Q- ^8 s% E) p3 Q
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + W" {' ]- b W6 ]FRESULT Test_f_delfile(const TCHAR* path)//删除一个文件,输入文件的路径;Test_f_delfile("/dir"); * c1 v; U# x, \4 A$ _" k
{ . Q8 F4 ]* o% F6 s FATFS fs; // Work area (file system object) for logical drive , J' U. \/ _1 w- b- [ //DIR dir;2 F( b& y# t" c8 [; C/ Y! c/ a6 M
FRESULT res; // FatFs function common result code 5 X# M* T0 T. L# P2 b g( ?8 z/ W4 ], l/ q6 K5 |
//检测磁盘是否插好 ! E. }$ E6 f7 k //if(disk_detect_OK()==FALSE ) return ; 0 F0 l" T8 d0 e7 z0 X* N //printf("\r\n inaert_ok:>");" i; s8 b x3 a6 v2 z/ `' c5 Y5 w
// Register a work area for logical drive 0 `+ N' ^) m+ F6 A* X6 ] f_mount(0, &fs); & Q% `: z% B8 F //f_opendir (&dir,path); 7 F% [& }; @; j: o res=f_unlink(path);//删除一个文件+ y3 F* H' c" z6 g# u
//die(res); }) m H6 J4 c7 I" g f_mount(0, NULL); 1 y" T( D7 ]* d: X5 n7 Z- v return res;& h, o7 y* F) q M3 ~7 j' E. e
}6 Z' u' L9 E) ]. W7 N# m- [
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0 G. b" V2 g. h4 S
FRESULT Test_f_readfile(const TCHAR* path,char *buff,DWORD ofs,UINT strl)//读文件的数据,如果没有此文件则返回错误;输入文件的路径名,内容缓存,读取开始偏移指针,读取的字节数0 k+ N, K% S4 `: W9 N
{ //Test_f_readfile("/dir/r.txt",str,0,sizeof(strr));2 A/ j" }- x( a( w* B8 L
FATFS fs; // Work area (file system object) for logical drive % g& T1 _8 A: q FIL file; // file objects: `9 A J; |* t. [/ y M" w
FRESULT res; // FatFs function common result code1 b, e% @" J' y" r; j* m
UINT br; // File R count 文件读回的字节计数4 f( l; l, v& {5 z7 R: T3 T. P9 A
//u16 i; 3 ~$ t# b" Q* r7 e+ I9 B( `% `' ^% o //检测磁盘是否插好( x) l' \" c! a7 F2 }+ j
//if( disk_detect_OK()==FALSE ) return;( m! E" Z6 [% o& _0 r5 J
// Register a work area for logical drive 0 0 O3 M) X5 C6 e3 Q: ? //for(i=0;i<sizeof(buff);i++) buff[i]='\0'; 6 f% V) \& O; s7 [ f_mount(0, &fs); S9 \" T+ U: d6 I. ]' z. r' O //Open source file & T* t6 Q+ S! ~1 z res = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);//打开存在的文件,如果没有则返回错误 . c! H8 T+ U5 S$ ^$ V e y //die(res); 7 ]% W' G; S9 G$ o5 x& H8 X res = f_lseek(&file,ofs); //指针移到文件ofs个字节处7 B9 t/ ^2 L/ U3 l& T
//buffer空间设大一点,会提高读的速度。" H8 O7 Q# P& F! }1 f
//如果文件实际大小512byte, 2 _# t0 P7 d- B% |5 f1 j //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。7 T2 G" T+ G6 ` X/ g+ y# R& r( M
//for (;;) $ Y4 a z4 z0 \1 J% @/ a! G( n4 u
{ " V6 }/ q' J% r- d2 Q' z. O //for(i=0;i<sizeof(buff);i++) buff[i]='\0';//清除缓存6 f3 D' S# s$ N0 ~; Y
, h7 p" p( y1 U" F! h9 S0 h res = f_read(&file, buff, strl, &br); e: F y3 j. x8 r) ] //if (res ||(br == 0)) break; // error or eof如果错误或者到文件末尾则退出 , F1 R& y9 M1 F% i& _2 E6 u 4 I; m. C, s: A4 b+ z! J) z //printf("%s",buff); ' E+ r |* Z9 ^7 S
} K0 Z) |0 Q2 p% F // Close all files* l; y# T3 _4 }9 m) S1 i& \5 q
f_close(&file); 8 Q' K. @2 z: i( ?" G H' S // Unregister a work area before discard it ( W+ L8 U( Z0 |/ J. e3 S+ _ f_mount(0, NULL); 7 J- } |- Q7 Z* \' [ return res; 8 A, J2 K3 H7 h: T# c5 o9 W) _}) n8 v; t. H, f) e0 l
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3 n9 p" A" W2 e" }6 M4 t; S
FRESULT Test_f_writefile(const TCHAR* path,char *buff,DWORD ofs,UINT strl)//写数据到文件,如果没有此文件则创建文件;输入文件的路径名,内容缓存,写开始偏移指针,写的字节数8 B, a% c+ d/ R
{ //Test_f_writefile("/dir/r.txt",strw,0,strlen(strw));$ v5 c! x4 P7 p
FATFS fs; // Work area (file system object) for logical drive. b' l! K) t/ n! @) z; ]
FRESULT res; // FatFs function common result code ) [ k1 U/ W% ?" J7 Z8 D: L FIL file;& y# G L* U+ L& ^: O, x9 E; P8 m
UINT bw; //文件写入的字节计数6 u7 @3 v) g$ q" T1 p. j
//检测磁盘是否插好 7 f; _. S; {% Z8 L- {9 M //if( disk_detect_OK()==FALSE ) return;& t% e4 [( B3 s4 X2 y
// Register a work area for logical drive 0 ) u3 T' z7 d! l, }' V. \* b f_mount(0, &fs); ( O3 |2 h- ?5 ?1 ?& D res = f_open(&file, path, FA_OPEN_ALWAYS | FA_WRITE); //可写方式打开 没有文件则创建 & t, D$ Y9 h8 v; J. s //die(res); 0 P- h6 L5 w' l. L res = f_lseek(&file, ofs); //指针移到文件ofs处;输入file.fsize指针移到文件最后 $ d2 Q' }4 S4 x |; p //die(res); 0 F- M6 `# q/ S; b res = f_write(&file, buff, strl, &bw); //每次需要写入的数据字节数;如果btr为strlen(buff)则写入所有的字符 - J( u: h8 _* a$ m$ d7 @ //die(res);) o3 `. h; L4 {! h# w, i
//res = f_lseek(&file, Make_file.fsize); //指针移到文件最后,一边再一次的写入 . q& O% j* f- o: R# [8 {
f_close(&file);//关闭文件 6 [# Z/ o- ^ n. _8 b" K/ g // Unregister a work area before discard it 6 ~+ H" u: h4 Y8 i f_mount(0, NULL);5 L: [0 k" o- Q! V
return res;/ v( b2 s* K1 s/ y' F
} : v6 i. [2 a0 d3 y$ h////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////% s8 M( v& _/ [* G& v& P( P
FRESULT Test_f_getfreem(DWORD *freem)//获取卡的剩余容量单位为M6 X1 B" x0 q" ~: D: T
{ 3 z( x2 r$ D5 u& }3 D: z, N FATFS fs;+ G. U" y& z0 l D1 R5 f
FATFS *pfs;" B: H7 C, Q/ q% C6 A ]6 x
FRESULT res; // FatFs function common result code/ t" {9 r- _, }1 }. `: W4 A4 s
//检测磁盘是否插好 3 r9 Z& T5 I0 h4 h //if( disk_detect_OK()==FALSE ) return; 8 M" ^% {" S. }1 O9 r- r // Register a work area for logical drive 0 + z7 E8 s! w3 x+ S5 n pfs=&fs;//指向( z& C9 g2 z" Y+ R
f_mount(0, &fs);//安装FATFS,就是给FATFS分配空间 ) C3 Z; c; X1 G+ \ // Get free clusters1 t* j# H! a9 P- N
res = f_getfree("/",freem,&pfs);//必须是根目录,默认磁盘0;"/"或者"0:/"9 N2 H }, Z4 A9 @1 I5 {% w! _/ p6 J; W
//die(res); - S d2 T6 i, e: B i ~ if ( res==FR_OK ) O$ L9 O: X; o* e7 ^3 P! c {- r6 ?" S3 A' S8 f) R& o
// Get free space. Y# R! J/ v* Y4 w* u# o
//printf("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",* S7 r2 S6 I% }
//(DWORD)(pfs->n_fatent - 2) * (pfs->csize) /2/1024,//总的磁盘空间M =(总簇数-2)*每簇的扇区数/2/1024=可用簇数*每簇的扇区数/2/1024 4 k* r0 i- S# ?7 @: _7 e //(*freem)*(pfs->csize)/2/1024);//空闲的磁盘空间M=剩余簇数*每簇的扇区数/2/10244 s u: X$ o5 J& T) I
*freem=((*freem)*pfs->csize)/2/1024; * R( j& P/ X, c+ F }( k: o8 r8 k( k: p Z$ z
//else die(res);//测试函数执行结果分析) B2 n* o0 A9 u9 n- f; Q# Q
// Unregister a work area before discard it. ?' w% y7 \: w F
f_mount(0, NULL);//卸载FATFS,就是释放FATFS结构体所占空间 ' I$ c0 Z& ~' R9 H* A8 i, g return res;6 ?- @3 ~6 `+ `" G1 X
}4 E* y' G. D: r. t
6 @3 x8 J. M0 ^ 8 K1 i; }! {0 G( T! p S: X9 U& Q" P7 ?' w& n' K
/ Feb 26,'06 R0.00 Prototype.- o8 c, M7 B6 u, B1 T
/* h, v- C2 `" N: |# z) Y. i9 `5 t
/ Apr 29,'06 R0.01 First stable version. , k1 G' X8 P+ n' F/! v3 d Y) d% u2 V
/ Jun 01,'06 R0.02 Added FAT12 support. / m6 K @; t% [* { t/ Removed unbuffered mode. : D- r: }5 v' z7 |! W: f( D/ Fixed a problem on small (<32M) partition.$ H. B/ `- O+ ~$ e
/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). 9 k/ O% r) M: N& o& J/1 B/ U: B# c, I. H$ U/ [/ {# q k- S9 V
/ Sep 22,'06 R0.03 Added f_rename().1 b0 J0 v" c% q6 _+ B
/ Changed option _FS_MINIMUM to _FS_MINIMIZE. - T. w9 k3 ~/ H: ^/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.( R. k; z8 q: A- n0 ]1 f
/ Fixed f_mkdir() creates incorrect directory on FAT32. 9 i0 g7 ~, k$ z; g i* Y/4 R2 X& U3 F' I7 i: Y) p; m! N% j' x
/ Feb 04,'07 R0.04 Supported multiple drive system. # ?+ R7 I! y, j5 ~5 { t. G5 b. h; a/ Changed some interfaces for multiple drive system. , d3 W6 I* }; m! |9 ], L' x/ Changed f_mountdrv() to f_mount().1 {2 h$ ?2 G. m8 R) A
/ Added f_mkfs()., i) d9 _8 v/ {9 k9 m+ O
/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. ( ^) O( v& w1 z- o+ @/ i$ n/ Added a capability of extending file size to f_lseek().$ q: l3 J+ }+ q7 s0 l: L0 f
/ Added minimization level 3. 4 p9 H8 S9 ]3 l1 t/ Fixed an endian sensitive code in f_mkfs().5 s* a" |! X" s$ q0 S
/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.: z% N8 `, X- ]% ]) f
/ Added FSInfo support. ; d: ?+ I' n/ p! R/ Fixed DBCS name can result FR_INVALID_NAME. " `+ K& z3 o8 _/ Fixed short seek (<= csize) collapses the file object. & |5 m. Y' @" A6 [5 x0 n; u! {% y* F/+ p% ^3 F3 J: A
/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). ( \" ~0 N8 S' w: ^! ]9 n9 J7 I/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. / R* |8 v9 e. U- {* `7 M/ Fixed f_mkdir() on FAT32 creates incorrect directory.9 g6 e3 [ X0 E( s1 X. W
/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().4 f! |, }# T m' k) h$ w
/ Fixed off by one error at FAT sub-type determination.. m. o1 {3 X& k
/ Fixed btr in f_read() can be mistruncated., B$ Y. a; M/ p0 A2 h0 l
/ Fixed cached sector is not flushed when create and close without write.' o2 ~1 c% K; K5 N" L
/ 6 C/ k) c) y" O1 G- s" S+ N/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets().- I8 N4 G" _6 j1 l ?" Q
/ Improved performance of f_lseek() on moving to the same or following cluster.6 \% F7 J: h! Q( v
/ _+ B& O) Z7 C" S5 ~/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) & d( M# |* W6 d9 E3 _3 b/ Added long file name feature.# Y# f, [2 K; Z
/ Added multiple code page feature.. b6 R4 y7 O& q g) \7 H; v, e' n
/ Added re-entrancy for multitask operation.# [( E0 R Q u
/ Added auto cluster size selection to f_mkfs(). : a7 w3 w; C+ v/ Added rewind option to f_readdir(). 3 }1 N: a3 f z' ~0 w1 _+ x7 H/ Changed result code of critical errors. , R" k4 F1 u7 k6 E0 L1 b+ y/ Renamed string functions to avoid name collision.! `5 Y o0 t. u$ p2 ?! N' l, B
/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. 6 T7 `% b& T, I6 E$ @- A2 k7 O/ Added multiple sector size feature. R6 L' X L( ?
/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.2 L# L' N" ~5 f _5 t
/ Fixed wrong cache control in f_lseek(). ) P$ ^; o$ h( Z8 N- F$ E/ Added relative path feature. ( H$ a# C; N# w0 {+ g/ Added f_chdir() and f_chdrive().% H" {; [9 L; c1 t
/ Added proper case conversion to extended char.- S: k: [2 K4 n9 ^
/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.% c. t8 k+ n+ ~# a8 R
/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. 1 G/ b% ^2 A1 c/ G/ Fixed name matching error on the 13 char boundary.% C9 T( B- o# N. k- \
/ Added a configuration option, _LFN_UNICODE. + A! R; `; w3 i, Y/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. & K' [8 H+ e# Y- Z9 n/ & c: i O* I. p2 F% Q/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) , M- d# `2 S/ O# D/ Added file lock feature. (_FS_SHARE) ' M/ [# j0 L1 K2 m* d/ Added fast seek feature. (_USE_FASTSEEK); q" M9 _6 s& \. C- z! B
/ Changed some types on the API, XCHAR->TCHAR. ; I$ \, g1 U4 B/ Changed fname member in the FILINFO structure on Unicode cfg. ' D* K0 d' C4 r. V) C8 B. l9 v/ String functions support UTF-8 encoding files on Unicode cfg. , H! |2 Q2 q; |/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)2 M$ e; X; d, E
/ Added sector erase feature. (_USE_ERASE)' V* p' p) z5 e: ~
/ Moved file lock semaphore table from fs object to the bss.2 L" ?" L l$ P3 s! f( B6 Z# t* s: L
/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. ; M& J o7 d4 y0 B# d! K/ Fixed f_mkfs() creates wrong FAT32 volume. 5 \3 l/ Z. a: ?; U) Z3 {( _/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). . O) y6 G; @ s2 |; P# ~/ f_lseek() reports required table size on creating CLMP. ' t0 y' d2 p. x/ Extended format syntax of f_printf function. ( @3 Z2 U; m. [1 ] b# y8 g8 ~/ Ignores duplicated directory separators in given path names.( j9 H5 h- s) m
/& i% C8 A7 g1 @3 ~3 \5 k$ O) l
/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. 1 f, z4 v, K9 f7 {" T: [/ Added f_fdisk(). (_MULTI_PARTITION = 2) # I2 d) v8 J; J! I8 _8 W6 L0 C5 G/---------------------------------------------------------------------------*/ 6 S) p! N( a A- c% J! z. Z) Y5 Q& ?' T" \9 O. L# j* A! L0 J7 \" J) `