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

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

[复制链接]
ren0zhe 发布时间:2013-11-20 09:57
第十五节 SD文件系统的学习
" o& \% S& n8 }  o% m* y6 q详细内容请看附件6 O' t: ~3 z- l

+ f% L: X1 E/ S: f0 g" x本节我们通过科星F107开发板的SPI接口对SD卡进行数据的读写。主要学习的内容就是SPI的配置与文件系统的移植。这里我们用到的文件系统是FatFs, FatFS 是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 的编写遵循ANSI C,因此不依赖于硬件平台。它可以嵌入到便宜的微控制器中,如 8051, PIC, AVR, SH, Z80, H8, ARM 等等,不需要做任何修改。
- N7 T3 u; V2 m. d/ p1 c* S         
/ L. ?' R2 {% y2 U3 G' _# w $ r9 H- `- f( t
最顶层是应用层,使用者无需理会FatFs Module 的内部结构和复杂的FAT 协议,只需
# ?& y6 F% ~% ]' u; ^0 i8 [
要调用FatFs Module 提供给用户的一系列应用接口函数,如f_open,f_read,f_write 和f_close

& [/ ^4 j) F& g$ B' n+ I
等,就可以像在PC 上读/写文件那样简单。
, |4 n) B& D. R& h6 f" |8 h- J( n
中间层FatFs Module 实现了FAT 文件读/写协议。FatFs Module 的完全版提供的是ff.c、
0 i( e1 n+ g% X
ff.h,简化版Tiny-FatFs 提供的是tff.c、tff.h。除非有必要,使用者一般不用修改,使用时将
% b0 U5 p* H& j# m
需要版本的头文件直接包含进去即可。

# N7 M) L3 g5 ?, E! w6 R/ Z% K
需要使用者编写移植代码的是FatFs Module 提供的底层接口,它包括存储媒介读/写
& q$ @" _# U* @! i7 Q( j
接口Disk I/O 和供给文件创建修改时间的实时时钟。

$ N" G6 k: ^) g5 V7 j9 Q5 h2 [# f * h" t  V4 m6 h. X/ m& M: G' ^
                        本例程的程序结构图# f# |9 u: {, K3 \  ?$ \) `3 F6 x. F
                  
' A0 b8 M) |, C1 c 0 k: n% M, ^. r1 b
RTC_time.c

; c$ _3 f( ^/ S! {* s3 G6 e
Diskio.c
0 q- H4 G8 N8 s& V- B
SD_driver.c
9 h2 X" _4 T4 D( j8 c$ U. C' h
ff.c

0 H7 C0 D1 Y1 m8 ?; \# L
fatfs.c

: o" b* @4 I" L9 ^5 p+ j2 j
) t, J7 a- i; G' ~& Z$ p
程序的编写
# t+ _: |$ p& O3 w7 \" x# |
下面我们开始代码的编写:
/ l9 A5 n  |+ R6 h6 k/ ?
1、  主函数的编写
( V+ _( o2 A+ O) l( ]/ g+ _7 ]' f
int main(void)

5 P7 h$ {. P3 m  _! }* f% L
{
' T0 H7 S8 A9 f
  RCC_Configuration();

5 P8 y3 s7 _5 V; F% z
  GPIO_Configuration();
8 }. K0 E3 u, t6 k
  USART_Configuration();

/ L+ x' n$ C  ~
  SPI_Configuration();
& ^) o5 s- q7 j: g' [( A
  FATFS_TEST();   //FATFS常用功能测试函数
* x3 F* D; j8 k4 `2 S7 x; a1 e
  while (1)
2 X& R; ~! q* K( v3 x" J) C
  {

& W0 ]! e! C7 C5 v! e) b, ~9 L
  }
7 c! L2 o( E/ F$ Q7 [
}

; y: @9 m: [2 o
这里新接触的配置函数就是SPI的配置了,也是使用库提供的结构体对SPI进行定义,更多的SPI的介绍,我们这里就不多说了,MCU的芯片手册写的也很清楚了,这里复制过来也没啥意思。下面我们看一下SPI的配置函数,代码如下:
4 z& a* F( p: [1 t
void SPI_Configuration(void)

# V+ b8 A) F* Y( s* Y
{
6 u; Z; o+ R& s3 ^
  SPI_InitTypeDef   SPI_InitStructure;

3 l. a& [/ a% x4 K: ^7 [
/* SPI3 Config */

+ S! k$ D  q, f  `# V7 {1 D) M( `' k
    //一开始SD初始化阶段,SPI<i>时钟频率必须<span lang="EN-US" style="color:#4F81BD;mso-themecolor:accent1">SD卡驱动函数的编写
7 f6 _# F0 y( ^. K' T2 v" F5 U
这里使用文件SD_driver.c和SD_driver.h来写出SD读写的一些驱动函数。
' k' |1 p' H# s, ^
函数列表如下:
6 t; w$ ]- V' E" c
/* Private define ------------------------------------------------------------*/

6 Y' E- d3 x6 g: O) P+ \- p- X- l2 v
/* SD卡类型定义 */

2 E, @' w- f# K1 d: O, f- e
#define SD_TYPE_MMC     0
; C3 A0 H& P% c' g+ a
#define SD_TYPE_V1      1

: t3 K; o- k$ ~  _: ~7 B
#define SD_TYPE_V2      2
' K. @8 {8 W; F8 |6 r% r
#define SD_TYPE_V2HC    4

/ C- o1 |( t# O0 L6 _  V, i4 ~, K
. U8 Y" v: m9 o+ A: \' h5 [
/* SPI总线速度设置*/
0 e5 a, E" v( F4 a
#define SPI_SPEED_LOW   0

2 X9 b8 d- J) p3 g; _* g1 w
#define SPI_SPEED_MID   1

) G2 T/ w# i, \: _" d( H8 S
#define SPI_SPEED_HIGH  2
; t8 o8 D1 t$ E; v8 R- }) x, f
/* SD传输数据结束后是否释放总线宏定义 */
5 [, S+ D' J" E* f4 i* ?
#define NO_RELEASE      0
" {/ i% u2 E) d) P
#define RELEASE         1
5 B+ t8 O) `3 {: a/ T2 y
2 g/ D1 }( T" Z3 q, J2 {
/* SD卡指令表 */

: j1 l9 I5 w3 S2 d
#define CMD0    0       //卡复位

' F  C' h6 b8 q, Y
#define CMD9    9       //命令9 ,读CSD数据
+ X! {$ E7 {( j
#define CMD10   10      //命令10,读CID数据

7 b/ \2 C! g" ]
#define CMD12   12      //命令12,停止数据传输

4 a  q  Y2 G; q- Y. y; a! a
#define CMD16   16      //命令16,设置SectorSize 应返回0x00

  k) q+ F: ^/ j, v$ k
#define CMD17   17      //命令17,读sector
. }4 b7 P6 L( D: |& n. d
#define CMD18   18      //命令18,读Multi sector
6 I( t3 v  k8 a5 c; I
#define ACMD23  23      //命令23,设置多sector写入前预先擦除N个block
, T+ Z. k# q1 O3 g) X+ D
#define CMD24   24      //命令24,写sector

% }# s" Q1 |% V: L
#define CMD25   25      //命令25,写Multi sector

' H" Q1 t, s* v; }- j9 q4 P
#define ACMD41  41      //命令41,应返回0x00

3 B1 U7 p- {+ ~5 V9 g* P
#define CMD55   55      //命令55,应返回0x01

7 J; [0 }4 \1 f4 L" n( Z. K% V
#define CMD58   58      //命令58,读OCR信息

- `8 x. Z" W4 o- S7 i  x* G  {: l
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00

8 r5 q' Q3 S6 {7 ]
, c$ ^1 G2 x7 r' w2 |( U& j$ v4 i$ v7 A
/* Private macro -------------------------------------------------------------*/

7 A* T; x1 M& h1 ~6 ?+ N
//SD卡CS片选使能端操作:

  o) U, d1 g$ P) W  |
#define SD_CS_ENABLE()      GPIO_ResetBits(GPIOD,GPIO_Pin_2)   //选中SD卡

- ^* Z# U8 ?: `- i/ ?# U' b- T
#define SD_CS_DISABLE()     GPIO_SetBits(GPIOD,GPIO_Pin_2)     //不选中SD卡

! j' E4 G- x- @6 b3 a
#define SD_PWR_ON()         GPIO_ResetBits(GPIOD,GPIO_Pin_10)  //SD卡上电

  p( `4 v! Y, T0 v4 ]: n7 L7 q' Q1 e5 ~! v
#define SD_PWR_OFF()        GPIO_SetBits(GPIOD,GPIO_Pin_10)    //SD卡断电
' j/ z2 w+ ?7 D! \. H' ]6 x8 j
#define SD_DET()             1 // !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡
1 Y6 I  ^" j4 `; t" J: \
                                                                    //1-有 0-无
1 _: G* U" V9 E1 e, r  Z
+ E4 V2 K, d2 }2 O. w
/* Private function prototypes -----------------------------------------------*/
* j0 u0 O7 Y5 n, d: X3 p6 v
//void SPI_Configuration(void);

/ c" z. q% G7 ~2 l/ h1 g
void SPI_SetSpeed(u8 SpeedSet);

5 X) d0 [# a2 s5 X1 C- i% j9 L   b# i; q6 K. [* L" k" N: n4 N
u8 SPI_ReadWriteByte(u8 TxData);                //SPI总线读写一个字节
7 k! D$ X4 L/ X% D* o
u8 SD_WaitReady(void);                          //等待SD卡就绪

* j( ^( m" \7 ]. P" h
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc);     //SD卡发送一个命令
' }3 b; A; z6 _" }2 k3 G2 f
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);

/ \% S! E. J5 ~) S
u8 SD_Init(void);                               //SD卡初始化
# H% v) K  P+ j# c
                                                //
) o, m. z. _* F+ t' O
u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据
0 C+ w: t$ \0 z, b! ]
u8 SD_GetCID(u8 *cid_data);                     //读SD卡CID
9 R" M1 \5 ]1 l
u8 SD_GetCSD(u8 *csd_data);                     //读SD卡CSD

% A. E' B1 B) Q! `' \
u32 SD_GetCapacity(void);                       //取SD卡容量

  _0 M4 E1 z! [2 o $ W% q. n# H+ M4 @" E
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer);             //读一个sector

. F- G& Q% P, C: P: j/ X
u8 SD_WriteSingleBlock(u32 sector,const u8 *buffer);       //写一个sector

: F1 J8 U) A: m0 D+ G0 w, b
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count);    //读多个sector
1 g: B& W: a$ m: ]  H0 E
u8 SD_WriteMultiBlock(u32 sector,const u8 *data, u8 count);//写多个sector

1 K# B8 H: G2 A9 z& h7 N
; B3 \; `  a+ T4 n/ I
3、  文件系统的移植

7 I# o3 m2 Z' z% `
FatFs文件系统主要有以下函数:
* x0 H6 e5 Z0 B3 ~. R. o
/*-函数详细的解释请查阅附录,点击链接也可以到----*/

- I/ W8 L  U( `2 R5 N1 x1 [
/* FatFs module application interface                  */

# R& i) T: s  y/ A
  l) ^  d4 \, S% p# l) B" E
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 */

! f) {- N- V* ^3 {5 S+ @1 S/ e
" c: A# m% Y* `- Y) ~4 Z* i9 m0 N
4、  底层接口I/O函数的编写

/ X: }5 O, P$ u* r5 J
底层驱动是必须由用户自己完成的,函数均放在文件diskio.c中,函数如下:
6 v) A2 R$ G6 g; y
/* Prototypes for disk control functions */

4 J4 e% K7 m) W
DSTATUS disk_initialize (BYTE);
6 W$ j/ t* ?: L- G% l( `6 E
DSTATUS disk_status (BYTE);

9 t6 ], i% b6 ^) N
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
: X; i$ C+ T# ?! N5 ^( Y- Y
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
9 M3 Y+ j" a" ~6 S( r! x
DRESULT disk_ioctl (BYTE, BYTE, void*);

; W$ q, L9 X9 l4 s
DWORD get_fattime (void);

6 W  p4 ~8 X2 W- E& }: F
6 个接口函数的详细信息如下图所示。
0 ^  L* N' v1 \5 `& }3 z
Disk I/O 函数结构图

. A, Q* `) q+ r. C, E+ J8 z7 I
因为FatFs 模块完全与磁盘I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘I/O 模块并不是FatFs 的一部分,并且必须由用户提供。下面的函数位于diskio.c 中。

$ m4 l$ `7 C! q# b
1)disk_initialize
         2) disk_status
         3) disk_read
         4)disk_write
         5)disk_ioctl
6) get_fattime

0 n5 c' \4 b. G% U$ |2 ?
5、  应用层函数的编写

; e7 y; a+ d& G' V7 j" }; w, X* a
我们这个例程要实现的8个功能如下:
6 _5 \; x1 {  p5 \. g5 o
2 D4 M4 r( U' P3 ?
每一个功能都对应一个函数,各个函数如下:
  E# _% A+ y; Z& U
// 0  读取磁盘容量 The f_getfree function gets number of the free clusters

# I' Y) T, h. y; N
void Test_f_getfree(void);

* l+ M! _/ H6 c
//1   读磁盘目录 The f_readdir function reads directory entries.

) r% j$ ?: n" h0 _0 ]* l
void Test_f_readdir(void);

! i2 N, [) e! _& M5 Q, B9 |
//2    创建目录   The f_mkdir function creates a new directory

+ y$ R- |: U' @2 o/ h8 c
void Test_f_mkdir(void);
2 R( o# f; w. E
//3    读取文件   The f_read function reads data from a file.
. ~& H" H2 v5 T% G; R
void Test_f_read(void);

* _( Q$ K5 z' ?" c
//4    文件拷贝   The f_write writes data to a file.

- y4 O! i9 z+ y& ]1 |! J& Z
void Test_f_write(void);

! u% V) f6 {3 M1 {! n: [2 o7 `! K
//5    重命名    Rename file or directory
( l* I$ d1 S9 e2 R* J% }4 F
void Test_f_rename(void);

. C* k+ I- d. t( ]! H" A) P* T
//6    删除文件   The f_unlink removes file or directory
$ G# o# \" D4 v0 ?4 Y) D
void Test_f_unlink(void);

9 _  a, \( @* @& n0 ?! y. i
//7    格式化     The f_mkfs fucntion creates a file system on the drive.
( t& |, X6 i1 j" `6 ~
void Test_f_mkfs(void);

" \5 O3 r8 _& s+ G* t, J, R
# B/ |3 ^* o  J7 N( d9 H
5 a0 W: l2 v6 Q/ E3 A
这8个函数的调用是通过一个二维的函数指针数组完成的,该数组如下:

5 t' f# d) ~; t; n; `
void *FATFS_Function[][2]=
" k1 T- z3 }4 e: z; P6 e; Z+ f2 t. _# R
{

: r, t( @2 L2 x+ i2 T
    (void*)Test_f_getfree, "磁盘容量",

1 s2 l+ t2 }9 c. T
    (void*)Test_f_readdir, "读目录  ",
$ b' [& I# q; L" |. y  N
    (void*)Test_f_mkdir,   "创建路径",
0 C$ J& i0 w0 [, R- E
    (void*)Test_f_read,    "读文件  ",
3 Q/ x: _/ O" g8 h- D9 Y
    (void*)Test_f_write,   "文件拷贝",
8 ]/ \& l0 Q. C& ~) n' a8 E
    (void*)Test_f_rename,  "重命名  ",

- c) E1 e# k) v+ Q/ O
    (void*)Test_f_unlink,  "删除文件",

, h5 L& \/ p  {
    (void*)Test_f_mkfs,    "格式化  ",
6 o% U0 k) D6 E
    0x00,0x00

5 [" d) k4 k: B' E: d# L0 r
};
, {+ o( t, t( H
这8个函数完成的功能都是调用FatFs文件系统里的函数,FatFs文件系统的函数前面已经列出了列表,在本节最后面我们也附上了函数的详细定义及用法,请查阅。下面我们着重分析一下这几个应用函数:

" {+ J( W; l: Z. H  ~2 n, ]% ^
0)//The f_getfree function gets number of the free clusters

; Y6 V- O$ O  k: h2 Y$ J
void Test_f_getfree(void)
( B3 o$ x# j# r7 w& v1 V
{

1 L4 C2 a/ T1 Y/ K0 \' a
    FATFS fs;
( k3 p$ z6 }( _4 w6 F
    FATFS *pfs;
. A4 F1 C, Q0 o9 {
    DWORD clust;

4 g7 |7 ]2 w% i5 l: W" I
    FRESULT res;         // FatFs function common result code

( \+ z8 H& [5 W, C- F3 P) M # Y7 c% f% o3 M0 Q2 @! Y: M8 R: H
    //检测磁盘是否插好

8 d! T1 g' Z# M' z; G3 W3 h4 C
    if( disk_detect_OK()==FALSE )

) D# s) J3 R& B* S0 b+ z2 I* Q& N  m
      return;
) k7 A1 N, O+ q) v. R3 P
" z, t8 J- ?( G2 x  i$ Q
    pfs=&fs;//指向
* z) F  v5 y' }
// Register a work area for logical drive 0

, b2 h# p1 T+ ?; h$ x! A
//温馨提示:该函数是文件系统FatFs里的函数,详细说明请查阅本章节最后的附录,可以用Ctrl+F快捷键,弹出搜索框,输入该函数名,找到该函数。以下类似函数均可以这样找到详细说明,不再赘述。该类函数我们会标记红色,并加粗,请留意。比如f_mount, 解释如下:
  i$ L5 s$ _! M% H9 U7 M

$ z  s  \- W& c
2 q3 c- V) ?5 h
f_mount(0, &fs);
$ F7 Q% y- }8 E; [* w. E1 |

* g0 n3 X) J. ]- F+ b3 R3 o
// 获取空闲簇Get free clusters ,空闲簇的值存在clust
: U( z2 V9 d# A/ F, C
    res = f_getfree("/", &clust, &pfs);//必须是根目录,默认磁盘0

. ]" j" J% G+ A" l- ^4 F% X% D' h2 _/ ?* d
    if ( res==FR_OK )
) ]2 D# ?8 v/ o
    {
& d9 W6 A" r& @# T& H" v+ \
        // Get free space 这里是打印显示出 SD卡总的空间大小以及剩余空间大小
  L& ?- R2 E$ ^* `$ P
              //计算方法:

8 K5 S. h1 h4 j5 u$ q: Q
//   总空间大小   最大簇数×每簇的扇区数÷2÷1024

7 k- F8 L" |8 q2 q3 u5 {9 i
//  剩余空间大小  空闲簇数×每簇的扇区数÷2÷1024

. i8 k5 u' R( L
        printp("\r\n%d MB total disk space.\r\n%d MB available on the disk.\r\n",
# l2 |, E' D, v$ @7 ^
        (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,

, E. B9 X4 s! N) [* x
        clust * pfs->csize /2/1024);

2 E  {+ [, t. R$ F" w1 e3 h
    }
4 p* Q2 T  e6 i( S9 [; Q
    else

* \* u, S9 P7 }4 ]' A" x
      die(res);//测试函数执行结果分析

( e4 }* r5 P* q& Q2 O3 i   X/ Q+ f* V. o& n6 n* c
    // Unregister a work area before discard it
( i: A) `( e& N7 j' p
    f_mount(0, NULL);
" B0 c( ^1 }6 P/ W3 _" |
}
* U# f6 r+ v, K  K( R+ q% V

$ D6 E# G5 x/ ^8 c, }" r5 s
4 Y. D7 t; a) z, i; ~5 j2 O) S2 i 8 v3 M* V, U1 ~2 D! |4 o' x
//1  读取目录 The f_readdir function reads directory entries.
* f; A7 }" ^# i' o! q* {
void Test_f_readdir(void)

1 O: u" q* T( C: ?# ]5 g% m, |
{
; z6 D4 k1 T) @
    FATFS fs;        // Work area (file system object) for logical drive
, y! z4 V1 x7 S  h) ?; D
    char path[20];

0 h' ^( d8 s" y  h' w 9 d. W$ V3 G5 j& ?+ L- w. o& `/ Q
    //检测磁盘是否插好
( O) C9 }' C  l1 j: [6 B
    if( disk_detect_OK()==FALSE )
/ N/ W1 m$ _' z) z' N
      return;

+ C5 T$ T; D( n  K
5 Y* s) F1 @& a! q) f0 y6 d
    f_mount(0, &fs); // Register a work area for logical drive 0
8 ?+ F- z4 T7 M; @" D5 @5 p6 h

( \$ \% m3 R1 H6 B/ {% M
    printp("\r\nread directory:>/");//默认输出主目录下的文件

7 [- v# x( d. n5 G ; _( i4 H7 O2 }2 O& w! B) @8 y" a' v
    USART_Scanf_Name(path);//通过串口输入路径名
. q2 a; W; A: [3 D$ q
( j. Q( q! }( X; A
    //扫描当前路径下子文件夹,并输出到串口
9 H7 g7 X) @. d' }' y. w
    scan_current_folder(path);      

+ z( Q( Y0 b6 ?/ l0 ~8 }% {" `1 ]
    //扫描当前路径下文件,并输出到串口
2 A( Z8 l. A3 }$ D1 l% M, W
    scan_current_files(path);

# H- k( \0 i$ B0 c ! E' @6 g1 L, S! C( T! K
    f_mount(0, NULL);// Unregister a work area before discard it         
- S+ ^: J/ B- s$ C
}
; f- c0 X% x! u7 ]& c
" U* y- T9 ^  b: F1 q
. b- K; J5 l3 D: u* f1 m) X& O

, w  Z" }/ z4 e
//2  读取目录  The f_mkdir function creates a new directory
3 N/ h" j9 z. P( @
void Test_f_mkdir(void)

9 q+ ?' Q* h5 ?, o
{
  ]* t4 a) t$ j$ {1 a9 Q+ a, D. U( j. |
    FATFS fs;       // Work area (file system object) for logical drive

: C6 E: {' u: D
    FRESULT res;     // FatFs function common result code
& R* D$ Y7 l6 w" E& B
    char path[20];

1 H" J: D9 Y) P& |
    //检测磁盘是否插好

' Z/ L" h- P  F
    if( disk_detect_OK()==FALSE )
* S; M6 C3 G! F* R
      return;

; I* d5 w6 d9 c# O
    f_mount(0, &fs); // Register a work area for logical drive 0

7 Z9 j1 Q9 S" k
    printp("\r\nmake directory:>");
8 H( B7 N. ~) P; y4 g7 {3 s, W# p
    USART_Scanf_Name(path);//通过串口输入路径名
1 c, o) f, o$ h
    res = f_mkdir(path);
+ g. Z; z& }0 N0 a9 x- r
    die(res);//测试函数执行结果分析

; I$ J$ d; z8 y. @# V; U& V
    f_mount(0, NULL);// Unregister a work area before discard it

) |4 V) }* t6 o, o
}

- e% G8 E( Z/ Q4 Y/ E/ s- G! I# z5 b

+ q9 n$ W2 ~% @1 x1 s% j" n
//3   读文件 The f_read function reads data from a file.
& c/ m* B, }" X7 G: D, t6 W
void Test_f_read(void)
( I3 T, r0 j" L0 X5 E
{
( a9 L" v) C2 z( N; i
    //用来记录读文件起始时间、结束时间
/ A0 _6 u3 c- \5 }4 P5 j; K, h+ o6 Q
    struct tm time_start,time_end ;
+ t# n3 z& O( q& A
    //用来记录读文件起始时间、结束时间 ,unix时间格式,用来记录时间差。

" P/ W( A4 q( J- n
    time_t unix_start,unix_end,interval;
( C4 H5 r- \- X9 h8 B( x- v
    char path[20];
6 |" U. ]( f0 m7 {( x' ~
    //检测磁盘是否插好
" A  O' n4 y6 Y( \! X9 T# ~9 f
    if( disk_detect_OK()==FALSE )

; s; m0 ~& U" I7 b
      return;

* [! H2 X5 b6 e5 l+ v! q3 ~1 N
    //printp("\r\nread filebbbb:>");
+ `7 n) U' J( F* q, C0 I% C
    // Register a work area for logical drive 0
0 e( e( d2 ]5 V
    f_mount(0, &fs);
0 t1 V! {/ l0 c3 w) {8 A6 t6 @

' h. ~3 x" T. {' J* x" G2 z
    printp("\r\nread file:>");

& p7 ^, u- f: `9 s! T
    USART_Scanf_Name(path);//通过串口输入文件路径名
! _- e; `4 H: a. j6 ~
    //Open source file
$ c* S( R. L2 Z) q7 c# B4 @2 W' h
    res = f_open(&fsrc, path, FA_OPEN_EXISTING | FA_READ);

2 E$ r- f3 i7 K: {8 y) B- Q
    die(res);
- r5 i3 V& {/ A: j0 n: _
    //buffer空间设大一点,会提高读的速度。

. u8 F' w* t2 }- l
    //如果文件实际大小512byte,
- h% ?, ]  C% k0 [% ~
    //设为buffer[512]时,只需要循坏一次,如果设为buffer[1],需要循坏512次。

' P4 S# c* B. F  Y6 M# v
    //下面两行主要是去除1s误差。

3 ?% f* C4 t7 S! \. ]  i& L
    //Read_File_Flag = 0;
4 ^, R  g! ^2 f
    //while( Read_File_Flag==0 );

, v7 A/ j( U4 B/ X- i
0 |+ u2 O" U, L5 j# j& N/ l: Y
    //time_start=Time_GetCalendarTime();//记录开始读时间
5 x/ Z1 [. Q( G
    //unix_start=Time_ConvCalendarToUnix(time_start);
( a0 C+ ~/ w) h( x& \
* d* h8 r- V0 X3 E1 @& ]* A' y
. o7 K) \' r$ k8 I6 w4 O% V; z! }
    //输出提示..
: D+ S2 i- y. \
    if( res==FR_OK )
5 Q: F" q3 j, W, E- }) ^
      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);

% ~$ v, o# j( H! c8 l7 V5 \8 q# D. V
    for (;;)

: T% [1 {$ o# g% T. [3 j! z  S
    {
; ?1 a( U6 `$ j
        //清除缓存
1 h( V3 A6 U3 P/ K
<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:599 l  {7 p# k3 C/ u$ _
 SD卡读写数据,FatFS文件系统 源码

% G; R8 h4 G7 t' {8 `# m, K6 T求助一个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
学习了~~~
" o" a4 G  I  y" |# r7 x
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 手机版