你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码  

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习. z9 e+ m5 {  f
详细内容请看附件6 x+ Q8 Y$ q* D4 ~% [" g8 C6 [1 }
+ L$ t8 _" g0 e4 s4 r
本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
4 N, V, k  X- h* f3 ?; G: }4 e         : F; U1 l' c4 T* S- U' N- K
4 T, c# g5 p# i4 K
最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需
1 P  m! O* ~% a" `  M0 ~  ^8 _
要调用FatFs Module 提供给用户的一系列应用接口函数,如f_open,f_read,f_write 和f_close

) @! v9 h. U. a9 o' P! n  l( e
等,就可以像在PC 上读/写文件那样简单。
! q# i# W1 |' Z  d
中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c、

4 C2 Q$ d" `; u+ K; n7 o, J
ff.h,简化版Tiny-FatFs 提供的是tff.c、tff.h。除非有必要,使用者一般不用修改,使用时将

. L; \7 U7 m% f8 M0 o
需要版本的头文件直接包含进去即可。

2 R3 N7 L2 a5 \; _& ?& J1 m) t
需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写

3 M8 K' |0 E9 @; L0 U
接口Disk I/O 和供给文件创建修改时间的实时时钟。
8 y7 n: G% n& h5 C
* A7 _! H. M7 {  E7 z$ k
                        本例程的程序结构图
2 c; d- j& X; Y0 K
                  
4 P, j& \1 G; Y5 E0 U8 I
! ?& T" t/ P" ~; N7 N8 l( k
RTC_time.c
6 S% r0 B$ D2 v2 F' q: D
Diskio.c

6 t: O* p* I* U% ~# @
SD_driver.c
" z" T/ a) B; y' b- b7 y
ff.c

4 S& ], `5 G3 g) P1 P
fatfs.c
7 r& Z+ D+ v7 \- }) @9 _1 Q

: [: I3 Q& m5 x+ v9 u
程序的编写
1 `' p0 G$ Q. @: i6 t
下面我们开始代码的编写:

3 h1 Q0 X: [3 s. ]. ]1 C- J
1、  主函数的编写
* @, |' z, R( I
int main(void)

) o; L  t# o& p" d* Y- }$ z) i
{
4 E/ f, s9 v# t  Z, z
  RCC_Configuration();

" C7 M; k* H, ^( y* y" B. ~' Y/ w
  GPIO_Configuration();
' K* k- @; `% v9 t$ L4 q
  USART_Configuration();
, V' n: b1 F2 _8 B/ e9 y
  SPI_Configuration();
# P0 F! O% U: C) p' m7 R; c5 L
  FATFS_TEST();   //FATFS常用功能测试函数

+ Q) p3 C; V# \: A+ |
  while (1)

$ Z- q; X* W0 [
  {

, m- T$ R% \6 x9 o7 R1 n! K
  }

4 y6 u% _2 e- {5 \/ U+ Q
}
: T: c8 F6 W1 g  I! z. b
这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:
/ _8 u9 V8 R9 d  l$ h) l" Q+ a
void SPI_Configuration(void)

; X: E$ t9 E6 _; X
{

! `8 P5 v5 p8 T# H. W1 ]
  SPI_InitTypeDef   SPI_InitStructure;

; a# ~1 w3 B0 \! @9 U" b7 A
/* SPI3 Config */

8 P2 V. k6 _8 p" q+ W$ o
    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写
. w- y& y( O  p1 |/ L, K
这里使用文件SD_driver.c和SD_driver.h来写出SD读写的一些驱动函数。
( J9 |* k( w- `' A. O( n+ H  h
函数列表如下:
$ H" `7 f2 B- _- R- i0 i0 r8 q. m$ X
/* Private define ------------------------------------------------------------*/
# h) O! l2 Q1 r% i
/* SD卡类型定义 */

9 y# V% d$ i0 ?2 l
#define SD_TYPE_MMC     0

5 q( q9 h! I6 R3 D. ?
#define SD_TYPE_V1      1

9 {9 J* {* v! r
#define SD_TYPE_V2      2

& _; h! N1 a' C0 ^; J
#define SD_TYPE_V2HC    4

2 G! {  K2 w0 I6 s' b' Q( v, [ 9 E6 d8 N  u3 e
/* SPI总线速度设置*/
5 f$ I8 g( S2 e  h% w) S
#define SPI_SPEED_LOW   0

7 [) u1 r1 r- c4 G' l
#define SPI_SPEED_MID   1
$ D: ?& U, A. g' O1 X
#define SPI_SPEED_HIGH  2
7 J) |  j1 w. ~. _
/* SD传输数据结束后是否释放总线宏定义 */
" P7 X2 M- t9 `
#define NO_RELEASE      0

' J- C- g; x% B4 S* ]1 p- S" B
#define RELEASE         1

$ ^% v- i1 ~* ~1 z 4 H5 G$ k+ t# v# \6 r2 a
/* SD卡指令表 */

& J1 ]% I. |% N- X7 m$ p1 u
#define CMD0    0       //卡复位

: y* y+ ~/ s2 k; H8 U
#define CMD9    9       //命令9 ,读CSD数据

' o  k0 k$ i8 P9 A2 ]% S1 W
#define CMD10   10      //命令10,读CID数据

1 h: _3 m9 k8 J  l
#define CMD12   12      //命令12,停止数据传输

- H( I/ W4 L! B! `* q7 P2 y- K$ o) c$ y
#define CMD16   16      //命令16,设置SectorSize 应返回0x00

* c+ |. G+ e9 w% V1 f8 V
#define CMD17   17      //命令17,读sector
8 F0 Z* W/ K' k3 w* z
#define CMD18   18      //命令18,读Multi sector
5 |9 E7 O" |' r  K+ `7 E
#define ACMD23  23      //命令23,设置多sector写入前预先擦除N个block

7 }) s3 s% d* n" {% t
#define CMD24   24      //命令24,写sector

" ~& c/ S6 _. N6 o
#define CMD25   25      //命令25,写Multi sector

0 B6 l+ D) g  u
#define ACMD41  41      //命令41,应返回0x00
2 x# l" i) D1 S9 t, a8 N- ~
#define CMD55   55      //命令55,应返回0x01
) J5 {( N+ r5 O
#define CMD58   58      //命令58,读OCR信息

# X8 r4 c& u. @+ \
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00

; h' p5 C' o2 X   L- Z. C7 |0 t) n& K8 W0 ^
/* Private macro -------------------------------------------------------------*/
7 C  V( T7 u" _) [# U, m  s
//SD卡CS片选使能端操作:

. y) D1 l. q/ s6 h  ?
#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD卡
( _* ~$ R) A2 R& |; Y5 _
#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD卡

- M7 n! q5 e: ^6 y
#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电
( r$ x9 x/ j, `4 O; q8 w; V+ Y+ {7 q
#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电
( c0 e! |& |7 _. U3 w
#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡
3 O6 T" U$ |( V' s, i# g4 f! i
                                                                    //1-有 0-无

( Q* g5 _& r! J( h+ G % S# c/ [) H9 ^2 h, d. }
/* Private function prototypes -----------------------------------------------*/

5 b. \% I" p* ]- Y, V8 q
//void SPI_Configuration(void);
0 }1 o5 K# {6 M8 V* G3 s
void SPI_SetSpeed(u8 SpeedSet);

; N6 p6 c3 o: F2 d
& F$ U3 Z- B- a- u  Q
u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节

. O3 k) E, s) @% W
u8 SD_WaitReady(void);                          //等待SD卡就绪
% O' d3 N4 Q/ j( p" s8 N, u; H
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令

2 f; |( D8 t$ }3 h! K
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);

" I- D9 h0 O4 X
u8 SD_Init(void);                               //SD卡初始化
9 Z6 f1 u  h/ W$ N5 Q
                                                //
, `( y# J; H* m, k5 T0 I* ]' P" A
u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据

4 m2 ?; C( ~; T+ P8 q- C) v* D* B- u
u8 SD_GetCID(u8 *cid_data);                     //读SD卡CID

' R" O' Z7 X% ^) ], x. N
u8 SD_GetCSD(u8 *csd_data);                     //读SD卡CSD

9 U8 H7 K6 t: L, n1 x& P& n, _- i
u32 SD_GetCapacity(void);                       //取SD卡容量
- }6 U* ?: T2 _. |5 {  F

2 e! y; _3 m$ I. _' A: o" Y9 f
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector

) w, g( S- F* G5 t1 X9 c" `& M, A- |
u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector
6 [( @' V9 l( ~+ l& D. v2 }( K2 B5 U
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector
; b# H9 |( a- ?, U: e, }0 s
u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector

: ?4 ?. f! Y9 t: {! a% a4 W  t/ b
  G' H( M2 k8 ^9 z# g
3、  文件系统的移植
/ K1 ^8 E& q: ?4 a
FatFs文件系统主要有以下函数:
+ R. W1 w1 \1 m, J0 F6 Q
/*-函数详细的解释请查阅附录,点击链接也可以到----*/
( ^3 x  O: E3 @
/* FatFs module application interface                  */
- g. G6 _( U+ C, Y/ R; o

% {  A0 r( V( P! X  L: j
FRESULT f_mount (BYTE, FATFS*);                                  /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const char*, BYTE);                         /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*);                        /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*);  /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD);                                           /* Move file pointer of a file object */
FRESULT f_close (FIL*);                                                                      /* Close an open file object */
FRESULT f_opendir (DIR*, const char*);                              /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*);                                             /* Read a directory item */
FRESULT f_stat (const char*, FILINFO*);                             /* Get file status */
FRESULT f_getfree (const char*, DWORD*, FATFS**);     /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*);                                                                /* Truncate file */
FRESULT f_sync (FIL*);                                                              /* Flush cached data of a writing file */
FRESULT f_unlink (const char*);                                             /* Delete an existing file or directory */
FRESULT    f_mkdir (const char*);                                                    /* Create a new directory */
FRESULT f_chmod (const char*, BYTE, BYTE);                    /* Change file/dir attriburte */
FRESULT f_utime (const char*, const FILINFO*);               /* Change file/dir timestamp */
FRESULT f_rename (const char*, const char*);                 /* Rename/Move a file or directory */
FRESULT f_mkfs (BYTE, BYTE, WORD);                       /* Create a file system on the drive */
0 F8 B# U+ a8 F7 b! t/ }* k/ X
: g7 M7 A: P3 O. D+ ?# t1 L4 V2 q
4、  底层接口I/O函数的编写

# @( }+ N1 H0 m
底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:

3 F5 R7 t# e3 Y; ^" k4 ]9 H2 O0 R
/* Prototypes for disk control functions */
- a3 g1 P1 r" i, E2 n
DSTATUS disk_initialize (BYTE);

+ D2 a' j. Z2 ]
DSTATUS disk_status (BYTE);

1 L6 B) m6 {1 Z3 ~3 L' h/ \
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
; u! C* H7 o6 \4 g( y
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
  p# r9 o- [) \5 C* T/ v
DRESULT disk_ioctl (BYTE, BYTE, void*);
4 Y# ~9 }) ~! n, K" N" s
DWORD get_fattime (void);
1 P  z& g- s0 q# j+ Z& M
6 个接口函数的详细信息如下图所示。
% b3 b; W- Y6 \! {7 l
Disk I/O 函数结构图

0 q9 ?0 G- i8 d, s
因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。

+ C* h( ]+ x' ~9 ]+ s
1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime
( ~* e5 a# E6 X2 w. A8 ^! t
5、  应用层函数的编写
- H5 g" t5 s- \6 |: l  p# A$ i8 N
我们这个例程要实现的8个功能如下:
) c/ A% Z9 k& h0 f
1 q7 Y% x% `! u, m% ^- U( U3 g/ Y' F
每一个功能都对应一个函数,各个函数如下:
( H; i" q% R# X$ ~$ n3 a
// 0  读取磁盘容量 The f_getfree function gets number of the free clusters

9 W7 V/ |, b4 h
void Test_f_getfree(void);

( s8 w/ `' U' T+ a
//1   读磁盘目录 The f_readdir function reads directory entries.

# a4 }8 A4 ^2 v2 l$ b* r. a# x
void Test_f_readdir(void);

6 e# X: [+ o! n# n; N; k: b
//2    创建目录   The f_mkdir function creates a new directory
8 L% g+ I; t6 [
void Test_f_mkdir(void);
) R" u* s) Q: t- |6 \- {- Y
//3    读取文件   The f_read function reads data from a file.

3 }3 {& O  J! g" }+ D  W: K
void Test_f_read(void);
6 t& V3 Z& n! K; W7 }
//4    文件拷贝   The f_write writes data to a file.
; P  i6 Y- V3 a: F) B
void Test_f_write(void);
8 u4 g) A. [7 Q3 t( x
//5    重命名    Rename file or directory

) o+ f/ u7 U! [
void Test_f_rename(void);

% Y- ^6 f" x6 A  [  ^  {" u9 n" T% e& V
//6    删除文件   The f_unlink removes file or directory

0 _2 p7 P7 ?+ l/ n
void Test_f_unlink(void);
4 p1 b# `$ [9 J% n: |' q
//7    格式化     The f_mkfs fucntion creates a file system on the drive.
3 V, l1 G' `, }" _# Y8 o" Q8 b
void Test_f_mkfs(void);
% j# U( D) f4 u' I

# L: m& C* X' r& Q$ X( k
: ~6 r/ C' ]( H! L
这8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:

! J  _' r  j* L, B5 X9 F9 p2 G
void *FATFS_Function[][2]=

. i& Z5 T4 V9 }7 @2 r
{
4 J: e& t$ G+ n7 ~2 Z, {, s" v; L
    (void*)Test_f_getfree, "磁盘容量",

/ ^1 Q; [: l$ D7 F: y
    (void*)Test_f_readdir, "读目录  ",
3 Z; s4 X% C( Z9 f* D" P6 r
    (void*)Test_f_mkdir,   "创建路径",

( I( x& a0 h9 A3 f8 y" P; R0 ^
    (void*)Test_f_read,    "读文件  ",

/ P" |! g* _" z; t; J. M: d% R9 R* |/ O
    (void*)Test_f_write,   "文件拷贝",

' a- `9 |( Q; H9 X
    (void*)Test_f_rename,  "重命名  ",

* e+ R  A' H0 ^1 H) d* O2 L( f
    (void*)Test_f_unlink,  "删除文件",

% ]8 Z( r( e6 M& f- A  {& c/ ]
    (void*)Test_f_mkfs,    "格式化  ",
4 ]0 O7 D, ~5 _
    0x00,0x00
- {6 ?2 h" w, k! M0 J
};

+ S. G* Y" c  @/ q3 y" z4 B! S9 u
这8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:

- T* z5 y% W8 j- D
0)//The f_getfree function gets number of the free clusters

3 a% w: w% }; t) o0 ~  A
void Test_f_getfree(void)
/ s% P/ x3 A6 h' ]$ x* k
{

. T$ f$ ?& B) P; B
    FATFS fs;

9 M+ v# B3 W# r& o# J& x3 v6 J
    FATFS *pfs;

1 j  Y' {% m1 R9 u
    DWORD clust;

; p2 i5 |: t3 l' h& W' s2 F  t" c
    FRESULT res;         // FatFs function common result code
1 n2 K3 H* b. u4 A) ^7 P

/ g7 n$ D3 S$ s/ x  K6 i  F  t/ \, w
    //检测磁盘是否插好
4 a6 G# x) f% v+ {2 v
    if( disk_detect_OK()==FALSE )
6 y3 w. n2 ]# d. Q2 T
      return;
) \, i3 i1 h) I/ g
- A, x# j- U8 a' P1 o5 r5 I
    pfs=&fs;//指向

8 q* _/ J) k( s) f7 g; {' Q4 R/ T
// Register a work area for logical drive 0

# h4 S% F$ z/ U6 K  G" w
//温馨提示:该函数是文件系统FatFs里的函数,详细说明请查阅本章节最后的附录,可以用Ctrl+F快捷键,弹出搜索框,输入该函数名,找到该函数。以下类似函数均可以这样找到详细说明,不再赘述。该类函数我们会标记红色,并加粗,请留意。比如f_mount, 解释如下:

  |* J! A$ F# s% f/ |
  j4 n, n1 G! t3 Q) u

; s# {5 C7 P- K4 x8 ^
f_mount(0, &fs);

/ i) J' o( |$ l+ B8 d: Y# N% |3 E

( v/ w, Z$ D, c( e7 R5 i: X* y. Y
// 获取空闲簇Get free clusters ,空闲簇的值存在clust
6 p$ z& j! ?  h, n# q1 X) E! b
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0

8 ]5 i6 Z# R% a3 K# n- y' X" w" q' S/ H: {2 ^' J
    if ( res==FR_OK )

0 t. n6 q7 m, a/ l1 I% B/ I
    {
3 G+ ~  q; ^2 v& \
        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小

$ `( ?# N- P( `# p& B5 ?, U/ q
              //计算方法:

7 X4 r* q, [, V$ G" R; [
//   总空间大小   最大簇数×每簇的扇区数÷2÷1024

7 `  ~7 j( w2 [3 \/ U
//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024

7 |1 j' I* r- k2 W- U4 e
        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",

7 b3 y) N; W2 A- U6 O& O5 j
        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,

( I! F; Z2 G. u8 }
        clust * pfs->csize /2/1024);
3 H2 ?# u; V" \& v8 O. o
    }

7 H4 g( J) f2 J0 e. c0 _
    else
" T0 J  `. o! |- q
      die(res);//测试函数执行结果分析

1 o* D- q: {* P $ X0 M8 e$ G, P
    // Unregister a work area before discard it

$ n; }7 U1 K" g1 L: u5 M
    f_mount(0, NULL);

* F1 d/ b+ k  ?$ {- O" h
}

- l9 L+ J3 A+ ]* `6 _7 E4 u' p 6 o+ K' f2 c' L5 p: I+ T' y( J

. i7 @( u2 \9 x" f* s! w; O+ }0 p
' ?& x; s# b% e9 ?. ^! \
//1  读取目录 The f_readdir function reads directory entries.

9 k& {$ o3 ?  H5 o9 I
void Test_f_readdir(void)
% N8 @2 G2 {$ V* c/ t! f8 L" M
{

" {0 e  L  ?( d$ u6 M! p7 [4 C
    FATFS fs;        // Work area (file system object) for logical drive

# n7 D7 u+ a+ y
    char path[20];

7 |+ T; U/ g" S, I9 M% x " o9 p- Y$ s" E/ ]0 _3 p6 r
    //检测磁盘是否插好

, |; f$ c' v# I: d: F9 X, H
    if( disk_detect_OK()==FALSE )
3 @, k: d: ?& a6 `! S4 c* G; B
      return;

$ r1 D$ g; Q# a* c: ~5 ~0 W, G2 O ! Z+ O# A+ p6 A) a$ y. O6 a# L
    f_mount(0, &fs); // Register a work area for logical drive 0
! s. [6 H8 A) {0 K+ L% ?& ?- T
8 [6 V0 |8 ~: ]5 n* S$ @# ?
    printp("\r\nread directory:>/");//默认输出主目录下的文件
; |( R; s# M8 [5 l
7 N8 l& q. A- i1 y
    USART_Scanf_Name(path);//通过串口输入路径名

- }# ~  D0 n, h" O( b% X
4 h1 J& z0 `* k
    //扫描当前路径下子文件夹,并输出到串口

5 b! f9 ]6 R" d, T4 w
    scan_current_folder(path);      

3 X( l5 x: r3 i* @
    //扫描当前路径下文件,并输出到串口
+ h) i  T* @# J
    scan_current_files(path);
' a6 p* _) l0 J0 K* `
, W% O+ {" u4 ]2 b
    f_mount(0, NULL);// Unregister a work area before discard it         
2 V" ^; @4 p9 n0 d9 v  U2 }
}
' a) {/ v6 w" k, w9 J8 G
! }- y$ j, s- z( x0 b( U' x: l
* G: o! {7 N4 E. ]. [
  Y5 x, P1 T4 N: I
//2  读取目录  The f_mkdir function creates a new directory

4 J4 l) ~& J% u. _7 }
void Test_f_mkdir(void)

2 v2 P; y' e2 }1 `( R! t
{
4 ~  M0 ?1 e/ B* H( p2 v2 s' ?4 w
    FATFS fs;       // Work area (file system object) for logical drive

7 J7 Z/ x: |, g; y/ [. \
    FRESULT res;     // FatFs function common result code
( c4 J7 \. s% g. K; z
    char path[20];

2 m7 M; h8 k2 h
    //检测磁盘是否插好

" T2 ]7 A# r; @: F
    if( disk_detect_OK()==FALSE )

1 d# A& [1 N% N# P( }9 i
      return;

' d3 q/ \) p$ @3 t/ r7 L6 b
    f_mount(0, &fs); // Register a work area for logical drive 0

6 F0 J# Y$ K! p+ x& ~) C2 U# T9 h7 R
    printp("\r\nmake directory:>");

/ P/ p8 Y4 u0 i. y& l" ^
    USART_Scanf_Name(path);//通过串口输入路径名
" a3 M! S6 }% I( x+ x* x
    res = f_mkdir(path);
2 `) \1 T. z  u5 G7 g+ X
    die(res);//测试函数执行结果分析
! O) A& q  [3 R7 g& V
    f_mount(0, NULL);// Unregister a work area before discard it

* P+ _/ s/ c0 \) @+ @
}

/ q! C3 y, Q6 p) o5 K/ ~; P+ R) I& }  s! f2 p( {
  F) e) t# h$ V: D1 H8 c
//3   读文件 The f_read function reads data from a file.
8 m9 a* K3 N, f( J7 S, F
void Test_f_read(void)

7 T' ]+ c) L, W* D% H0 w6 c
{
8 t, B$ x: m. L  k$ x' L, A
    //用来记录读文件起始时间、结束时间
: ~, F5 q* j" l' Z# H
    struct tm time_start,time_end ;

1 t4 t* W; g7 c
    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。

) W/ s0 l& c0 P* G) i6 T
    time_t unix_start,unix_end,interval;
/ T6 v9 Y$ m) d, ?
    char path[20];
$ e' ~& O! j# l2 \- W
    //检测磁盘是否插好
1 R3 w: n" R7 r" \& x! N# B$ f
    if( disk_detect_OK()==FALSE )
& S" m) K; F" _2 ~: @
      return;

$ S: j2 S4 s6 d6 F- _
    //printp("\r\nread filebbbb:>");

1 m9 D% k, @2 n* ^! x
    // Register a work area for logical drive 0

7 l- ]- w6 t0 U! |. s4 Q' J- t
    f_mount(0, &fs);

" E0 m8 G$ [: I+ Y3 M6 c& V* H$ E+ ~$ W$ y- O: Z  M
    printp("\r\nread file:>");

3 m+ z+ N4 U9 [. D/ b( t1 z
    USART_Scanf_Name(path);//通过串口输入文件路径名

! P( J+ s$ A0 Y" _/ O% P
    //Open source file
# P& j, k! L; ?
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);

0 ?6 |) a# S4 s4 f3 P9 T
    die(res);
+ j# ?$ x: F7 G4 G, w( W
    //buffer空间设大一点,会提高读的速度。

6 W3 A- y" P2 V' f$ ]7 i& o: s
    //如果文件实际大小512byte,
6 W7 G, b* w! u+ k- c
    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。

  a% s( }1 m- u3 I. L2 m
    //下面两行主要是去除1s误差。
. s9 {  j; \: X, a- _( A3 B, J
    //Read_File_Flag = 0;

+ B0 Z8 g; ?9 R0 N( D
    //while( Read_File_Flag==0 );
7 {; Y* z, z# w7 {& i

4 N3 C' b5 k1 ?1 J# c0 ]
    //time_start=Time_GetCalendarTime();//记录开始读时间

) K/ t; ?( t3 a+ I: t
    //unix_start=Time_ConvCalendarToUnix(time_start);
; e0 [7 V% G3 {" `1 \
4 ~. I5 a( @$ v

; h6 \( r* W! H3 V, N9 D
    //输出提示..
3 N7 e, @) W% X6 B
    if( res==FR_OK )
2 o0 Q4 ~) `9 c( r+ j& C
      printp("\r\nread file start time :%02d:%02d:%02d\r\nplease waiting...\r\n", time_start.tm_hour, time_start.tm_min, time_start.tm_sec);
9 T' G9 F, r! k+ B
    for (;;)

) @0 |! n9 @5 }* `' w+ |
    {

$ l) I% g6 D0 R% X  j" m' e/ [! R
        //清除缓存

5 Q% w+ b3 B; \, l. x- o
<span lang="EN-US">        for(i=0;iRTC函数的编写

15科星F107开发板学习笔记—SD卡上文件系统FatFs的学习.pdf

下载

2.25 MB, 下载次数: 949

赞 1 收藏 9 评论38 发布时间:2013-11-20 09:57

举报

38个回答
hhhhhhhaa 回答时间:2018-10-18 09:48:43
ren0zhe 发表于 2013-11-20 09:59
8 e0 V  @2 V( i) A3 ? SD卡读写数据,FatFS文件系统 源码
* e1 b. e4 d" N9 U/ L
求助一个STM32F103VCT6与AT45DB081芯片通讯添加文件管理系统FATFS,SPI2的接口的示例
lusonghua 回答时间:2015-6-4 12:25:01
不是很确定FatFS使用SPI-FLASH是否合适,对于NorFlash和NandFlash,损耗平衡什么的也应该注意一下吧。
alvin_ 回答时间:2015-4-10 13:40:38
感谢分享~!支持!最近准备试下,不知道这个能否移植到STM8S003上?
ren0zhe 回答时间:2013-11-20 09:59:14

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

 SD卡读写数据,FatFS文件系统 源码

15科星F107开发板学习笔记源码—SD卡上文件系统FatFs的学习.rar

下载

863.7 KB, 下载次数: 886

沐紫 回答时间:2013-11-20 10:11:23

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

支持支持!
qinkaiabc 回答时间:2013-11-23 15:55:38

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

支持支持!
JohnsonJiang 回答时间:2013-11-27 09:43:25

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

不错,看起来写的很详细。。支持!
boldchild123 回答时间:2013-11-27 17:48:04

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

来学习,取经中,,
少韶 回答时间:2014-3-19 20:49:35

RE:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

,学习学习
1942-406215 回答时间:2014-4-22 10:21:12

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

学习了
xuyp188-265233 回答时间:2014-6-2 13:51:17

回复:STM32 FatFs文件系统 移植,SD读写数据 58页笔记+源码

好东西!
caizhiwei 回答时间:2015-4-10 10:09:00
学习了~~~0 ^4 M6 T  g: A( C, l  C" A3 v
stary666 回答时间:2015-4-10 10:22:55
支持一下,学习。。。
木木鱼 回答时间:2015-4-15 23:44:05
必须顶下!
stary666 回答时间:2015-4-16 09:32:05
学习一下。。
eurphan 回答时间:2015-4-16 13:06:19
好人一生平安
123下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版