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

【HAL库每天一例】第045例:SDIO-FatFS文件系统功能使用

[复制链接]
haohao663 发布时间:2016-6-19 11:27
【HAL库每天一例】系列例程从今天开始持续更新。。。。。8 M2 e* i* t8 m( k
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
  B. [+ c( X) [' ?9 c7 X0 j* a该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。# d1 N* `9 }# b0 A' P
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
' v$ @# j/ l. u例程下载:8 K3 p" ~, O8 _4 U
资料包括程序、相关说明资料以及软件使用截图' o" y& d/ X9 T& x" }* p
链接:https://pan.baidu.com/s/1i574oPv 1 b/ b8 b+ ]  O# ?' ]5 _
密码:r3s3/ G7 Y) o1 l4 m4 L- V( r
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-045. SDIO-FatFS文件系统功能使用
* |; H1 G/ X* M- N
/**
9 t- r1 F* t4 S0 U  ******************************************************************************
) W% A. n, `: T7 E" q6 L$ I' I  *                           硬石YS-F1Pro开发板例程功能说明
) V7 q$ e! s7 h1 p+ h( w/ G) s, j) R  *
2 e8 x7 w' F* ^+ B  *  例程名称: YSF1_HAL-045. SDIO-FatFS文件系统功能使用
( `5 G7 S) p7 D5 g+ a6 Q% u  *   
+ N0 a0 j. P* o4 ^  ******************************************************************************
" s# p2 ^0 ]( B1 K9 H( m6 J$ X. J& c5 m  * 说明:! @8 l" K- `( D- F+ _3 D
  * 本例程配套硬石stm32开发板YS-F1Pro使用。0 q* T5 e/ ~( c% N4 l# H
  * 5 v! e( d" ^2 t% U' C; q
  * 淘宝:
- t; E0 P' b# |5 M% V" E8 S  * 论坛:www ingbbs com
& O( O( W5 X( A1 Z. {% i  * 版权归硬石嵌入式开发团队所有,请勿商用。
4 o7 w) T3 F( Y4 l! U  ******************************************************************************
. s/ G, l' b, J7 r  Z: Q  */  w* s# y( ^% |6 t& y
! p, k' L! D% k0 T, q0 o% U
【1】例程简介
9 O  x! W, I* w  _; A  SDIO是安全输入输出接口,采用在SD卡上。SD卡做为一种性价比极高的存储介质,在生活中非常9 M. J- }' D! }; |1 q
普遍可见。
: B/ a# h! a% P5 F  上个例程是直接对SD卡进行读写操作,一般使用SD卡都需要通过文件系统,使得类似电脑操作文件, Z  p  Z( l& i! }+ k" [
一样简单明了。; n7 V0 n" N6 P9 M) S- J9 e
  FatFS是一个专门为嵌入式开发的开源小型文件系统。提供了非常丰富的文件操作函数,本例程使用
6 r- t. y% K" J$ n# ?+ N9 @其中部分函数实现文件操作。
) l- |1 W) M/ H3 V  9 p( o1 i0 s* R: a. ?1 A! m1 q! J
【2】跳线帽情况
1 ~7 h+ F% P6 H& x3 h******* 为保证例程正常运行,必须插入以下跳线帽 **********& p- e, @; U4 c9 P* Q5 {
丝印编号     IO端口      目标功能引脚        出厂默认设置) x% |2 z, I& F) {* D
  JP1        PA10        TXD(CH340G)          已接入! P! D) L1 x4 b) C6 g4 ^# `9 [
  JP2        PA9         RXD(CH340G)          已接入" o5 ?* [6 S! |+ O8 _
  
) o  X0 B  v0 o+ R+ n【3】操作及现象% v6 {3 X& R3 o0 c# ^! g" i
  将一张小于32G大小的Micro SD卡插入到开发板上的SD卡槽内,使用开发板配套的MINI USB线连
  ?7 j! y" i- d+ J: O$ W接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱动),在电脑端打开串口调试助手
% _0 E6 o+ |; Y4 L8 |工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试助手窗口可接收到信息。6 z/ `/ w$ v) S; b) b6 A3 K

. @" q0 J" f  _( }/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
9 k1 N* n- J/ W, e6 o' {0 a( g1 [7 ~  h3 P* }

! a2 W# ~" M' R( c, i. Xmain.c文件内容
  1. /**
    . p5 S6 B, L& z0 U* y+ t0 I6 \
  2.   ******************************************************************************) [. J# x7 I5 d+ p
  3.   * 文件名程: main.c 0 j0 ]& _) D: q) P
  4.   * 作    者: 硬石嵌入式开发团队  j) E2 F5 C1 ~. v$ o
  5.   * 版    本: V1.0
    5 q& ?" ?: c; q" t1 @: ?
  6.   * 编写日期: 2015-10-04
    ( Q6 K3 @4 y" T( S+ o) y( Y
  7.   * 功    能: 基于SD卡的FatFS文件系统功能测试
    : y6 y) y8 y! {/ n2 ^" T# h
  8.   ******************************************************************************0 B% C3 u3 z  u  x' M' N8 {+ a, F! M
  9.   * 说明:
    % R" b2 }* l( b4 e; c7 X
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
    3 z' ]0 E. X" A1 j$ N/ @8 B
  11.   *
      |8 t+ I+ F7 s' Z5 f9 ~( m" o7 t/ U
  12.   * 淘宝:' g  k! \9 x* V. p3 [3 M8 l. o
  13.   * 论坛:http://www.ing10bbs.com
      a8 Z$ t. ^8 E6 c, G8 s
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。" }: y9 |# s+ W* }9 R; C/ O
  15.   ******************************************************************************
    ) V/ e/ `9 q2 T- b: l, m
  16.   */5 K; b% j( M& U+ c6 K0 j: t8 m
  17. /* 包含头文件 ----------------------------------------------------------------*/: ^8 t# C4 G3 {) [
  18. #include "stm32f1xx_hal.h"
    " O: G2 f( K: g- A6 P4 Q* k
  19. #include "usart/bsp_debug_usart.h"
    4 j- q4 R  m+ u# g& z% G9 O- p
  20. #include "sdio/bsp_sdcard.h"
    , o) Y) F) k* i2 D% u! f
  21. #include "ff.h"
    2 ?1 ?; {1 q! P0 S
  22. #include "ff_gen_drv.h"
    6 g" s% z! r' x1 E8 ]
  23. #include "drivers\sd_diskio.h"
    - h% U) ^* U( j! S7 L3 |
  24. #include "string.h"/ f# C0 Q# ^6 T

  25. ; h3 j6 n8 T; o4 o! N' b, k7 @
  26. /* 私有类型定义 --------------------------------------------------------------*/# r. c8 g" }2 J% ]! z+ T* _3 M0 B
  27. /* 私有宏定义 ----------------------------------------------------------------*/9 T1 L# F- }/ b4 S
  28. /* 私有变量 ------------------------------------------------------------------*/
    7 @* P# C& Y; F& h# p) y
  29. char SDPath[4];                   /* SD卡逻辑设备路径 */
    7 e8 K7 o# [" C- w
  30. FATFS fs;                                                                                                        /* FatFs文件系统对象 */
    % E2 c  X, U( ?/ U* }9 x* `, \
  31. FIL file;                                                                                                        /* 文件对象 */
    9 ^+ Q" _- _/ F4 V5 {) y# }
  32. FRESULT f_res;                    /* 文件操作结果 */2 {' [/ G0 y2 S3 T
  33. UINT fnum;                                                      /* 文件成功读写数量 *// z/ e; k3 n, b5 O. t, g# {
  34. char fpath[100];                  /* 保存当前扫描路径 */; ]: D( _% o4 n6 w1 y/ o& r
  35. char readbuffer[512];
    * |9 H- v  t5 p2 R3 c6 g

  36. ) d9 r& ~' L4 E3 J- e( X; U
  37. /* 扩展变量 ------------------------------------------------------------------*/
    / E6 w% g, ?3 f$ p8 Q/ i
  38. /* 私有函数原形 --------------------------------------------------------------*/
    * Z! I8 |* [2 X/ }0 Q8 K; h& Z3 J8 c6 C) z8 L
  39. static void printf_fatfs_error(FRESULT fresult);
    6 T; C) X' H" j
  40. static FRESULT miscellaneous(void);1 t, ]. K; k; W& \; O
  41. static FRESULT file_check(void);
    % {1 M; g4 r( b( U* O$ I, A
  42. static FRESULT scan_files (char* path);
    & s7 D) \8 e! T

  43. 6 |4 f  s1 [; w
  44. /* 函数体 --------------------------------------------------------------------*/# m1 T: a+ T: w) t- A# ]
  45. /**" }# P& j+ \4 K
  46.   * 函数功能: 系统时钟配置
    2 u& @( ^6 D% n: R; j
  47.   * 输入参数: 无
    . o+ j! v9 l5 y
  48.   * 返 回 值: 无# @2 G2 ]* ^; s7 Y8 T
  49.   * 说    明: 无
    , L0 [: Q8 C1 u% f- C& s6 t' ~
  50.   */! m) G) y" R( h# w, _
  51. void SystemClock_Config(void)
    2 q) Z- s+ L8 P( h) R
  52. {
    5 |0 K* K  D! T. F: N9 ]3 t2 R# z
  53.   RCC_OscInitTypeDef RCC_OscInitStruct;; [- m# F# f" |0 \# c
  54.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
    , k; M: D# U2 ~/ T0 x$ t

  55. , a' }# {0 `, E& S5 ]: k( s* c
  56.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz4 B/ K* a) T  x$ d; m+ _! ^. `
  57.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    ; X& u+ b8 i+ }# E3 _+ U3 Q
  58.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    2 g( C. A5 _5 M) t
  59.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    * a; `# n7 M- Z& z' q
  60.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;# a6 k% x, t" m/ k1 x; `
  61.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟$ d: A. ]! t1 }* [& ?+ Y
  62.   HAL_RCC_OscConfig(&RCC_OscInitStruct);
    1 t. }$ r8 Y6 m6 }( M# U, M* L
  63. & T, y* y. i' U0 s+ g  M9 g) K( k
  64.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    , y# j, z* Q! J& g
  65.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;2 Q4 E+ k, u+ g  k3 `4 s$ J
  66.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
    + Y. Y% D' S0 E! [. B: B
  67.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟:72MHz
    $ f3 f! U0 L, Y& u4 U" p" m
  68.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;               // APB1时钟:36MHz$ t( ^: K% ]. K* [5 y
  69.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;               // APB2时钟:72MHz/ P  w- n% L4 p) n5 S; z7 j. F* _' A
  70.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);- ^7 z1 J3 k  V" ^/ s$ U) Z: f$ V

  71. ( T4 F8 q" B" h9 v1 _% c
  72.         // HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
    - y" b+ G8 n; v* G3 t
  73.         // HAL_RCC_GetHCLKFreq()/100000         10us中断一次5 v% y% i0 M8 F, O
  74.         // HAL_RCC_GetHCLKFreq()/1000000 1us中断一次  G3 Q; z9 B! A( ^/ e
  75.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器% p- i' b, N* }& S0 L
  76.   /* 系统滴答定时器时钟源 */
    8 S- ^5 K; i# B8 D1 [4 Y- R
  77.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
      h5 \# {2 R/ ]
  78.   /* 系统滴答定时器中断优先级配置 */$ _# a5 M. [& P3 J! [/ g) B
  79.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);7 I3 e, q+ w6 v8 P( t1 _) G+ ^
  80. }$ r6 Y6 A4 Q) @
  81. + }% g" e0 c/ r
  82. /**! w0 }# E* P% I% }1 t2 E; L0 P& f
  83.   * 函数功能: 主函数.
    , c; ]7 B" O5 s5 n  b# K8 `
  84.   * 输入参数: 无
    * @" I, M- C$ J* @- b+ O
  85.   * 返 回 值: 无
    4 _* B1 k6 K+ B1 i# L) F
  86.   * 说    明: 无* u2 {  |- P1 t0 `) {$ J/ o
  87.   */
    2 l0 J( [- i; Z2 }; f" m2 O' A
  88. int main(void)2 y( O/ |) l& P' b
  89. {  
    - z0 X" t: I8 p, G. Q
  90.   /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
    0 K/ ]; B# W2 u0 \+ J( o
  91.   HAL_Init();
    : A  u, g: w! N% r9 q
  92.   /* 配置系统时钟 */
    ' J& @8 ^2 Q+ ^& F
  93.   SystemClock_Config();2 J+ a3 h8 H% D) Z3 P( g

  94. 7 U! @$ o& a3 @4 {- D
  95.   /* 初始化串口并配置串口中断优先级 */
    2 [/ r9 y- W9 o: ~, P0 H
  96.   MX_DEBUG_USART_Init();
    2 r; @5 T+ U7 ]
  97.   printf("****** 这是一个基于SD卡的FatFS文件系统功能使用 ******\n");7 o4 ~1 w. s0 h/ r, L! [4 }
  98.   
    4 e: N" G5 j$ w
  99.   /* 注册一个FatFS设备:SD卡 */
    , C6 o9 b3 `! g) S% P$ p
  100.   if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
    & H! d* I& ^2 k
  101.   {
    ) Z) h. a3 Q$ j& l5 N2 |- g( I
  102.     //在SD卡挂载文件系统,文件系统挂载时会对SD卡初始化
    . ]* V3 z, z' ?6 T( A/ c% g8 b- }
  103.     f_res = f_mount(&fs,(TCHAR const*)SDPath,1);8 Y' G" J1 ?( h" [' o7 \
  104.     printf_fatfs_error(f_res);
    7 Y: y5 J4 K* r
  105.     if(f_res!=FR_OK)
    7 Q. W/ R' P' l  H# s$ i
  106.     {9 b2 D3 }. G  Z
  107.       printf("!!SD卡挂载文件系统失败。\n");8 D" j' I6 D* N7 o  b1 ?
  108.       while(1);
    ) Q( X" x" c& ?" Q) t: }
  109.     }. G: ~: @! R( K0 f; O2 P* v
  110.     else# Y+ H% a4 g7 q3 z: c
  111.     {' p6 D! f. w7 N8 }) C5 o% D$ [
  112.       printf("》SD卡文件系统挂载成功,可以进行测试。\n");   
    . @* u0 `* R0 c* x) }
  113.     }
    2 N% N6 g4 @6 V/ j# B
  114.    
    8 }7 I: y! d3 F! P/ }
  115.     /* FatFs多项功能测试 */
    + Z3 R5 o4 ^- l( a5 ]; j: @
  116.     f_res = miscellaneous();/ p; d* x  k4 |
  117.     ) B6 _2 q( U8 l8 D
  118.     printf("\n*************** 文件信息获取测试 **************\r\n");5 u) z5 H3 H8 k# |+ M1 f( j
  119.     f_res = file_check();
    7 E( n5 ]5 `+ q" P- t, H7 V- U) T3 [

  120. % {  L7 r5 i% C
  121.     8 X& K. d6 J4 L( o5 E
  122.     printf("***************** 文件扫描测试 ****************\r\n");
    0 v; w* k' A! j/ F' U: {
  123.     strcpy(fpath,SDPath);
    6 `* V5 @" i& n5 h" B
  124.     scan_files(fpath);$ m  L: `8 h8 Z: s
  125.     5 \2 f" m/ I5 P5 Q# K
  126.     /* 不再使用,取消挂载 */
    0 P+ r1 M' q) R; W
  127.     f_res = f_mount(NULL,(TCHAR const*)SDPath,1);        3 G" k3 p" w- Q! J
  128.   }  4 T* P# e9 }, ~9 E8 i$ O
  129.   $ N6 `2 r6 M1 `7 S  A
  130.   /* 注销一个FatFS设备:SD卡 */
    - b# _9 H* k( j! O7 H7 ]
  131.   FATFS_UnLinkDriver(SDPath);
    $ }" U$ ?+ l) u' l2 @( y. u
  132.   
    0 i+ c7 S; e! @& k. J$ r
  133.   /* 无限循环 */4 ?/ ^/ ~; O: I
  134.   while (1)8 M% N8 Y& B3 o# `1 ^% n; P% d1 f& J+ p
  135.   {& ^# J# A2 B% U- S, x, P. Z% \# B
  136.   }% |8 S/ K% z( d# c+ z+ l
  137. }: o4 u. D! [, U, n

  138. : S" q* X5 z; {
  139. /**5 b2 J2 V1 ?) z, Z1 A- ~- E
  140.   * 函数功能: FatFS文件系统操作结果信息处理.
    ; h/ G* F! N5 Z% z* W! Z* I
  141.   * 输入参数: FatFS文件系统操作结果:FRESULT
    : X7 }( O& p0 O
  142.   * 返 回 值: 无
    * R6 C& u. o- E: r* p6 ^
  143.   * 说    明: 无, L: R1 C% S: }$ J' v" f
  144.   */
      \& ]4 n6 q/ B, Z# m8 r  C
  145. static void printf_fatfs_error(FRESULT fresult)
    7 _, i2 h0 T( l: ]
  146. {6 L* e6 L5 w  @% S- h
  147.   switch(fresult)
    7 h2 k2 q3 n  N3 \% F& x8 ?3 D# W
  148.   {; @1 R0 s5 f. T& w+ e3 H. N5 `
  149.     case FR_OK:                   //(0)
    . t$ @8 g; O) f9 P+ u( U; g
  150.       printf("》操作成功。\n");$ v% A* ?1 j0 u: i- [  {8 w% C# S' y0 F
  151.     break;; |+ Y1 w% [* r! t2 q! b6 E
  152.     case FR_DISK_ERR:             //(1)
    . `5 P0 Q5 N0 n1 K8 J1 A' j
  153.       printf("!!硬件输入输出驱动出错。\n");
    ; C4 S4 p/ g4 b* i( A- [$ N5 n6 H
  154.     break;
      h1 ^4 Z1 Y. N- P
  155.     case FR_INT_ERR:              //(2)
    - x2 Y; x8 M7 j' ~, g
  156.       printf("!!断言错误。\n");
    8 T& L2 t2 {* B  e: a: Q/ a
  157.     break;( g4 d" _" X3 L5 `2 ~
  158.     case FR_NOT_READY:            //(3)  E. I0 e8 e$ ]  O0 ?/ ~0 y
  159.       printf("!!物理设备无法工作。\n");
    7 l+ u/ A- b2 X' ]/ o
  160.     break;5 X) b/ f) ~' T& s; |
  161.     case FR_NO_FILE:              //(4)
    6 Q+ J4 K* V  J% a
  162.       printf("!!无法找到文件。\n");
    5 m; F' v) p; e$ f
  163.     break;
    8 K9 q0 J/ O' Z: N: d8 }4 U
  164.     case FR_NO_PATH:              //(5)9 a# U6 i# w  H: V5 o
  165.       printf("!!无法找到路径。\n");
    * c8 Z  s! P5 q, X  C5 X: C: e0 J
  166.     break;
    1 t2 S+ U4 p; y, b. [. n
  167.     case FR_INVALID_NAME:         //(6)
    9 S+ |2 x/ F8 h! U: [. ^# u
  168.       printf("!!无效的路径名。\n");" L- N9 o. v5 ]: O: \8 Q
  169.     break;; x. z* o" n2 C5 A/ Z8 m0 F4 j; }( `
  170.     case FR_DENIED:               //(7): N' r( Q' Z/ s& M" n8 }; y' h
  171.     case FR_EXIST:                //(8)
    3 v. G  b1 ?! L  g# G8 u2 k8 D5 \2 f
  172.       printf("!!拒绝访问。\n");
    # l6 z: S; J# |* i- k5 U% R6 _8 q
  173.     break;
    ' _8 ]  i) e3 z; a; I9 S
  174.     case FR_INVALID_OBJECT:       //(9)
    ! z( N$ {; [0 V
  175.       printf("!!无效的文件或路径。\n");: y0 N3 R3 Q: M0 ], O. [
  176.     break;
    ( t# V* P9 S. R: [* i7 P
  177.     case FR_WRITE_PROTECTED:      //(10)
    * K- P& q4 o: E$ y: Y6 Q
  178.       printf("!!逻辑设备写保护。\n");) S" Z4 E' F% @+ O7 F
  179.     break;
    + q% M7 f1 ^5 k: K7 \% v- @. t) c  [0 }
  180.     case FR_INVALID_DRIVE:        //(11)
    ' J! @+ d+ ]* w8 `* w
  181.       printf("!!无效的逻辑设备。\n");
    0 K+ M$ e5 o, b
  182.     break;* \0 T" V# `# z
  183.     case FR_NOT_ENABLED:          //(12). h" I  D9 o' }( {3 d* I6 M
  184.       printf("!!无效的工作区。\n");
    $ T9 \( d, Z6 I/ @4 I* q, e
  185.     break;7 g/ }7 q( p, n& f/ {8 @" m' t$ `
  186.     case FR_NO_FILESYSTEM:        //(13)' }1 {8 A: P' I5 e1 G# K& m. J# v3 r
  187.       printf("!!无效的文件系统。\n");$ I( c- f4 x; o$ [# W
  188.     break;8 I0 h% r) {5 E* I% l
  189.     case FR_MKFS_ABORTED:         //(14)
    $ Q# g' d- M" r; K* \' i5 b
  190.       printf("!!因函数参数问题导致f_mkfs函数操作失败。\n");5 m1 H/ N7 q  C# b' P
  191.     break;
    . I5 }: V/ J/ T2 T3 O: |7 S
  192.     case FR_TIMEOUT:              //(15)3 h  Q) H' u  G1 R
  193.       printf("!!操作超时。\n");
    1 H3 }, e( _0 ^; n
  194.     break;6 F( p4 q+ T+ N2 Y
  195.     case FR_LOCKED:               //(16)9 u! y- e- Z- j5 v+ z+ v
  196.       printf("!!文件被保护。\n");
    0 b' M& O7 ~6 o4 g
  197.     break;. g+ `- ^; A. s3 {
  198.     case FR_NOT_ENOUGH_CORE:      //(17)1 [# N6 h- P0 L- `. b7 a/ {
  199.       printf("!!长文件名支持获取堆空间失败。\n");: z" \' Z- i1 |% Y6 x! ~1 [
  200.     break;  h3 u0 T6 v( y) x& U  d6 c
  201.     case FR_TOO_MANY_OPEN_FILES:  //(18)9 a+ V% R% O* t4 [+ ?$ V3 K6 k
  202.       printf("!!打开太多文件。\n");! P- _  l4 I$ }2 P' U
  203.     break;* K$ Q1 v2 Z; W) Z, p: Y8 X% A) C3 e
  204.     case FR_INVALID_PARAMETER:    // (19)
    $ i6 h5 c8 l6 D3 o6 ?
  205.       printf("!!参数无效。\n");8 b: \6 N) a) K  Z  G& F2 k! T
  206.     break;
    % i! Z' q- f4 t: y
  207.   }4 l! B" ^+ @0 X* B  j
  208. }
    & C3 @; v% B- A& \' N0 b8 j
  209. 5 o: I7 I' B% C! i
  210. /* FatFs多项功能测试 */2 p  ~% t, s5 ?# _7 G. x+ [: d
  211. static FRESULT miscellaneous(void)
    & m' L3 R$ P/ j: t7 U
  212. {& D0 F' B' G6 `, S" E( y/ {' {7 h
  213.   DIR dir;
    % I$ z2 D6 U/ _/ A
  214.   FATFS *pfs;" u! V% M" I- y0 v' ^4 L
  215.   DWORD fre_clust, fre_sect, tot_sect;* V1 E4 i# j+ E
  216.   
    . e, U9 Z1 V3 c5 U: \& y8 `- Y2 D
  217.   printf("\n*************** 设备信息获取 ***************\r\n");/ Y! f' n8 {, A" J& |% ?- H
  218.   /* 获取设备信息和空簇大小 */
    ! U  V/ |. z1 ^
  219.   f_res = f_getfree((TCHAR const*)SDPath, &fre_clust, &pfs);* T& P: s7 f  w! I9 f
  220. ! e. B- T3 e6 M7 S
  221.   /* 计算得到总的扇区个数和空扇区个数 */
    0 T9 t" P1 c. j- Q- {2 y8 t
  222.   tot_sect = (pfs->n_fatent - 2) * pfs->csize;. w+ O6 X( T$ [7 @* b% [: ~; ^
  223.   fre_sect = fre_clust * pfs->csize;
    9 @  X% f+ o" ?/ i# A( `3 c7 ~
  224. & M( s1 R% K2 V1 t" x" R3 e$ ]
  225.   /* 打印信息(4096 字节/扇区) */1 L" J- w& Y1 M+ ?& V
  226.   printf("》设备总空间:%10lu KB。\n》可用空间:  %10lu KB。\n", tot_sect *4, fre_sect *4);
    & B7 e  g8 S- F- s" n5 J' W6 e3 ]
  227.   " U8 S) `! n5 V: P# t$ u" B
  228.   printf("\n******** 文件定位和格式化写入功能测试 ********\r\n");- z* U7 n. f- q  D# `
  229.   f_res = f_open(&file, "FatFs读写测试文件.txt",
    3 B- [4 o9 o% H- u2 F
  230.                             FA_OPEN_EXISTING|FA_WRITE|FA_READ );' M7 ~% V% p) b3 g
  231.         if ( f_res == FR_OK )
    + K. N3 M' Y0 B$ j
  232.         {
    . j$ f( |& S- P: j) o* o' h% q
  233.     /*  文件定位 */
    4 g5 n7 Z' s2 m
  234.     f_res = f_lseek(&file,f_size(&file)-1);' I% L1 e% }2 O2 [, s# B
  235.     if (f_res == FR_OK)
    $ o4 I* U! u  w, n
  236.     {0 N9 l$ J" G' l+ `* F
  237.       /* 格式化写入,参数格式类似printf函数 */
    9 C& V# T% ?6 n# F# N, K  _  ^% S, S
  238.       f_printf(&file,"\n在原来文件新添加一行内容\n");3 u1 o2 q6 P  |# R' C2 N
  239.       f_printf(&file,"》设备总空间:%10lu KB。\n》可用空间:  %10lu KB。\n", tot_sect *4, fre_sect *4);) r& W, }% W3 A2 d0 z
  240.       /*  文件定位到文件起始位置 */, j/ U3 \; y! ^* H! c, U" B; A* a+ d
  241.       f_res = f_lseek(&file,0);5 M# ~9 P; x: ~# f( N: T# `$ N% D
  242.       /* 读取文件所有内容到缓存区 */
    # \1 M0 ]7 _' W
  243.       f_res = f_read(&file,readbuffer,f_size(&file),&fnum);
    . Q) @# O. N5 e) T' ?. V
  244.       if(f_res == FR_OK)! }3 M. [' T9 S! Q. e! i
  245.       {: B6 T4 I0 ^* m! f$ j; N9 d8 n
  246.         printf("》文件内容:\n%s\n",readbuffer);
    ) ^4 U/ h! }( C! q7 _5 ~, z3 i+ W" E
  247.       }" m- d9 @- e6 I) a7 q& Q
  248.     }) o5 J) c# T! O
  249.     f_close(&file);    $ i! a$ m, m1 p$ _
  250.    
    ) z' o) X; \: b1 b4 J
  251.     printf("\n********** 目录创建和重命名功能测试 **********\r\n");
    " P4 h0 q2 |8 s5 k. }$ h
  252.     /* 尝试打开目录 */% @( @4 F5 s! z
  253.     f_res=f_opendir(&dir,"TestDir");
    4 A2 \% a# {6 E8 H' S/ _) r
  254.     if(f_res!=FR_OK)0 V% ^" G) f' R2 U& e/ P
  255.     {5 T  E8 h8 p6 r2 V( T
  256.       /* 打开目录失败,就创建目录 */. e% f$ J6 _4 {6 R; T% l
  257.       f_res=f_mkdir("TestDir");7 h& q% @& Z9 V9 [" _& d+ c4 z
  258.     }) o+ n6 b7 U' l" N: a5 s
  259.     else4 z/ k1 s1 g+ R/ l
  260.     {
    1 y# w* ~8 o* t3 n. {2 z/ e
  261.       /* 如果目录已经存在,关闭它 */( z$ u+ g! ~- k" j
  262.       f_res=f_closedir(&dir);
      w8 D0 r( k1 D, U; ~
  263.       /* 删除文件 */* C: G/ v& U( ~- o) h
  264.       f_unlink("TestDir/testdir.txt");
    ( I9 m- y: i: H8 \) _* y9 n2 A3 e
  265.     }
    - g0 ]7 p$ ^2 {8 p' r3 p0 u
  266.     if(f_res==FR_OK)
    1 ?% c0 F1 c' ]7 ^5 \$ D
  267.     {$ b$ {7 Q' `# b* u) P
  268.       /* 重命名并移动文件 */
    & y1 x- ?2 M/ B+ C
  269.       f_res=f_rename("FatFs读写测试文件.txt","TestDir/testdir.txt");      7 ?; u  t2 a, h+ T9 [6 j" Q# I8 o
  270.     }
    & p; x* B, t2 q  \8 \4 o; @! l
  271.         }( e  k' H- O: Y; H6 v" F
  272.   else
    $ z" x+ Y2 ?! {, F; y5 [
  273.   {
    # ?  b  q3 q2 p
  274.     printf("!! 打开文件失败:%d\n",f_res);
    & G: D8 A, l9 \$ o2 p3 [5 W
  275.     printf("!! 或许需要再次运行“FatFs移植与读写测试”工程\n");
    : |' O2 ~8 h1 ?, Q3 ^) ?8 y
  276.   }
    , r7 c+ p- l% w1 P
  277.   return f_res;
    & k: d  M0 B3 l3 s
  278. }5 T% U, Z9 {* f0 X8 E4 n) F7 x0 h, J
  279. / ^3 d# ]6 ^& N8 U! F

  280. $ a3 v1 ]. |: ]2 ^; B
  281. /**
    3 L& E, ^* e( _% W8 J9 U
  282.   * 文件信息获取3 D0 S" e( t; M! ]/ i- D
  283.   */
    9 i0 I. y5 s$ T, Q( B5 N6 F/ j
  284. static FRESULT file_check(void)6 u! i* Z) i( u" n
  285. {  
    6 O2 b# g* i- G8 `" m
  286.   static FILINFO finfo;7 \- H7 j+ d  d' }+ u8 I! Q! }
  287.   /* 获取文件信息 */, _4 f/ I% ]; j. q
  288.   f_res=f_stat("0:TestDir/testdir.txt",&finfo);
    : |7 j- z& f2 {0 u" x$ q
  289.   if(f_res==FR_OK): a) ?* z, k4 p3 e' M
  290.   {6 P: h- B' S( l' z8 S( H( `
  291.     printf("“testdir.txt”文件信息:\n");  i$ m$ X3 \5 v+ u3 D
  292.     printf("》文件大小: %ld(字节)\n", finfo.fsize);) l9 V( |. T7 S7 ~$ t
  293.     printf("》时间戳: %u/%02u/%02u, %02u:%02u\n",
    5 o5 y8 _1 x- I8 P  u4 s
  294.            (finfo.fdate >> 9) + 1980, finfo.fdate >> 5 & 15, finfo.fdate & 31,finfo.ftime >> 11, finfo.ftime >> 5 & 63);
    % Y" d1 F' L2 h0 T+ g- b7 ^
  295.     printf("》属性: %c%c%c%c%c\n\n",
    + P4 Y6 W+ i4 P
  296.            (finfo.fattrib & AM_DIR) ? 'D' : '-',      // 是一个目录0 \) c) y# s0 h
  297.            (finfo.fattrib & AM_RDO) ? 'R' : '-',      // 只读文件. v" O  v) b& H" W$ W' }* k( }
  298.            (finfo.fattrib & AM_HID) ? 'H' : '-',      // 隐藏文件
    ( e( j) C6 [7 S/ p& L
  299.            (finfo.fattrib & AM_SYS) ? 'S' : '-',      // 系统文件' R$ O7 l" s1 j/ p- T8 m' S% _
  300.            (finfo.fattrib & AM_ARC) ? 'A' : '-');     // 档案文件! d* {+ s; c  v; P. x( `
  301.   }; W" O7 Y8 {# V" A9 s" I
  302.   return f_res;" r/ m; J1 `1 Q
  303. }" V# P% {1 [' ?* `/ h
  304. - j& W) g9 _" K1 q/ N% z( l
  305. /**
    , C! ]* o3 q& i/ o
  306.   * @brief  scan_files 递归扫描FatFs内的文件5 ]1 X( a( U6 B
  307.   * @param  path:初始扫描路径) d  |7 S( [6 v1 c* U3 p; \
  308.   * @retval result:文件系统的返回值
    6 P9 @5 M7 U4 V( K: c* F
  309.   */
    + G3 V6 Q- b7 F8 n6 L5 I
  310. static FRESULT scan_files (char* path)
    $ U( s6 P9 F9 J2 T) [# u
  311. { " K3 a( Z2 W9 @1 q8 S8 e
  312.   FRESULT res;                 //部分在递归过程被修改的变量,不用全局变量       
    $ |* h3 ~0 \6 l1 {5 S
  313.   FILINFO fno; $ o# H5 Z+ v. i9 M
  314.   DIR dir;
    1 a6 A. V( n$ C9 T* e
  315.   int i;            
    9 E+ c- I  |; Z. A- {
  316.   char *fn;        // 文件名       
    # v. [; A* I! l) H# s% P
  317.         9 q2 q. [6 l+ W0 W  _& A
  318. #if _USE_LFN
    / R+ I  G5 x0 H4 U9 f
  319.   /* 长文件名支持 */- J$ Q. j& M# i. v3 C6 d) }
  320.   /* 简体中文需要2个字节保存一个“字”*/
      X0 T9 Y3 |0 N; W) _
  321.   static char lfn[_MAX_LFN*2 + 1];         7 B, u* s% p% a% S- e/ w2 `) T9 T
  322.   fno.lfname = lfn; 9 T" y% y- k2 q% Z
  323.   fno.lfsize = sizeof(lfn);
    : Q* U& E. o2 D0 U) A. J# l
  324. #endif
    3 {1 D& \5 f; J4 \/ I
  325.   //打开目录
    6 |% U4 P  H' ]) [( ^! R+ e
  326.   res = f_opendir(&dir, path);
    3 q9 u: U9 J  l4 V1 _. ]/ J& t
  327.   if (res == FR_OK) - H. M( j. y9 a/ j% e7 Z; K7 _/ \+ w+ L4 ~
  328.         {
    8 z0 |2 U4 ]; S& w8 k, c% P1 ~
  329.     i = strlen(path);
    , h8 e# K, N3 E; s$ {0 p
  330.     for (;;)
    / k  k1 ]' Q5 j4 I  ~& F. e
  331.                 {
    6 e4 `, x. G3 Y" a) y" t
  332.       //读取目录下的内容,再读会自动读下一个文件, [/ `1 M+ @/ o$ N' g
  333.       res = f_readdir(&dir, &fno);                                                                 $ O8 w4 X- `7 \, r  O
  334.       //为空时表示所有项目读取完毕,跳出
    4 T6 l( Q( i5 |
  335.       if (res != FR_OK || fno.fname[0] == 0) break;         / m5 y5 i. l; F8 W1 T! C
  336. #if _USE_LFN & c2 E; t  ]; H8 x6 ?
  337.       fn = *fno.lfname ? fno.lfname : fno.fname;
    % V" X. {, ]5 ~) A5 e8 C
  338. #else 9 P' P: |" G% P' J) q# H) y
  339.       fn = fno.fname;
    & y' Z' W# U5 I. U
  340. #endif
    4 G- ]1 R4 `6 r
  341.       //点表示当前目录,跳过                       
    2 s* e- k0 F$ R, E( W; s! a0 ~( V
  342.       if (*fn == '.') continue;         , u0 ]! w" S2 U* ?
  343.       //目录,递归读取      
    ! p4 c. t% ?: y, w
  344.       if (fno.fattrib & AM_DIR)         ; u5 k" e2 |7 I4 K( y
  345.                         {                         ' A7 g7 Q7 c. C) d, d* P2 `" Z2 [
  346.         //合成完整目录名        6 v# t- k# U$ t1 l4 k
  347.         sprintf(&path[i], "/%s", fn);                
    ) r% i+ J9 X0 \1 _1 l# I0 D
  348.         //递归遍历         
    6 c6 y) V( P% C* M. F  g
  349.         res = scan_files(path);        ! `, \7 M( |) P% k+ g
  350.         path[i] = 0;         9 k  K6 h9 W& B# J3 n, m: @5 i# F
  351.         //打开失败,跳出循环        
    . _/ r4 Y# U' W& U5 P! ~
  352.         if (res != FR_OK)
    2 L' U" G  O# u2 l
  353.                                         break;
    - \# i2 l" x1 i1 R$ `9 M3 ]5 E
  354.       }
    5 Z, U* A3 i. [! Q! \. P0 @  t1 d
  355.                         else " Z/ F/ Z& A. C( M$ l% c# m
  356.                         { 2 V  {% \. [; s  N" S( O/ y
  357.                                 printf("%s/%s\n", path, fn);                                                                //输出文件名       
    2 A* H1 j7 d) C: [
  358.         /* 可以在这里提取特定格式的文件路径 */        # b$ Q; u3 X/ V" _3 }
  359.       }//else; a) R0 n+ A+ |* g0 W+ \# d; l
  360.     } //for
    9 z1 l; l5 G9 {0 G$ [& `* H
  361.   }
    2 \% b- F. D, ]9 p
  362.   return res; " T- [3 m- W! I
  363. }
    5 ^' ]. L- l, s; x- O
  364. - Q. g. R$ e) {" ]
  365. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/' a! u( m& x" O6 l7 Y$ I4 o
复制代码
串口调试助手截图.jpg
, E5 L( j; l2 f3 _# C/ W# ^
1 g: f( g) D! s$ o* s$ R
, P; l/ u' {: \) Z5 i( |) ~! ^

3 ?5 [1 |3 g  U8 @  @+ @& B
1 收藏 评论2 发布时间:2016-6-19 11:27

举报

2个回答
Ian-392967 回答时间:2016-7-1 22:40:53
多谢分享
asdfasfasfasfas 回答时间:2021-2-8 12:55:28
网盘失效了, 能再发一次吗

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版