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

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

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习! ^% ~# F# [/ t5 U
详细内容请看附件/ n4 }) w3 D( R8 y9 C8 c8 [

" d$ W- K6 i5 {2 p本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
: \) ^( F7 R7 }9 \/ y5 ~         
7 g- d3 U7 v( c! R( E
8 \, \& s( _' N. T6 j; S
最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需
: Z2 I& }9 c) F- k; j
要调用FatFs Module 提供给用户的一系列应用接口函数,如f_openf_readf_write f_close
  K6 D9 q; E* ?. t! L, n
等,就可以像在PC 上读/写文件那样简单。

1 G/ U7 e- S6 X3 m& M5 [2 B
中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c

- I$ D& O- U# g- D2 l" d1 m
ff.h,简化版Tiny-FatFs 提供的是tff.ctff.h。除非有必要,使用者一般不用修改,使用时将

8 ?: H3 Y: E0 o' t6 q$ L0 w* u
需要版本的头文件直接包含进去即可。
' X# S5 e" l& P! |( }/ d1 ~
需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写
; [( u4 E1 E  P8 ?4 I6 m% H) ~* L
接口Disk I/O 和供给文件创建修改时间的实时时钟。

# m) R2 Z! K! `
4 B) K: k$ J% _2 J, ^  B
                        本例程的程序结构图
7 z4 R6 m) q3 @' N4 G
                  
: _0 }8 U8 y: \: ^' o" j1 A* C8 b3 p. j 0 F2 |( S- z' i5 S* t% k. H; `4 S
RTC_time.c
7 u4 w6 s" ?6 ?. t3 H# a
Diskio.c

5 v0 O) }" B6 T/ Y
SD_driver.c

' X6 u. \, Q6 n/ c" s
ff.c

+ Y8 y  k; N9 |0 w; l) t. K& b3 b. K$ m5 z
fatfs.c

( q6 l4 ?- S- D2 g/ h! A9 l2 i , J0 N9 L2 S& P4 I! `9 X
程序的编写

* [5 M5 s8 R9 m% C
下面我们开始代码的编写:
% Y, z: V6 \3 D8 W' X) D* i
1、  主函数的编写
' Q6 m0 A! n- h7 i
int main(void)

1 L7 T1 G) J7 E$ k+ Z: D
{
6 S& f) N6 t6 w( f
  RCC_Configuration();
6 _* q1 ~% x- w  o! j
  GPIO_Configuration();
' U' h8 e# B, c
  USART_Configuration();
2 n6 l+ g& K3 e  f  w
  SPI_Configuration();
  O( M- m" _# \8 R: E9 D! X: @
  FATFS_TEST();   //FATFS常用功能测试函数
: p( O9 P0 o$ S9 `; u
  while (1)
$ E. E* i* L0 ~3 Q+ k8 y6 S- o
  {
( Y: A' N, D9 q0 P: v# J
  }

& F; `. }$ S2 T' {. V4 B% q
}
8 p; l# Q2 c7 w  t7 g2 Y: ?
这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:
. e9 P- h1 K. r0 W; C
void SPI_Configuration(void)

; j; y1 R7 Z% i+ i& x; v
{
8 M- n% S2 u2 o% g
  SPI_InitTypeDef   SPI_InitStructure;
4 j0 ?. }4 `/ k1 P
/* SPI3 Config */
! X0 t3 z) N$ \
    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写

) b) u$ N1 Q. x7 u1 n, G
这里使用文件SD_driver.cSD_driver.h来写出SD读写的一些驱动函数。
3 M6 n4 P: G- ~) {' M+ s
函数列表如下:

2 M$ `- {# z: C( L
/* Private define ------------------------------------------------------------*/
9 I0 q, l' R5 S; j) a  Y
/* SD卡类型定义 */
6 [- }2 t* x) x4 D# g
#define SD_TYPE_MMC     0
$ F: X& j" ^4 N/ d) z1 H
#define SD_TYPE_V1      1
4 g. [! _+ @7 x0 E! |% g  g, J
#define SD_TYPE_V2      2

  L6 }% E3 R; E* R2 P
#define SD_TYPE_V2HC    4

0 j4 N: X: d! b; g 8 ]1 k' h0 _% ~9 k
/* SPI总线速度设置*/

! u! o0 K/ d; S
#define SPI_SPEED_LOW   0

* O) g3 m. S$ @! w. u! d
#define SPI_SPEED_MID   1
9 h5 l( J  f  v9 R( G1 ~- ~  i
#define SPI_SPEED_HIGH  2
8 H2 K: @. z0 ^) H8 n" [
/* SD传输数据结束后是否释放总线宏定义 */

2 Z% S2 O$ F9 t1 x- X/ `1 e
#define NO_RELEASE      0
3 s' [) I  _5 \6 K, N: x
#define RELEASE         1
$ Y( @" }8 z/ p# c5 m( r
% {7 `* {" ?& M9 C8 U) W& e6 _4 i
/* SD卡指令表 */
  h( o# b) v5 E. e' k% {, S
#define CMD0    0       //卡复位

" N8 I7 g7 ^# l1 q( j
#define CMD9    9       //命令9 ,读CSD数据

  s6 G: o" J/ l" R" n# h
#define CMD10   10      //命令10,读CID数据
! _0 i8 {4 O6 [: }: ?
#define CMD12   12      //命令12,停止数据传输

. m: w& p6 \( E8 g
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
8 p# {9 N. d- [1 t$ Y- T- A
#define CMD17   17      //命令17,读sector
7 j) r# n" b' P- l1 w
#define CMD18   18      //命令18,读Multi sector
( h1 B% }$ w& X  v/ B% `/ ^
#define ACMD23  23      //命令23,设置多sector写入前预先擦除Nblock
) ~7 }$ V# S  R, S2 }1 y/ d
#define CMD24   24      //命令24,写sector
" m: b4 [* _( d! |
#define CMD25   25      //命令25,写Multi sector

" ~4 |# n: G; O% P+ M# l
#define ACMD41  41      //命令41,应返回0x00
& i5 S1 l( _# l+ c0 d8 @
#define CMD55   55      //命令55,应返回0x01
5 ~0 }( v  D* K" L% I6 B
#define CMD58   58      //命令58,读OCR信息

3 Q- \$ h7 d) A! }" G
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00
7 ^7 M/ v, z+ F* S) }
$ K/ J. J$ Q9 U1 U) K9 w9 j
/* Private macro -------------------------------------------------------------*/
/ K1 x% s" f* l6 L# J; t- r
//SDCS片选使能端操作:

" q# L5 u3 c8 d
#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD

$ a1 @( f6 k7 C
#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD
* ~3 W. P9 P! Q
#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电
: H" v# h: \/ k0 Q4 I) g1 @
#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电

) D# |" a* ^+ ]) w, O0 C! t9 u
#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡
7 W7 B9 _" i7 g4 L& ]
                                                                    //1- 0-
. J* r" W  [' a6 s- z5 f% V

5 F8 [/ O! C( S9 h4 e% e
/* Private function prototypes -----------------------------------------------*/
* H$ q/ p% D1 }! |) g0 E
//void SPI_Configuration(void);
0 {: U- O, f6 L. F0 q, _. T; f
void SPI_SetSpeed(u8 SpeedSet);

! m3 N( O7 J' ~8 f0 [/ L; E , {; y" o- s/ T' c2 w
u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节

3 d2 Y( u5 k' I0 w7 o$ m
u8 SD_WaitReady(void);                          //等待SD卡就绪
- M% Y8 t0 C- e) v& Y
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令
" T5 k. h! U% F- ^  n* k3 u
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);
$ j1 k. _& M: R5 X6 a+ T2 A4 y  h
u8 SD_Init(void);                               //SD卡初始化
% j6 }  ^! `* ^6 e3 b
                                                //
: g1 V, y% E9 j+ I
u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据

) }6 v* u& f% k
u8 SD_GetCID(u8 *cid_data);                     //SDCID

+ B- c, R- b0 @5 |
u8 SD_GetCSD(u8 *csd_data);                     //SDCSD

5 N, S, r7 L& k4 E7 `* n! m
u32 SD_GetCapacity(void);                       //SD卡容量
5 z1 y3 E8 H, G* X. {4 V8 `

7 Y" f1 H! D1 e8 J
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector

% c# H) X, m/ s! j& F4 B
u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector
7 W% a* o5 d0 }
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector

( E3 ]2 i# o' C' u! }
u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector
/ R6 R( l( d, a% _0 b* o
( W  W! E& I% F9 Y7 I5 U7 ]
3、  文件系统的移植

3 P& ]9 h- a5 ?- C9 k% P
FatFs文件系统主要有以下函数:
. T# ]4 b5 k3 |6 `
/*-函数详细的解释请查阅附录,点击链接也可以到----*/
- n8 ~0 a  J) |5 m, ^! V
/* FatFs module application interface                  */

/ Q' ]0 ^2 W: f/ S+ H3 O- |
6 l- I; ^7 O4 T; L) s/ k/ V& f
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 */

: Y! y( V: A- a% x) m4 q# [2 S
5 ?. l4 T; b# S3 Y
4、  底层接口I/O函数的编写
( W1 c+ K- V5 r1 \+ k3 ^% F
底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:
: b/ N( E2 c& Y! h$ r
/* Prototypes for disk control functions */
! e& S3 M8 K$ t/ {3 }* C; v
DSTATUS disk_initialize (BYTE);

% S! m6 P6 Z! o- v% D+ G
DSTATUS disk_status (BYTE);

! K8 D9 I% D' l' I6 O5 H9 T
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
  b1 S) X6 r, H4 A
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
; I' x+ r6 Q- n# Z
DRESULT disk_ioctl (BYTE, BYTE, void*);
' C  H  \8 T4 W  c
DWORD get_fattime (void);

6 \+ [6 F0 D/ z, ]3 z- g
6 个接口函数的详细信息如下图所示。

6 H: \8 E8 l* Z( P8 D1 u5 h8 K9 o
Disk I/O 函数结构图

0 a  l- E! H- v4 d: R& W3 ~$ A
因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。

) U& C: j2 d! K  }8 Y
1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime

& q8 P+ [! v! Q- I- e7 }$ b2 q
5、  应用层函数的编写

# o4 Y( u# F8 ~: ^
我们这个例程要实现的8个功能如下:

; h, X1 N0 s' D  G+ r- L

2 M2 ^- d- }5 W
每一个功能都对应一个函数,各个函数如下:
9 k' \  Y) H3 W* `7 c. X1 t! [
// 0  读取磁盘容量 The f_getfree function gets number of the free clusters
  D1 k# U1 H0 F* I
void Test_f_getfree(void);
# B) H  W/ u# c: Q3 s& i. [
//1   读磁盘目录 The f_readdir function reads directory entries.
% y9 j: o6 C- ^! g
void Test_f_readdir(void);

" D0 x* I* L* N4 ^1 f
//2    创建目录   The f_mkdir function creates a new directory

8 [) L" m7 W- g
void Test_f_mkdir(void);
2 x4 g& L) l! S8 O. P% l; L
//3    读取文件   The f_read function reads data from a file.

) y# @8 C. n0 P+ x( A! p
void Test_f_read(void);
! I1 a' C) y  Z, \6 X; d6 ]# a
//4    文件拷贝   The f_write writes data to a file.
2 H& B: U: J0 ^( B
void Test_f_write(void);
( Y  j0 J# L8 t$ v' @
//5    重命名    Rename file or directory

" W, b. w1 O' z+ K9 f8 f* Z2 x1 }
void Test_f_rename(void);

* W. L3 ^, s; h
//6    删除文件   The f_unlink removes file or directory
" a+ c& M( z+ ]# K* ~$ d
void Test_f_unlink(void);
+ P5 J# w6 z: I: n
//7    格式化     The f_mkfs fucntion creates a file system on the drive.

. o% x) V0 `2 S0 ^
void Test_f_mkfs(void);

6 }# f- P  a) T+ t; k; X
/ I; M% ^! d* Z  p2 O
  t# j$ \: t% t" g
8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:

# {9 Q2 J- J" |& E8 \
void *FATFS_Function[][2]=

) m, M9 V; d' N% f
{
5 F0 _# e/ k! [* E
    (void*)Test_f_getfree, "磁盘容量",

4 [& X6 r7 w: X; B( s
    (void*)Test_f_readdir, "读目录  ",
( J  r$ b' L* c: H; P% _
    (void*)Test_f_mkdir,   "创建路径",
' R- m# y' v- k. P
    (void*)Test_f_read,    "读文件  ",

" f- L( v  @$ F7 \/ e. p; ]+ t
    (void*)Test_f_write,   "文件拷贝",
' V- q: z# S4 o/ o. I8 y
    (void*)Test_f_rename,  "重命名  ",
  y& m& V  W4 P2 I! c
    (void*)Test_f_unlink,  "删除文件",

2 S. A: t9 ], F) N
    (void*)Test_f_mkfs,    "格式化  ",

0 |+ x8 W  \( ]! X
    0x00,0x00
% \) @6 ~3 H; c8 r  t/ R& W5 @1 G
};
, }9 v* X# H4 V; a2 ?8 Z
8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:
" P0 o+ K9 A4 s; K7 r; r
0//The f_getfree function gets number of the free clusters
% I2 u, {9 d! M1 f: ?6 B  C
void Test_f_getfree(void)
: T+ p) g; @- ?* Q! c9 Z
{
0 i! t; S2 M5 `4 j! i6 }2 d
    FATFS fs;

4 |1 y, p0 V; U' b
    FATFS *pfs;
3 N3 A7 F2 v$ ^3 |/ I2 v
    DWORD clust;
* [# Q+ I; ^6 F$ k0 P/ X- d
    FRESULT res;         // FatFs function common result code
. K% D8 [4 X/ i  [+ K, e- a
9 d7 F) ]7 ?; u$ q/ ]$ ~) ^0 T9 F
    //检测磁盘是否插好

6 u& W8 A! K. x* h
    if( disk_detect_OK()==FALSE )

4 [; E/ E4 [9 \, V. S) [% ^" S- q$ r
      return;

; S6 Z9 D" @6 R9 u' {+ b
8 f$ v$ W& n! w* \
    pfs=&fs;//指向
% r7 p' ^0 t- f! ~7 X
// Register a work area for logical drive 0
$ h- G! N: \! V- L, O; b
//温馨提示:该函数是文件系统FatFs里的函数,详细说明请查阅本章节最后的附录,可以用Ctrl+F快捷键,弹出搜索框,输入该函数名,找到该函数。以下类似函数均可以这样找到详细说明,不再赘述。该类函数我们会标记红色,并加粗,请留意。比如f_mount, 解释如下:

, U* c+ k! p7 J% m  t1 |
7 T# o* V1 D/ [6 s( q
& }( H! E7 `2 h
f_mount(0, &fs);
& _9 W  J( ]% X2 ^5 q4 U
/ @; [$ ~+ E) I% c( B
// 获取空闲簇Get free clusters 空闲簇的值存在clust
1 o. U0 P" t' ^$ d
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0

0 q+ n+ ^+ I/ U( Q. m/ D+ J7 b8 M# ^
    if ( res==FR_OK )

% R; P  [* \6 w' r+ i! v  }
    {

# u. t+ Q! U1 E4 u! {0 j0 K
        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小
  c$ t) a" h! ~
              //计算方法:

( ?- {6 i' s: ~$ p. }/ @
//   总空间大小   最大簇数×每簇的扇区数÷2÷1024

; s, I- W1 K3 P1 G0 D
//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024
+ X3 x3 y2 o2 ]1 r3 f- c' J+ }
        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",
5 [+ G! T5 ]7 v0 r
        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,
, b7 W" Q- F1 T& _# k; {1 G
        clust * pfs->csize /2/1024);
% Y0 C$ I: G, p
    }
7 c7 }# {$ u- ?" @$ t1 o2 T6 h2 g
    else
- m/ s( ~0 D6 n3 C0 P
      die(res);//测试函数执行结果分析
+ k) f5 {! }5 Z; ~% ]; [' C

7 L. a0 R0 g* Y* S4 R! _2 ^4 Z
    // Unregister a work area before discard it

% {  j# H, p& J; A
    f_mount(0, NULL);
7 {# w4 a, C. t2 ]
}
& ^4 b% p/ k1 h, _0 P

1 N! W2 l1 l1 T3 ^7 Z
; k/ Q% p3 M. S
, I0 L8 n9 B! N3 }* z2 ^
//1  读取目录 The f_readdir function reads directory entries.

- K* `+ f0 Q3 x
void Test_f_readdir(void)

  S2 z* ]$ g5 ?$ i0 ]+ N8 A
{

6 `; S7 t* v6 m7 f* c8 c# x+ b
    FATFS fs;        // Work area (file system object) for logical drive

. z0 e+ X5 `! t: a* G
    char path[20];

- M; I! ]: H2 }# _1 q  F * A7 V- o0 u5 S# w7 D% {1 k
    //检测磁盘是否插好
8 Z8 |" C0 l* X1 F  t3 e$ p
    if( disk_detect_OK()==FALSE )

# d5 _* b9 I" T9 Z  _) J
      return;
$ I. o3 {% [; ~; b5 e
5 v; H2 [8 i9 s) g" i% b
    f_mount(0, &fs); // Register a work area for logical drive 0

/ k6 |& k% I9 n5 f1 l- }8 b
5 Z8 h5 a* a" K& q0 J% q8 P1 b8 u$ L
    printp("\r\nread directory:>/");//默认输出主目录下的文件
" x% k/ |- a3 b: ]7 ^# n
$ @9 m0 S& ~- P1 n  ^+ W5 q' j
    USART_Scanf_Name(path);//通过串口输入路径名

6 _  l. h# j9 B! y3 ~9 N% l+ }) C 0 F! j( N8 v% C9 D
    //扫描当前路径下子文件夹,并输出到串口
8 h7 v' N9 j, R. l4 @
    scan_current_folder(path);      
% G- V7 }0 S9 _8 ^7 O! {' Z$ d
    //扫描当前路径下文件,并输出到串口

' e3 R9 |; F0 L/ b: Z" P' v6 R/ w
    scan_current_files(path);

& Z( t' l. e- `
; ]: C# \) T% ]( q( E
    f_mount(0, NULL);// Unregister a work area before discard it         
4 V' r! x9 ?: u  S2 A( c1 X& [% l
}

$ V( @% u" Z( Q4 z% B* _# O" L* Y, B
, Y5 X: s/ f5 m- ~' w  l$ H2 p2 ~& _- I9 z9 P

  `9 C" v0 t3 Q  x4 b
//2  读取目录  The f_mkdir function creates a new directory
/ b; g: j' {  D8 A+ c' I8 n2 I. z5 i
void Test_f_mkdir(void)

% t4 @! w+ j3 r0 Y7 @
{
, t2 @/ _! x6 f6 O! V. h1 Y# j
    FATFS fs;       // Work area (file system object) for logical drive
4 G1 K7 @0 G! b
    FRESULT res;     // FatFs function common result code

# g( i( E* W; y
    char path[20];

+ X! q1 j8 u+ L3 h
    //检测磁盘是否插好

3 E( i. }0 [/ r
    if( disk_detect_OK()==FALSE )

; E/ T# u' ^% V/ g. l' u3 G
      return;
+ O: |9 g- [" w0 k# }" q
    f_mount(0, &fs); // Register a work area for logical drive 0
1 g, E$ c0 ~$ K, N8 O( h
    printp("\r\nmake directory:>");
9 u$ `& g' v  W
    USART_Scanf_Name(path);//通过串口输入路径名

4 v$ W: D4 k: P7 ~6 w" f4 |
    res = f_mkdir(path);
, z3 l) h- S5 H. l" j) ^
    die(res);//测试函数执行结果分析
' R! N& }4 m( a1 x
    f_mount(0, NULL);// Unregister a work area before discard it

  M( w, z. E7 f8 |6 r9 y$ I7 O1 j+ _
}

) w" J& y; t6 w: \: r0 |! C7 Z+ r* {* j
- D! }% y, N$ V: C+ `  D* Q1 i3 N' _5 P
//3   读文件 The f_read function reads data from a file.

3 ^& u6 a* f; A3 R+ X
void Test_f_read(void)

# d" F0 i8 z% m. B! o
{

3 Q2 n0 s% m5 z# L" M1 }1 Z. J3 |  u
    //用来记录读文件起始时间、结束时间
, z' c! U$ c' s- K) Q0 `1 E/ i2 B
    struct tm time_start,time_end ;
, h" Q, W5 k( n$ L' Q3 j- b6 E, I
    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。
, E( U. u8 G' q5 I
    time_t unix_start,unix_end,interval;
, p$ q* w& y/ M! x% l
    char path[20];
" _: Z" S. E4 Q% {: j
    //检测磁盘是否插好

. H1 [8 F' G6 b/ |
    if( disk_detect_OK()==FALSE )
/ c# z5 B; Q1 `  T; Z7 @
      return;
# }: Z4 w) }- x
    //printp("\r\nread filebbbb:>");
- |0 L( @& B% t3 U
    // Register a work area for logical drive 0

8 j# m& p9 H) g. L2 w# D+ Z
    f_mount(0, &fs);

+ D$ V( b# t; m4 W4 t9 K: N4 T' C: c6 P
    printp("\r\nread file:>");
& @* u& ]. m$ z) N) o
    USART_Scanf_Name(path);//通过串口输入文件路径名

5 k( o( s0 X+ |, n6 L9 S) L# F6 V
    //Open source file

) l4 X9 j6 z$ ]& ~
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);
) F2 o7 W. t; R% n# i
    die(res);

0 l+ {* V% R$ ?4 w$ D
    //buffer空间设大一点,会提高读的速度。

' n+ ?8 j3 d- x* c5 N, B
    //如果文件实际大小512byte
9 o! ^5 R: w2 z# o2 g6 p2 E/ }; K
    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。

+ L5 q0 D' W$ C0 j8 K
    //下面两行主要是去除1s误差。
' y; _, E% Y$ s) M/ V
    //Read_File_Flag = 0;
" b6 L1 C( _0 U1 ^. f! l& m: Z; `
    //while( Read_File_Flag==0 );

" j4 ]+ M* a$ r$ U
: d# G" ?& V; u$ m( Y% ]: F
    //time_start=Time_GetCalendarTime();//记录开始读时间
0 H8 i* W' F9 j3 `  _$ W4 r
    //unix_start=Time_ConvCalendarToUnix(time_start);
% v8 a1 L4 k- q) P  L+ r
( t  Y3 q# |1 I+ O- g5 ~6 D3 N

+ d7 _" v- s# d8 e' c8 }
    //输出提示..

; E) c/ V# o- t6 q0 Z8 \$ C( u1 L
    if( res==FR_OK )

9 `# g/ E2 [) K, D7 f. Q
      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);

. I6 D/ J& ^/ L6 E" U$ X$ u2 O) r
    for (;;)

& S1 p! `8 P! o' G0 Y
    {
+ m$ F  p6 f& H/ t
        //清除缓存

; l: `5 N* ?" v. h8 y, s9 d
<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:592 z; Y% x/ U; U5 |6 N
 SD卡读写数据,FatFS文件系统 源码

  m. c4 t5 ]7 B' O+ l0 A求助一个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
学习了~~~) c/ @8 b$ X, ]; l# ?5 m% ^& d
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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版