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

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

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习
, r4 y2 Z4 G* }详细内容请看附件
! Q8 Q+ F1 \; S3 B5 y. w$ h" O
6 N' o" W$ |& B9 e+ W& H2 f本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
! Q, Z; b2 G( c$ b' M" P& [         - M4 {* r% [9 }9 I; g
1 d. ?+ J+ ]* B* a
最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需
+ R) \* s# s8 h8 N. G/ y# y/ r
要调用FatFs Module 提供给用户的一系列应用接口函数,如f_openf_readf_write f_close
$ @! ?2 H& W7 x) A' n
等,就可以像在PC 上读/写文件那样简单。
" }0 j1 m7 e% n9 {5 a8 i0 `( A& q
中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c

! d* ]9 W- }( \! O4 B" u- z0 ]1 V
ff.h,简化版Tiny-FatFs 提供的是tff.ctff.h。除非有必要,使用者一般不用修改,使用时将

6 ?$ [9 ?% M1 P. I) k
需要版本的头文件直接包含进去即可。
7 V3 f; M* {* j: l, ^
需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写
7 r* }! A; i1 N* L0 t) c2 Q  u2 w
接口Disk I/O 和供给文件创建修改时间的实时时钟。
; o- T) f! C% e+ L% U; B9 e0 |! l
; d. U: ^" J( |5 W- P7 D
                        本例程的程序结构图
# h2 }! m7 P6 Z) w
                  
: ?9 `3 D0 k2 V3 P9 ]0 i# A
9 v* ?* O9 Z# B4 V
RTC_time.c

1 |2 Z3 a+ d+ w: q7 e( V
Diskio.c

: r2 C% a! U% \7 P: I/ r4 j9 d* p  |8 t
SD_driver.c

- B7 ^0 e# P1 w  F3 C) y( }) c3 u
ff.c

  c4 n. J# s5 N' a* }2 y
fatfs.c

' B9 g& N( `& Y. ~; w- J7 d
6 F2 }9 u5 b: X7 F) F' U7 g
程序的编写

' |: n& \2 L+ `. b
下面我们开始代码的编写:
8 e' `1 X* n' {
1、  主函数的编写
. k6 `2 @) W1 q- `& {
int main(void)
# y  M& p! [2 x
{
: K  L4 u0 X9 G6 t8 \1 q
  RCC_Configuration();

& Q/ m" w% B7 A2 Q( [( m7 H4 P
  GPIO_Configuration();
! O8 y0 C, r; [7 v4 e
  USART_Configuration();
  Y* k5 j( s) u9 S) B: U. q/ H7 s
  SPI_Configuration();
7 }7 g8 F8 _& Y& n' }3 F; z) S6 X
  FATFS_TEST();   //FATFS常用功能测试函数
* b2 `* N3 l/ C1 s* M3 [" s
  while (1)

( `0 n( \: W) B! t& X; S
  {
8 H- O' j' k$ t  d1 f# u! ^
  }
; q3 _0 X: k6 |& N2 u( ~2 A. |
}
# z" i! H2 V0 v8 k" ^
这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:
1 j. X3 b7 U3 D$ M& E4 G. _9 i$ p: O
void SPI_Configuration(void)
+ H% p2 X* B5 X# W$ K- X( m% N
{

& ]+ w7 S9 P4 p* J
  SPI_InitTypeDef   SPI_InitStructure;
3 o1 Z3 ?! O9 l/ z; b- P9 w
/* SPI3 Config */
) H* R( U- _; C1 x0 w- r/ Y
    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写

. S7 F9 m) S" u  S" i
这里使用文件SD_driver.cSD_driver.h来写出SD读写的一些驱动函数。

( L. C& q1 K% s
函数列表如下:
' k/ [& z: S% ]0 k8 f
/* Private define ------------------------------------------------------------*/
& M9 e' N8 W+ H' U; h* h
/* SD卡类型定义 */

2 {+ G! M2 h  J5 m# z3 O
#define SD_TYPE_MMC     0
/ W! `- \, h' H# Z) ~8 v
#define SD_TYPE_V1      1
" F/ e% {4 `" ~3 E. ~
#define SD_TYPE_V2      2

( Z7 e( C5 v# p* |" n8 o
#define SD_TYPE_V2HC    4
2 E" D2 C. _/ A6 V& n# c' `

: y7 r! B1 K/ Y, l
/* SPI总线速度设置*/
/ }; _+ X$ |2 N! k2 k
#define SPI_SPEED_LOW   0

$ U- X- Y6 z3 \; P+ N: d6 l
#define SPI_SPEED_MID   1
& k( z  A/ {4 M2 t9 r! L8 E
#define SPI_SPEED_HIGH  2

0 x" M  _1 _' n0 L' N
/* SD传输数据结束后是否释放总线宏定义 */

. w* A0 ]' Z" V$ V7 \
#define NO_RELEASE      0
/ S. K* M( |" g6 ?7 f
#define RELEASE         1
! n) \( `% U$ b* k! [( i

$ d- \7 J$ J- j, }/ e8 Q
/* SD卡指令表 */
2 j: _) @  C0 Q" a
#define CMD0    0       //卡复位
: j% S! z6 K) A+ \9 V
#define CMD9    9       //命令9 ,读CSD数据

2 K- D/ I' o  X4 o6 i/ ]
#define CMD10   10      //命令10,读CID数据

# C& l+ y5 o5 O8 c4 `2 g
#define CMD12   12      //命令12,停止数据传输
" z' R: U( s6 i, i. b0 K! ~: \
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
" }* L$ D+ p- _- K7 }* H
#define CMD17   17      //命令17,读sector

& O$ f8 u! p! e$ j: Q
#define CMD18   18      //命令18,读Multi sector

3 p# w3 u8 `3 ]# s) A) b+ M3 p, M6 K
#define ACMD23  23      //命令23,设置多sector写入前预先擦除Nblock
; C- e) H# M7 y+ w! B4 ^* @
#define CMD24   24      //命令24,写sector

# _, V1 G- y' S9 ]0 e, I5 g4 A
#define CMD25   25      //命令25,写Multi sector

, h+ Y. U% b0 u# y7 h9 V- K; |
#define ACMD41  41      //命令41,应返回0x00

5 `: z2 D# ^0 Q& \# E, L7 `( {, a/ F2 {
#define CMD55   55      //命令55,应返回0x01

% Z4 |" M. A5 w, W
#define CMD58   58      //命令58,读OCR信息

( `' Z  q* \7 f
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00
. j) H. ^& w: E& r+ W; J. z1 _

, |, V2 k0 v7 I& {$ Q: d
/* Private macro -------------------------------------------------------------*/
0 U3 z: W8 D' d9 k
//SDCS片选使能端操作:
8 H% I6 x3 I9 f) M* w
#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD
! U/ [- `- M( ^/ {
#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD

/ S  _# P7 W* M
#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电
' v& `6 d* Y2 M4 j. w+ X
#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电

* h/ \1 s6 h1 E" @# p0 e
#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡

2 j8 u7 L3 a* |% X
                                                                    //1- 0-

1 E6 C) n& g% t' ], \$ l 5 z5 E/ \& ?7 u; {1 y9 a; }* g, `; b
/* Private function prototypes -----------------------------------------------*/
* ?" r3 f; R3 b* Q5 [9 v
//void SPI_Configuration(void);

4 K. }% X7 o0 p1 F
void SPI_SetSpeed(u8 SpeedSet);

; a7 ^9 f' R' y, C1 W( Q 5 @- c1 K& m8 T2 c: M. j* b& }
u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节
7 ]3 q' {% Q3 C  U8 Z7 [# @
u8 SD_WaitReady(void);                          //等待SD卡就绪

& y; P/ W# N( z7 S* V
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令

. X6 |" c/ ]% h4 x- a$ F1 l
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);

' l4 Z: {- W, Q7 X
u8 SD_Init(void);                               //SD卡初始化

+ D' O4 J% l4 q2 g
                                                //
' ]0 G1 c. V) D
u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据

: h: _) E: w9 X
u8 SD_GetCID(u8 *cid_data);                     //SDCID
/ I, M& {/ S/ f; ]; m% j
u8 SD_GetCSD(u8 *csd_data);                     //SDCSD

# F7 [" p, F* l; W. q8 l5 k
u32 SD_GetCapacity(void);                       //SD卡容量

% d1 o8 P; H7 D9 c3 b* |' @
  Y$ u7 x" R' Q5 V& N5 N
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector
, Y0 Z) Y  w2 f) j. V2 ?! W+ f
u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector

3 Z5 h; O8 X8 r" |$ d* s5 Z5 ~
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector

% P$ K1 U  D$ Z2 X$ X
u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector

2 ]' f& X0 Z, E' [( r7 D. ~" Q9 w , P' ^4 N0 p$ K) ~  k2 W
3、  文件系统的移植

  L  Z# R+ q5 l, l% L! [/ P1 u; u/ w
FatFs文件系统主要有以下函数:
% J/ T! [2 l5 L* K! t) g
/*-函数详细的解释请查阅附录,点击链接也可以到----*/
0 s5 C. i1 s9 q' R0 F
/* FatFs module application interface                  */
! ]3 o) _9 E6 Z) J/ t

( ?9 T, l) |2 Y8 g+ t0 d! }& b( m
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 */
! `8 k3 I) B9 ]$ S; }

9 x% q" e, M& W  C0 U
4、  底层接口I/O函数的编写
0 k' Q4 k" Q7 e# Y; q$ b; G/ b/ ^$ ^, K
底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:
3 z* |$ u) Y/ X$ U- r9 F, R9 a# q
/* Prototypes for disk control functions */

, n: Z% ]9 q! o
DSTATUS disk_initialize (BYTE);
- |4 Z2 z4 F! A4 Y
DSTATUS disk_status (BYTE);
) A4 e, Z% ^1 ?3 M0 Q9 m7 g, d
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
7 Z" d  a0 x/ L! F, I5 A5 {" Z/ A
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
% I$ ?. I5 R( E# b% \
DRESULT disk_ioctl (BYTE, BYTE, void*);
7 l: K9 A0 }' x/ ]& ~% f! m$ s5 A
DWORD get_fattime (void);
; Q. e1 w! m% u- x: h5 V
6 个接口函数的详细信息如下图所示。

5 m. U6 ?  k$ j: `7 P  M7 t
Disk I/O 函数结构图
  b# ~, \4 Y- ]6 S* s
因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。
1 c6 Y' A) F" T) n1 W4 A2 J
1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime

# L- f7 d6 `& ]* _
5、  应用层函数的编写
  a/ o. n( N9 U" c9 j
我们这个例程要实现的8个功能如下:

$ c6 y! {: z) A  @, R2 v( i- y
" h. c4 T; z5 K7 Q6 @
每一个功能都对应一个函数,各个函数如下:
* p, M1 M( ]2 H; b( y4 q( C$ G
// 0  读取磁盘容量 The f_getfree function gets number of the free clusters
* @/ A" Q$ j! q$ D  U: u
void Test_f_getfree(void);
. `6 [$ k9 Y% [, e8 a5 c5 P
//1   读磁盘目录 The f_readdir function reads directory entries.

" `# K& a$ k& {& w( V, n5 ~! B
void Test_f_readdir(void);
# [# B9 N" g* G+ b+ k# P
//2    创建目录   The f_mkdir function creates a new directory
% H$ z: Y4 j- Q
void Test_f_mkdir(void);

* G9 H: n' I* j; Y5 Z6 \, f( M7 f# x" c
//3    读取文件   The f_read function reads data from a file.
5 m9 P! l* H6 B& b
void Test_f_read(void);

5 Q* H) h( @( Q- y- b( Y4 Z. x
//4    文件拷贝   The f_write writes data to a file.
* T) m+ t" h- E4 L5 M4 k
void Test_f_write(void);
8 `# F- L, `4 V$ E
//5    重命名    Rename file or directory
. W/ e9 y  \6 r, Z
void Test_f_rename(void);
0 k! T- r, G, h: C) d0 n  ]; o" y4 U8 f# {) g
//6    删除文件   The f_unlink removes file or directory
8 @3 b; }0 f  E0 @$ e/ ?6 l
void Test_f_unlink(void);
1 H. d1 g' K6 }7 |% z
//7    格式化     The f_mkfs fucntion creates a file system on the drive.
  G( t% N& D; q4 ?7 x/ Y% }
void Test_f_mkfs(void);

) P& \6 j6 @5 {# W% J, { 4 w* j0 w# k- m/ g
! I' Y: j: C( v& \- b5 s+ L
8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:
) G, g! s, ?& F
void *FATFS_Function[][2]=

0 R% B1 r$ d& H$ y% n
{
: O7 j8 X' }1 ?2 h+ g, e
    (void*)Test_f_getfree, "磁盘容量",

7 s1 {4 N$ g  _* F. g' b
    (void*)Test_f_readdir, "读目录  ",
3 |( q0 m4 [4 c& o; ^% \% U* K
    (void*)Test_f_mkdir,   "创建路径",

! G# B( R: _. h/ ~" h. g
    (void*)Test_f_read,    "读文件  ",
' r* m4 [0 N, {! C" u; h4 R
    (void*)Test_f_write,   "文件拷贝",

  F/ {! l. S& J6 A$ n
    (void*)Test_f_rename,  "重命名  ",
! q) ]6 Y4 U! H
    (void*)Test_f_unlink,  "删除文件",

* e6 ?; i: I- e7 M
    (void*)Test_f_mkfs,    "格式化  ",
. n4 J0 h! T- D0 d9 ~' }, w5 i
    0x00,0x00

/ W: X; m$ j9 s# `
};
# \4 C8 O9 ?4 c
8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:

( C( A& i0 b) Y
0//The f_getfree function gets number of the free clusters

  O! w. ?/ w6 Z3 S% L6 U% c! U
void Test_f_getfree(void)
4 O" E% \: p6 T
{

. ?3 F' |; V+ i7 U1 l# k( A
    FATFS fs;

1 h. I# ~# K( \7 c. m& |
    FATFS *pfs;
6 T  |( [6 U8 v; x
    DWORD clust;
1 {+ \; r) Z5 U% [8 M" H0 v
    FRESULT res;         // FatFs function common result code

; T# \) |( x  ^/ d8 S: q. K
7 Z7 N' X! Y6 b. r+ H& d
    //检测磁盘是否插好
; I) |. G8 @; ^' L) }
    if( disk_detect_OK()==FALSE )
# R9 W; q( R" B# {) ?
      return;

! K3 t2 p$ V- L7 k. \* H* S) a  T  P
% W' n. a% ]: M3 L
    pfs=&fs;//指向
7 _, R# s( I3 ]
// Register a work area for logical drive 0

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

% D# G& D4 ^/ N: _% @6 ?6 e" u! h4 `
+ h4 o! P% M, K9 R+ h5 P

  a* W2 ?$ |; q" H5 ^3 n
f_mount(0, &fs);
( k  ~" f- Q9 F$ Q& a6 a

0 o; D5 v" Z' z. }! N
// 获取空闲簇Get free clusters 空闲簇的值存在clust
* U* }& ~' O. n7 K
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0

& a6 I0 b7 [: f6 T. u7 `4 i5 \( q
    if ( res==FR_OK )
' d+ ^  I+ b' n1 y( P7 T9 G
    {

4 N6 r% I! O9 N5 H5 w" E* D$ T
        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小

. P8 X6 ?  d; T' W+ h8 X, v
              //计算方法:

3 N5 M7 K& C1 S+ J+ N
//   总空间大小   最大簇数×每簇的扇区数÷2÷1024
* g" l- Q. U. U8 O$ a# ]) D; Z
//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024

" r% d1 c4 ^3 j3 U4 {
        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",

4 v% u' m4 ~% I  u
        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,

. r, K* j3 t: d  K
        clust * pfs->csize /2/1024);

2 n" z, }7 k) h+ [$ x
    }

7 A8 i6 I% e/ |# d
    else

" Z3 i7 W: l6 R# A6 @. o7 b& \& y
      die(res);//测试函数执行结果分析

7 u- T# {- U& f+ c( H  c* f3 u
+ }) b" ~" d$ d& O5 n$ f* B: l. ^
    // Unregister a work area before discard it

# E- s% w6 @' W  P
    f_mount(0, NULL);
, {1 C9 u. Y$ t6 [: x' A
}

1 p- _5 E9 R6 ?" d: P
- _, ~0 ], m. l# c, \; ~
* R  J5 Z2 W5 M+ ?' L" e* K 3 `+ P8 G- X2 s# M. W) e* Y! R
//1  读取目录 The f_readdir function reads directory entries.

2 t% T/ f9 F# m0 p) ~; t+ e
void Test_f_readdir(void)
) |+ U* e% ?+ E- ?0 K. k
{
9 q8 U* A6 k5 q0 G" J6 c
    FATFS fs;        // Work area (file system object) for logical drive

  W! p5 I7 m! B0 M
    char path[20];

) L  P/ X$ C% a' P2 }7 Z: N7 @ 6 j. _2 Z9 ~$ l/ |& G. h" Z6 d
    //检测磁盘是否插好

9 |+ \  w) C% I$ @0 N- u4 a
    if( disk_detect_OK()==FALSE )
. m- A. @+ c$ t! j) r$ p( E
      return;

- Q0 r: q8 N( c! \( i
0 v9 E" o5 n: }, ^' {. m0 a+ p
    f_mount(0, &fs); // Register a work area for logical drive 0

4 X, X, ?. D' L$ w! h / r2 H6 t4 F$ q  n, B5 s' n
    printp("\r\nread directory:>/");//默认输出主目录下的文件

- H% Z; M4 Q# J6 U- A! u- R% X ' |4 {# n; A  j
    USART_Scanf_Name(path);//通过串口输入路径名
( `1 _4 l$ S6 a$ ?' x7 F

: U" p; t# {; r1 t
    //扫描当前路径下子文件夹,并输出到串口

8 _/ S$ H" i0 h6 v* w9 u) @9 p
    scan_current_folder(path);      

: F1 ]; X( q/ ?) [
    //扫描当前路径下文件,并输出到串口
7 k2 O3 U  ^, A( \1 M$ e
    scan_current_files(path);

( O' S- Z% p! x 9 g% D  Z2 m7 h
    f_mount(0, NULL);// Unregister a work area before discard it         
6 I/ ^/ Y1 N1 s8 B8 f$ Y* k8 X
}
& |$ z% ]4 b9 z* d5 U2 }5 y) J) T/ G

8 f9 O5 f( `6 e/ C5 q
% Z' \; N" S$ W/ t: q: p& ^1 V( u
4 `9 c6 W/ _# a+ X: b
//2  读取目录  The f_mkdir function creates a new directory
  p6 }8 E4 H% f0 A. G1 T  N
void Test_f_mkdir(void)
( P6 S9 Y4 X9 g2 v7 K. Z
{
1 v6 a2 N$ G9 H$ u+ |( y" n
    FATFS fs;       // Work area (file system object) for logical drive
) N1 Y" g2 m4 M+ v
    FRESULT res;     // FatFs function common result code

, i9 g2 u9 V3 g2 p! P
    char path[20];

: P4 O" n- M  H" L4 I2 [
    //检测磁盘是否插好

1 X! ?- [# W2 \( f! c# B2 U* u
    if( disk_detect_OK()==FALSE )
6 ^/ k/ n( c+ i7 g$ W+ |% y
      return;
6 e  Y' n5 L  ?/ }
    f_mount(0, &fs); // Register a work area for logical drive 0
6 b+ O( d2 P9 _, B  [
    printp("\r\nmake directory:>");
2 @4 }5 P$ C5 _6 u' U! Z
    USART_Scanf_Name(path);//通过串口输入路径名

; L% w; }- \* ]( f. p8 |
    res = f_mkdir(path);
* p% W' [: }, n6 X* V" W, h" F
    die(res);//测试函数执行结果分析

; d% V) |# T, p$ X
    f_mount(0, NULL);// Unregister a work area before discard it
( I) A  Z: Z; o3 H2 h
}

7 L  h6 ~* D/ F  p* e& z$ P: ?4 D! }# D
6 E8 |! w! F. \
//3   读文件 The f_read function reads data from a file.
8 c' `2 ~5 ]  ]+ l
void Test_f_read(void)
* q2 ?7 M9 s% B" z3 `
{

# r" a* s, ~2 H2 e
    //用来记录读文件起始时间、结束时间

6 s2 Q7 F  x* @0 i2 V
    struct tm time_start,time_end ;
8 W. h  d( c% c9 r
    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。

; L% b4 H6 r& O% a! V$ i9 {
    time_t unix_start,unix_end,interval;
/ p" h% p# ?; |4 A
    char path[20];
# G2 B% J, a0 f: s
    //检测磁盘是否插好
7 \2 ~( g. f* N" ~$ a
    if( disk_detect_OK()==FALSE )
& Q# u: |& i& {& U: _
      return;
) Y# H7 G0 m/ p
    //printp("\r\nread filebbbb:>");
0 d. _1 E9 b! x3 P' u5 R4 _6 l
    // Register a work area for logical drive 0
; b# X% a0 ^. M# |% b5 g. M
    f_mount(0, &fs);

/ H4 i3 N3 d+ x2 b
0 z  a# `& W5 }5 a% G. s
    printp("\r\nread file:>");

& `+ h8 p! u- N7 Y7 n) B' }
    USART_Scanf_Name(path);//通过串口输入文件路径名

* i9 t: J. H  ?
    //Open source file
& ^* F& v! q: j0 A
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);
/ ]5 L4 Y+ M5 P* @, @- K
    die(res);
, _( Y9 A; N: j/ r  U" M2 W8 ^
    //buffer空间设大一点,会提高读的速度。
/ u; D" E& ^7 x: K1 s# S$ T
    //如果文件实际大小512byte
( {8 C: F& @! O; G6 k+ T( N5 s
    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。
, U! q+ g. R* ~" R- D
    //下面两行主要是去除1s误差。
8 J; `% r; c4 L- m
    //Read_File_Flag = 0;
/ z0 R* D0 Y6 o! ?
    //while( Read_File_Flag==0 );
9 J4 G& a( Q" D0 X/ ^( H( v, c7 |7 _3 z; x
( C" l, r& b' a( ]% z- t& R! T9 o8 s( K
    //time_start=Time_GetCalendarTime();//记录开始读时间

, G  L; d7 R5 e' w9 V3 B/ a$ s) s
    //unix_start=Time_ConvCalendarToUnix(time_start);

& H6 i+ U2 K* C" `
# ~; i/ j2 ^' _/ [9 c
2 A/ u0 d; [; {7 l1 a
    //输出提示..

. r1 p: R2 O7 _6 K& B; H) c
    if( res==FR_OK )

4 W/ s# U+ U- M
      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);

2 B* e0 \  s+ x0 D* [' V1 B( R
    for (;;)

1 Z( W( n0 [2 J) s) `2 \: e
    {

# a) J4 `/ q/ c. ?) w0 m
        //清除缓存

; Z# z  [2 [, A/ v5 A6 ~- m
<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:594 p  C& F4 d' k" Z
 SD卡读写数据,FatFS文件系统 源码
1 b" [; R( {% |9 C- H
求助一个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
学习了~~~* p+ L" ?2 d+ N3 `0 E' 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版