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

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

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习
! y, i- `- R8 _详细内容请看附件
  o6 U7 z$ a. u9 D$ f ! R1 [$ x4 S9 w8 h, P
本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
% H- C: S3 T8 X( z5 D         ! E6 N6 ~& I7 x/ a

" @0 L9 b6 `6 y/ R- x
最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需

/ Z, @2 b: z4 o  r! m! t
要调用FatFs Module 提供给用户的一系列应用接口函数,如f_openf_readf_write f_close

1 g! R2 X& X3 k
等,就可以像在PC 上读/写文件那样简单。

' d0 o+ U% B  j6 V* A  _3 I3 U
中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c

6 l; U0 d8 N/ J  [$ g: k
ff.h,简化版Tiny-FatFs 提供的是tff.ctff.h。除非有必要,使用者一般不用修改,使用时将

. _( U: u5 e' V" Y% V
需要版本的头文件直接包含进去即可。

0 ^4 k  o- M, X9 v! z
需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写
/ ?0 @( v6 s4 E$ N
接口Disk I/O 和供给文件创建修改时间的实时时钟。
0 N  i7 g$ ^+ G7 |0 y
) O) X! M  ?. h% O2 P" G
                        本例程的程序结构图) r4 D0 F& x+ w8 K, V0 q1 [1 C
                  
/ i0 D/ ?8 d: z( P
1 E3 R, k1 r* ]: z
RTC_time.c
' {  s3 y8 l. N# I/ N
Diskio.c
) ]# F9 x& `# d9 o+ d7 Z+ w7 A/ Z
SD_driver.c
4 ~+ L! E8 U8 B+ I
ff.c

/ T( q  q) N- Q+ X  Q7 v, z
fatfs.c
! `8 [$ d! K) U
& ^5 C1 i% l( {+ P: C; F
程序的编写

: `# m. v# e4 N9 @! K8 [
下面我们开始代码的编写:
4 N  D5 Y/ s" K- H
1、  主函数的编写
* v* Q$ q' p8 Y8 D5 K/ Q7 l+ N" B
int main(void)

8 r5 o' T* [5 e1 V
{
, c+ v5 I& l, v3 i1 e" D
  RCC_Configuration();

$ B( A; Q0 F3 t, ]9 W
  GPIO_Configuration();

) C6 `6 T/ R& I- Y% z  E
  USART_Configuration();

3 b- S0 q6 K' I, z: P3 s" Y' [
  SPI_Configuration();
; l+ A  u  C$ g- }; Y# r
  FATFS_TEST();   //FATFS常用功能测试函数

2 _/ @3 G7 r0 T
  while (1)
) C/ A  j9 o) z" k$ w$ e. U3 S0 N
  {
2 ^0 x9 [- X/ m- o: ^; I
  }

9 v/ _: g4 z% ~8 a, ^0 Z
}

  b  f! k% b2 t+ e7 ]+ E8 k
这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:
0 w/ ~+ V% T4 D% N/ X
void SPI_Configuration(void)

5 ~* ?% l7 e$ A  `* [
{
+ r5 A. p' M. L) Z
  SPI_InitTypeDef   SPI_InitStructure;

( P* M1 U4 s- Y/ K, Y
/* SPI3 Config */
/ B( P: C. }0 I5 t: T
    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写
/ a  B  R5 [/ e  J- G
这里使用文件SD_driver.cSD_driver.h来写出SD读写的一些驱动函数。
) k$ s1 j1 ~% z1 }! O" T
函数列表如下:
  s4 p9 _4 H( |. L" v' {
/* Private define ------------------------------------------------------------*/

! u! X$ f" g4 d: f
/* SD卡类型定义 */
6 m7 L6 @3 [+ z+ \& T" H
#define SD_TYPE_MMC     0
# S: q9 n% m2 t! J, {, b
#define SD_TYPE_V1      1
4 u" M- `3 P( j6 ]/ T
#define SD_TYPE_V2      2
1 d4 B1 A4 k" [% M( x, i* J
#define SD_TYPE_V2HC    4
% Q# K8 y6 p5 _( Q2 p/ c1 I; N  f

  o" R6 T" L& N7 [
/* SPI总线速度设置*/

0 v: V# p, N  w2 z& O) L; E
#define SPI_SPEED_LOW   0
5 h. o" [/ p! c: s) L
#define SPI_SPEED_MID   1
; V$ a" |7 P% |5 J) y- Q" P
#define SPI_SPEED_HIGH  2

6 g/ T0 ?2 I3 @( T
/* SD传输数据结束后是否释放总线宏定义 */

0 ?0 T1 Q* \2 l' R; X0 A
#define NO_RELEASE      0
4 M) E7 t; A8 r  e* `5 W% E
#define RELEASE         1
& x6 v' F" L$ J, H3 U$ u
' x! n) [; e' x
/* SD卡指令表 */
! k/ H8 d+ r* h8 [& f( g, k+ L
#define CMD0    0       //卡复位
1 x$ O) D. u) ^/ G; Q
#define CMD9    9       //命令9 ,读CSD数据
4 y2 i% @! M& c. E, Z
#define CMD10   10      //命令10,读CID数据

% ?9 [" O+ t# g% B$ M2 \. ?8 T
#define CMD12   12      //命令12,停止数据传输

+ \: `: N% j" B! x$ U+ k
#define CMD16   16      //命令16,设置SectorSize 应返回0x00

; s7 q5 P3 w8 O# w
#define CMD17   17      //命令17,读sector
# p1 K% U2 t8 V9 ?* G7 D
#define CMD18   18      //命令18,读Multi sector

1 l& ^+ f% G( k- R. u2 |% R
#define ACMD23  23      //命令23,设置多sector写入前预先擦除Nblock

$ g* o3 y. v9 Z9 b" |5 g8 G) S
#define CMD24   24      //命令24,写sector
* Y$ o( X- J* _1 H  n+ |) N
#define CMD25   25      //命令25,写Multi sector

3 j1 h) i$ A& C0 ~
#define ACMD41  41      //命令41,应返回0x00
) |; [: z8 s* Z) y' w% F6 H; ^
#define CMD55   55      //命令55,应返回0x01

" l* ~0 L! u* w3 `
#define CMD58   58      //命令58,读OCR信息

% s# x1 g' v! T9 h
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00
( H! J5 h6 L5 X5 Z' O

* y- U8 ?7 T# R6 z, Z+ \0 Q
/* Private macro -------------------------------------------------------------*/
7 M$ k9 x( k9 U7 B, J9 y" T
//SDCS片选使能端操作:

& p: r: \9 m  P" B
#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD
0 d0 [* @: ]" t* W6 k' ]
#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD

  [) {* ^! U  T4 K( F- [( F: j
#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电
: _: U- y8 {6 C7 d  b
#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电
5 f5 Q" W8 g. t& ~' g2 P- p
#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡

- _: V' D, j" u7 Q9 u1 S, c4 [
                                                                    //1- 0-
/ J* {2 G; ~$ {% |% ^

" T0 ?. `' i* z
/* Private function prototypes -----------------------------------------------*/
7 C6 }" Q: v- [2 |- V; ^
//void SPI_Configuration(void);

% N7 b9 |5 \% S$ R
void SPI_SetSpeed(u8 SpeedSet);
2 T' e1 {; r" }8 g5 j

  V+ z9 p: I* D& Z1 @  _
u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节
: g. p- K; l& Y3 m; k
u8 SD_WaitReady(void);                          //等待SD卡就绪
+ P. d5 _* l; Q* S5 P# d
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令
+ `& w# M! D+ C( m( a  [
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);

! [- y" z: a; T) [) G+ X, \
u8 SD_Init(void);                               //SD卡初始化
5 m; }- J) |7 J% A/ J/ W
                                                //
1 V7 Q( Q! W6 X; I6 \, B
u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据
4 p" |9 r% G8 G& J& i% L
u8 SD_GetCID(u8 *cid_data);                     //SDCID
# m" j; N8 g: l
u8 SD_GetCSD(u8 *csd_data);                     //SDCSD

5 p* a1 ^. F5 b* z: T# T
u32 SD_GetCapacity(void);                       //SD卡容量

  H9 @6 n. ^9 K* ^: v+ d) y
; p3 G. `+ T8 @5 _1 p) L7 g5 }
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector

0 h* h1 Q0 x# b: o, d: ~
u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector

$ R' K) k1 i# V
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector
. z: y  p% r# w" j
u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector
3 k" w  a, O% w
, u; G) G" x3 h
3、  文件系统的移植

* D- Y3 b6 q, O" `" V3 F
FatFs文件系统主要有以下函数:

, |# U9 a+ ^6 [4 [9 b
/*-函数详细的解释请查阅附录,点击链接也可以到----*/

7 s! V8 r' d* ~0 K& n6 b" h: _
/* FatFs module application interface                  */

, n4 B! U& c; n& x% F: u

1 h4 O  `/ h" [
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 */
2 J! n" s/ X) _, j! q+ J- ^9 h( I
8 K( i" u/ z$ y' f
4、  底层接口I/O函数的编写
$ e* z# u: T0 V
底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:
3 s* E" I$ a9 w
/* Prototypes for disk control functions */
4 s; F2 T9 @" z( \. D# U+ h! E4 W
DSTATUS disk_initialize (BYTE);
* c6 {- ~$ |  j+ ~. G3 f9 y8 a
DSTATUS disk_status (BYTE);
7 w' l% H1 Z' A! i0 b1 h  c% K. ~" ?
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
, S1 k2 \1 ^* k! H# M5 J0 H
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);

8 d: Q& F- H# x
DRESULT disk_ioctl (BYTE, BYTE, void*);

) i% U6 E! s/ B$ t$ A5 p3 U7 [! c
DWORD get_fattime (void);

/ m$ ?% b- R0 @$ d
6 个接口函数的详细信息如下图所示。

5 l& T4 l7 |6 e' ?
Disk I/O 函数结构图
1 D) |9 _, C  m5 H- {5 I; O8 \
因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。
* P# Y( Y7 m+ ?1 X3 B- \
1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime

7 S+ ], _# q, A
5、  应用层函数的编写

6 G0 X, R8 N& A. [
我们这个例程要实现的8个功能如下:

0 H; c$ J0 a: n! J; D
- G4 L" S- r2 |
每一个功能都对应一个函数,各个函数如下:

' J% ]; x% e: b
// 0  读取磁盘容量 The f_getfree function gets number of the free clusters

" ^0 `( X- i+ F( l
void Test_f_getfree(void);
4 _2 j6 z6 s9 r
//1   读磁盘目录 The f_readdir function reads directory entries.
8 a; b8 P1 {4 D1 ?& X  ^
void Test_f_readdir(void);

# i  W$ b4 e4 a
//2    创建目录   The f_mkdir function creates a new directory

2 v! R2 {/ I0 T8 ]4 \) c8 ]+ E
void Test_f_mkdir(void);

) [9 V" R# b/ p: h3 N5 D) A' w
//3    读取文件   The f_read function reads data from a file.

& [9 }3 t# U# m
void Test_f_read(void);
9 p4 h" F. w1 x- g' \
//4    文件拷贝   The f_write writes data to a file.

7 m0 C5 S2 h( F& d* s; y
void Test_f_write(void);
) {  R) X- L2 j& S1 v, u* F; p; |
//5    重命名    Rename file or directory

3 ?3 [* {# Y8 I9 y* B7 g
void Test_f_rename(void);

8 N  n1 ^3 l7 h
//6    删除文件   The f_unlink removes file or directory

. T! v6 B7 K4 l7 B  I2 \
void Test_f_unlink(void);

6 `: z: ?6 h( w' }# G1 [0 v$ U
//7    格式化     The f_mkfs fucntion creates a file system on the drive.
  P7 @: J. M) t6 r9 \3 D3 t- B
void Test_f_mkfs(void);

9 W/ G2 `4 [2 I% p- P1 j
- g  U! i3 C, q5 U$ C) I % P+ g; Z- r2 x7 D  h3 I3 p
8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:
! l3 B6 m  b, j
void *FATFS_Function[][2]=

7 f# s+ `! J, X# p
{
9 A" S  K, C+ U0 l6 Y
    (void*)Test_f_getfree, "磁盘容量",

! C, G4 w1 {* Y3 u. Y5 q
    (void*)Test_f_readdir, "读目录  ",
% s: c7 s" V; _8 a
    (void*)Test_f_mkdir,   "创建路径",

. a. M) }5 c1 m
    (void*)Test_f_read,    "读文件  ",

5 r! ^% u/ K( k/ C1 W* Q
    (void*)Test_f_write,   "文件拷贝",
) I! f# T/ r# w" D
    (void*)Test_f_rename,  "重命名  ",

" v) I, U6 i% b& ~: l) C
    (void*)Test_f_unlink,  "删除文件",

5 h- X; `" E) E, A, ^5 u& {0 @
    (void*)Test_f_mkfs,    "格式化  ",
& h; |) S* x5 F6 D) X8 O
    0x00,0x00

6 L3 F% W8 w, c) Z, x" K- Y7 Y
};
. V! d' ~: Y$ l- z
8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:
+ i& x; O1 ~5 X7 G) @
0//The f_getfree function gets number of the free clusters
9 c' n( c6 k4 I* t
void Test_f_getfree(void)

! J% J3 I: R, ]( G/ ~9 I- i$ {
{
* a' A3 L0 ?( Z. H$ F& b  D- V
    FATFS fs;
% z9 W4 a- a# }: e4 m2 E& [
    FATFS *pfs;
8 x, t8 ^0 U1 H  Y5 b$ @$ K
    DWORD clust;
) `& N8 _  z4 K7 S/ [
    FRESULT res;         // FatFs function common result code
. ^6 e) Y  f& ?0 V+ X! e
0 b& ?/ {5 i, T$ _8 g' \0 L$ C/ y
    //检测磁盘是否插好
! M; H# i$ K7 R$ l. J" ^, @3 |) I- O( w
    if( disk_detect_OK()==FALSE )
2 y3 J2 Q! ]) Z- ^  |$ \
      return;

8 ~) r! ]- J" a) @6 B, R) a8 \+ n) P, ~   T- j2 y$ K6 `6 `, t7 x5 ^7 Q( Q
    pfs=&fs;//指向

5 w6 c( o- C; |; t8 }+ ]5 A! g7 f9 J
// Register a work area for logical drive 0
. T. v  W. k# a
//温馨提示:该函数是文件系统FatFs里的函数,详细说明请查阅本章节最后的附录,可以用Ctrl+F快捷键,弹出搜索框,输入该函数名,找到该函数。以下类似函数均可以这样找到详细说明,不再赘述。该类函数我们会标记红色,并加粗,请留意。比如f_mount, 解释如下:
! U$ d) M" j, _

3 d6 R4 t0 ]* a9 F
$ V: k' i. o5 g0 e* n
f_mount(0, &fs);

6 d  V- M+ z9 i% M) B  l9 M

+ \6 X  w6 O0 l. ~/ U5 s  M; K
// 获取空闲簇Get free clusters 空闲簇的值存在clust

( {. `4 w) F% h! d
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0

1 Y* C+ g8 f: I0 q& w! T
3 J& s: I; }$ Q$ P) @6 B
    if ( res==FR_OK )
/ |( K% H  k* ?/ @5 H$ ^
    {
) g& l  k8 }$ {: s
        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小

8 d1 ?( A3 Q# t% M! V* k0 {5 q
              //计算方法:

. {# n8 m! Y3 u/ @" @
//   总空间大小   最大簇数×每簇的扇区数÷2÷1024
5 Y/ e$ z. ], i* y* K
//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024

8 B* d# E; C3 V; A
        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",
- ?9 @- a7 U) `+ A0 ?3 Q
        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,
2 ^% ?6 q) ~- D5 J4 X
        clust * pfs->csize /2/1024);

4 ]4 s9 D4 e$ L- r
    }
5 [! w) J( E4 |  E
    else
* Z" m) S0 w6 V3 \8 h: {
      die(res);//测试函数执行结果分析
; p  _0 w3 S/ Y2 c

+ ^: y& F# h' [2 m
    // Unregister a work area before discard it

; p% @- B3 O8 n" _! Q& f' j
    f_mount(0, NULL);
% \, d7 s2 M+ s. t4 ]* x+ S& A
}

: H: z+ c7 q1 K
; \9 J& f9 ^6 s' h, D
! `1 m- t, ]0 e
& f* ]" h) ?+ w- n
//1  读取目录 The f_readdir function reads directory entries.

3 U8 q, V% S  U5 {* t) b9 T+ s! g
void Test_f_readdir(void)
9 Q* J; y* D* h# K
{
- ^4 O& P7 ?" ^/ Z0 ^3 P5 c2 E* A
    FATFS fs;        // Work area (file system object) for logical drive

& T. M8 S  n  j2 ~0 r) h
    char path[20];

3 V+ G0 N3 g5 S) [! D
$ ~, ]& U- ~9 J6 K9 X( L
    //检测磁盘是否插好
4 A0 ^+ J, c2 O: h
    if( disk_detect_OK()==FALSE )

, M* A$ c1 G. S8 T& @' h: O. C
      return;

+ C0 x9 w8 a: ]( z# w- l
3 a: e1 E! g( Q' F! E
    f_mount(0, &fs); // Register a work area for logical drive 0

6 X9 Q- B2 J+ P0 E+ C2 c 9 n" P& Q9 ]& b) @
    printp("\r\nread directory:>/");//默认输出主目录下的文件
9 r9 k- _0 D4 f8 ]; R% F

8 E2 ?4 _7 h1 R% I# ~4 V9 z
    USART_Scanf_Name(path);//通过串口输入路径名
5 V9 ~! ?0 F7 y1 D# B4 L$ Q
8 @# ]! @! k; v+ E' Y+ g
    //扫描当前路径下子文件夹,并输出到串口

/ X* g. Q# z% S* ]+ W& L
    scan_current_folder(path);      
$ n; `, u% y5 ~: K/ K+ E
    //扫描当前路径下文件,并输出到串口

5 [# K+ P3 y/ a& L
    scan_current_files(path);

8 A0 w7 a8 {( l/ s, \  V , m$ Q3 p6 O0 [; A
    f_mount(0, NULL);// Unregister a work area before discard it         
2 H- {$ r" s" }/ u: s' i3 u; Z
}

$ S" f7 N+ m9 c1 ^5 Z7 S7 Z: Q * U+ a7 n$ T0 @

. C' W/ q* V5 T- t; T# d. V. {  e# i
//2  读取目录  The f_mkdir function creates a new directory
" h! W& k+ A( C5 v: a; Y  u) f
void Test_f_mkdir(void)
- y$ y4 D3 i# [  d" m+ Q' ?
{
# R! \9 q5 B" }1 M/ f: n: c
    FATFS fs;       // Work area (file system object) for logical drive
9 e7 j4 w% b) Y( m* o% r, u* ?, d
    FRESULT res;     // FatFs function common result code
. p7 v, R0 Q' M9 G( z! [# I1 P1 v9 S
    char path[20];

: j/ h6 g4 P* ^! Q; O2 l( D* P2 `
    //检测磁盘是否插好

) M/ L5 }+ F2 b
    if( disk_detect_OK()==FALSE )

# N/ m; k  ?& C- Y' R
      return;
' [8 @( t# a( ]) G: |( Y
    f_mount(0, &fs); // Register a work area for logical drive 0

$ s% @8 e- e8 Y" G8 D. n
    printp("\r\nmake directory:>");
4 G  Y$ j2 E; V( n- O* M
    USART_Scanf_Name(path);//通过串口输入路径名

2 n, c7 u  M' S5 M$ }1 i
    res = f_mkdir(path);

  R( [7 l6 p- U
    die(res);//测试函数执行结果分析

8 u9 T; x! t7 t* ]0 z
    f_mount(0, NULL);// Unregister a work area before discard it

( R1 a& S5 a9 T7 D) x! P
}
% E6 R6 |4 h5 `6 {
$ W- ^: H% Q8 U7 ]! I! f
* {8 j- I* G# |+ \5 z: ?6 H$ S4 _) R
//3   读文件 The f_read function reads data from a file.
! u7 F3 E6 K- t  ?* `4 I8 B- v
void Test_f_read(void)

/ k2 A$ {/ \4 v& q$ z, I! g
{
( Y& G$ ]8 }/ B( s
    //用来记录读文件起始时间、结束时间
9 Z4 k, {) g4 ~! j- G
    struct tm time_start,time_end ;
! Q$ |" T, u! P2 S. C
    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。

3 B7 u. Q1 F7 ~+ o, V0 h" w
    time_t unix_start,unix_end,interval;

5 ~; \; W  T- u7 j/ u8 n
    char path[20];

* a+ Y! i; _5 e% [* V# b
    //检测磁盘是否插好
# {! i1 m" p7 k0 H
    if( disk_detect_OK()==FALSE )
0 G' M. q( ^% c2 e% u; W/ `8 c1 J6 r
      return;
+ A, S: N8 Q9 R# U! i! ~+ h
    //printp("\r\nread filebbbb:>");

8 \$ a+ b1 B- ?- p: s) z& l
    // Register a work area for logical drive 0

; E( U& O, V; B( y' Y2 @
    f_mount(0, &fs);
9 b0 \9 Q; ^& P( P, i" @

  _5 ?/ ]+ ?2 c
    printp("\r\nread file:>");

4 Y: x" z- J3 ^1 w4 `
    USART_Scanf_Name(path);//通过串口输入文件路径名

# p& t" e& w: o1 A& I) p
    //Open source file
+ u/ B! d3 k3 n+ \: Z- e0 y* x6 `
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);
" P! _$ t; x& V; B' G" _
    die(res);
. X0 e& R1 c  B* X8 U5 b1 A
    //buffer空间设大一点,会提高读的速度。

! p: Y# B1 g$ L  C" {8 M) R
    //如果文件实际大小512byte

! o" E7 `0 O5 f% z2 h
    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。

9 r( A$ V/ d( Z% X1 _7 e
    //下面两行主要是去除1s误差。

) g8 r3 w5 R7 v" [# y
    //Read_File_Flag = 0;

5 Q9 K) T' y! P5 V+ Z
    //while( Read_File_Flag==0 );

& t$ K$ h: f, O" M4 K# H$ a2 v7 }+ U# C
    //time_start=Time_GetCalendarTime();//记录开始读时间

1 @' b2 f6 ]* D. F
    //unix_start=Time_ConvCalendarToUnix(time_start);

. m9 R) D* v3 C8 R5 [! Q" _5 n, ]; w1 S" w  E5 g8 ]  J

9 `3 P& j+ M# _% X" |6 G
    //输出提示..

" ?6 D5 C( _1 m6 q& u6 n4 T! x
    if( res==FR_OK )

. \2 f! Q  A" e9 `. V- v
      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);

' Y2 }! p& w1 L* J4 O1 h
    for (;;)

3 F2 V/ Z; Y& l8 f" _2 \8 V( b/ D, Y
    {

2 ]( a# x( B$ C6 }+ ~$ n% L
        //清除缓存

$ M' w0 c4 `3 @# ~' 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:590 t0 Q: y( K- @+ G; D. u# U
 SD卡读写数据,FatFS文件系统 源码

- I8 {/ E1 h/ I* x- M求助一个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
学习了~~~' F5 B3 B; @) P: a. b0 {
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 手机版