【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文件内容- /**
. p5 S6 B, L& z0 U* y+ t0 I6 \ - ******************************************************************************) [. J# x7 I5 d+ p
- * 文件名程: main.c 0 j0 ]& _) D: q) P
- * 作 者: 硬石嵌入式开发团队 j) E2 F5 C1 ~. v$ o
- * 版 本: V1.0
5 q& ?" ?: c; q" t1 @: ? - * 编写日期: 2015-10-04
( Q6 K3 @4 y" T( S+ o) y( Y - * 功 能: 基于SD卡的FatFS文件系统功能测试
: y6 y) y8 y! {/ n2 ^" T# h - ******************************************************************************0 B% C3 u3 z u x' M' N8 {+ a, F! M
- * 说明:
% R" b2 }* l( b4 e; c7 X - * 本例程配套硬石stm32开发板YS-F1Pro使用。
3 z' ]0 E. X" A1 j$ N/ @8 B - *
|8 t+ I+ F7 s' Z5 f9 ~( m" o7 t/ U - * 淘宝:' g k! \9 x* V. p3 [3 M8 l. o
- * 论坛:http://www.ing10bbs.com
a8 Z$ t. ^8 E6 c, G8 s - * 版权归硬石嵌入式开发团队所有,请勿商用。" }: y9 |# s+ W* }9 R; C/ O
- ******************************************************************************
) V/ e/ `9 q2 T- b: l, m - */5 K; b% j( M& U+ c6 K0 j: t8 m
- /* 包含头文件 ----------------------------------------------------------------*/: ^8 t# C4 G3 {) [
- #include "stm32f1xx_hal.h"
" O: G2 f( K: g- A6 P4 Q* k - #include "usart/bsp_debug_usart.h"
4 j- q4 R m+ u# g& z% G9 O- p - #include "sdio/bsp_sdcard.h"
, o) Y) F) k* i2 D% u! f - #include "ff.h"
2 ?1 ?; {1 q! P0 S - #include "ff_gen_drv.h"
6 g" s% z! r' x1 E8 ] - #include "drivers\sd_diskio.h"
- h% U) ^* U( j! S7 L3 | - #include "string.h"/ f# C0 Q# ^6 T
; h3 j6 n8 T; o4 o! N' b, k7 @- /* 私有类型定义 --------------------------------------------------------------*/# r. c8 g" }2 J% ]! z+ T* _3 M0 B
- /* 私有宏定义 ----------------------------------------------------------------*/9 T1 L# F- }/ b4 S
- /* 私有变量 ------------------------------------------------------------------*/
7 @* P# C& Y; F& h# p) y - char SDPath[4]; /* SD卡逻辑设备路径 */
7 e8 K7 o# [" C- w - FATFS fs; /* FatFs文件系统对象 */
% E2 c X, U( ?/ U* }9 x* `, \ - FIL file; /* 文件对象 */
9 ^+ Q" _- _/ F4 V5 {) y# } - FRESULT f_res; /* 文件操作结果 */2 {' [/ G0 y2 S3 T
- UINT fnum; /* 文件成功读写数量 *// z/ e; k3 n, b5 O. t, g# {
- char fpath[100]; /* 保存当前扫描路径 */; ]: D( _% o4 n6 w1 y/ o& r
- char readbuffer[512];
* |9 H- v t5 p2 R3 c6 g
) d9 r& ~' L4 E3 J- e( X; U- /* 扩展变量 ------------------------------------------------------------------*/
/ E6 w% g, ?3 f$ p8 Q/ i - /* 私有函数原形 --------------------------------------------------------------*/
* Z! I8 |* [2 X/ }0 Q8 K; h& Z3 J8 c6 C) z8 L - static void printf_fatfs_error(FRESULT fresult);
6 T; C) X' H" j - static FRESULT miscellaneous(void);1 t, ]. K; k; W& \; O
- static FRESULT file_check(void);
% {1 M; g4 r( b( U* O$ I, A - static FRESULT scan_files (char* path);
& s7 D) \8 e! T
6 |4 f s1 [; w- /* 函数体 --------------------------------------------------------------------*/# m1 T: a+ T: w) t- A# ]
- /**" }# P& j+ \4 K
- * 函数功能: 系统时钟配置
2 u& @( ^6 D% n: R; j - * 输入参数: 无
. o+ j! v9 l5 y - * 返 回 值: 无# @2 G2 ]* ^; s7 Y8 T
- * 说 明: 无
, L0 [: Q8 C1 u% f- C& s6 t' ~ - */! m) G) y" R( h# w, _
- void SystemClock_Config(void)
2 q) Z- s+ L8 P( h) R - {
5 |0 K* K D! T. F: N9 ]3 t2 R# z - RCC_OscInitTypeDef RCC_OscInitStruct;; [- m# F# f" |0 \# c
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
, k; M: D# U2 ~/ T0 x$ t
, a' }# {0 `, E& S5 ]: k( s* c- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz4 B/ K* a) T x$ d; m+ _! ^. `
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
; X& u+ b8 i+ }# E3 _+ U3 Q - RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
2 g( C. A5 _5 M) t - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
* a; `# n7 M- Z& z' q - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;# a6 k% x, t" m/ k1 x; `
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 9倍频,得到72MHz主时钟$ d: A. ]! t1 }* [& ?+ Y
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
1 t. }$ r8 Y6 m6 }( M# U, M* L - & T, y* y. i' U0 s+ g M9 g) K( k
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
, y# j, z* Q! J& g - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;2 Q4 E+ k, u+ g k3 `4 s$ J
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:72MHz
+ Y. Y% D' S0 E! [. B: B - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟:72MHz
$ f3 f! U0 L, Y& u4 U" p" m - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1时钟:36MHz$ t( ^: K% ]. K* [5 y
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2时钟:72MHz/ P w- n% L4 p) n5 S; z7 j. F* _' A
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);- ^7 z1 J3 k V" ^/ s$ U) Z: f$ V
( T4 F8 q" B" h9 v1 _% c- // HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
- y" b+ G8 n; v* G3 t - // HAL_RCC_GetHCLKFreq()/100000 10us中断一次5 v% y% i0 M8 F, O
- // HAL_RCC_GetHCLKFreq()/1000000 1us中断一次 G3 Q; z9 B! A( ^/ e
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器% p- i' b, N* }& S0 L
- /* 系统滴答定时器时钟源 */
8 S- ^5 K; i# B8 D1 [4 Y- R - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
h5 \# {2 R/ ] - /* 系统滴答定时器中断优先级配置 */$ _# a5 M. [& P3 J! [/ g) B
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);7 I3 e, q+ w6 v8 P( t1 _) G+ ^
- }$ r6 Y6 A4 Q) @
- + }% g" e0 c/ r
- /**! w0 }# E* P% I% }1 t2 E; L0 P& f
- * 函数功能: 主函数.
, c; ]7 B" O5 s5 n b# K8 ` - * 输入参数: 无
* @" I, M- C$ J* @- b+ O - * 返 回 值: 无
4 _* B1 k6 K+ B1 i# L) F - * 说 明: 无* u2 { |- P1 t0 `) {$ J/ o
- */
2 l0 J( [- i; Z2 }; f" m2 O' A - int main(void)2 y( O/ |) l& P' b
- {
- z0 X" t: I8 p, G. Q - /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
0 K/ ]; B# W2 u0 \+ J( o - HAL_Init();
: A u, g: w! N% r9 q - /* 配置系统时钟 */
' J& @8 ^2 Q+ ^& F - SystemClock_Config();2 J+ a3 h8 H% D) Z3 P( g
7 U! @$ o& a3 @4 {- D- /* 初始化串口并配置串口中断优先级 */
2 [/ r9 y- W9 o: ~, P0 H - MX_DEBUG_USART_Init();
2 r; @5 T+ U7 ] - printf("****** 这是一个基于SD卡的FatFS文件系统功能使用 ******\n");7 o4 ~1 w. s0 h/ r, L! [4 }
-
4 e: N" G5 j$ w - /* 注册一个FatFS设备:SD卡 */
, C6 o9 b3 `! g) S% P$ p - if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
& H! d* I& ^2 k - {
) Z) h. a3 Q$ j& l5 N2 |- g( I - //在SD卡挂载文件系统,文件系统挂载时会对SD卡初始化
. ]* V3 z, z' ?6 T( A/ c% g8 b- } - f_res = f_mount(&fs,(TCHAR const*)SDPath,1);8 Y' G" J1 ?( h" [' o7 \
- printf_fatfs_error(f_res);
7 Y: y5 J4 K* r - if(f_res!=FR_OK)
7 Q. W/ R' P' l H# s$ i - {9 b2 D3 }. G Z
- printf("!!SD卡挂载文件系统失败。\n");8 D" j' I6 D* N7 o b1 ?
- while(1);
) Q( X" x" c& ?" Q) t: } - }. G: ~: @! R( K0 f; O2 P* v
- else# Y+ H% a4 g7 q3 z: c
- {' p6 D! f. w7 N8 }) C5 o% D$ [
- printf("》SD卡文件系统挂载成功,可以进行测试。\n");
. @* u0 `* R0 c* x) } - }
2 N% N6 g4 @6 V/ j# B -
8 }7 I: y! d3 F! P/ } - /* FatFs多项功能测试 */
+ Z3 R5 o4 ^- l( a5 ]; j: @ - f_res = miscellaneous();/ p; d* x k4 |
- ) B6 _2 q( U8 l8 D
- printf("\n*************** 文件信息获取测试 **************\r\n");5 u) z5 H3 H8 k# |+ M1 f( j
- f_res = file_check();
7 E( n5 ]5 `+ q" P- t, H7 V- U) T3 [
% { L7 r5 i% C- 8 X& K. d6 J4 L( o5 E
- printf("***************** 文件扫描测试 ****************\r\n");
0 v; w* k' A! j/ F' U: { - strcpy(fpath,SDPath);
6 `* V5 @" i& n5 h" B - scan_files(fpath);$ m L: `8 h8 Z: s
- 5 \2 f" m/ I5 P5 Q# K
- /* 不再使用,取消挂载 */
0 P+ r1 M' q) R; W - f_res = f_mount(NULL,(TCHAR const*)SDPath,1); 3 G" k3 p" w- Q! J
- } 4 T* P# e9 }, ~9 E8 i$ O
- $ N6 `2 r6 M1 `7 S A
- /* 注销一个FatFS设备:SD卡 */
- b# _9 H* k( j! O7 H7 ] - FATFS_UnLinkDriver(SDPath);
$ }" U$ ?+ l) u' l2 @( y. u -
0 i+ c7 S; e! @& k. J$ r - /* 无限循环 */4 ?/ ^/ ~; O: I
- while (1)8 M% N8 Y& B3 o# `1 ^% n; P% d1 f& J+ p
- {& ^# J# A2 B% U- S, x, P. Z% \# B
- }% |8 S/ K% z( d# c+ z+ l
- }: o4 u. D! [, U, n
: S" q* X5 z; {- /**5 b2 J2 V1 ?) z, Z1 A- ~- E
- * 函数功能: FatFS文件系统操作结果信息处理.
; h/ G* F! N5 Z% z* W! Z* I - * 输入参数: FatFS文件系统操作结果:FRESULT
: X7 }( O& p0 O - * 返 回 值: 无
* R6 C& u. o- E: r* p6 ^ - * 说 明: 无, L: R1 C% S: }$ J' v" f
- */
\& ]4 n6 q/ B, Z# m8 r C - static void printf_fatfs_error(FRESULT fresult)
7 _, i2 h0 T( l: ] - {6 L* e6 L5 w @% S- h
- switch(fresult)
7 h2 k2 q3 n N3 \% F& x8 ?3 D# W - {; @1 R0 s5 f. T& w+ e3 H. N5 `
- case FR_OK: //(0)
. t$ @8 g; O) f9 P+ u( U; g - printf("》操作成功。\n");$ v% A* ?1 j0 u: i- [ {8 w% C# S' y0 F
- break;; |+ Y1 w% [* r! t2 q! b6 E
- case FR_DISK_ERR: //(1)
. `5 P0 Q5 N0 n1 K8 J1 A' j - printf("!!硬件输入输出驱动出错。\n");
; C4 S4 p/ g4 b* i( A- [$ N5 n6 H - break;
h1 ^4 Z1 Y. N- P - case FR_INT_ERR: //(2)
- x2 Y; x8 M7 j' ~, g - printf("!!断言错误。\n");
8 T& L2 t2 {* B e: a: Q/ a - break;( g4 d" _" X3 L5 `2 ~
- case FR_NOT_READY: //(3) E. I0 e8 e$ ] O0 ?/ ~0 y
- printf("!!物理设备无法工作。\n");
7 l+ u/ A- b2 X' ]/ o - break;5 X) b/ f) ~' T& s; |
- case FR_NO_FILE: //(4)
6 Q+ J4 K* V J% a - printf("!!无法找到文件。\n");
5 m; F' v) p; e$ f - break;
8 K9 q0 J/ O' Z: N: d8 }4 U - case FR_NO_PATH: //(5)9 a# U6 i# w H: V5 o
- printf("!!无法找到路径。\n");
* c8 Z s! P5 q, X C5 X: C: e0 J - break;
1 t2 S+ U4 p; y, b. [. n - case FR_INVALID_NAME: //(6)
9 S+ |2 x/ F8 h! U: [. ^# u - printf("!!无效的路径名。\n");" L- N9 o. v5 ]: O: \8 Q
- break;; x. z* o" n2 C5 A/ Z8 m0 F4 j; }( `
- case FR_DENIED: //(7): N' r( Q' Z/ s& M" n8 }; y' h
- case FR_EXIST: //(8)
3 v. G b1 ?! L g# G8 u2 k8 D5 \2 f - printf("!!拒绝访问。\n");
# l6 z: S; J# |* i- k5 U% R6 _8 q - break;
' _8 ] i) e3 z; a; I9 S - case FR_INVALID_OBJECT: //(9)
! z( N$ {; [0 V - printf("!!无效的文件或路径。\n");: y0 N3 R3 Q: M0 ], O. [
- break;
( t# V* P9 S. R: [* i7 P - case FR_WRITE_PROTECTED: //(10)
* K- P& q4 o: E$ y: Y6 Q - printf("!!逻辑设备写保护。\n");) S" Z4 E' F% @+ O7 F
- break;
+ q% M7 f1 ^5 k: K7 \% v- @. t) c [0 } - case FR_INVALID_DRIVE: //(11)
' J! @+ d+ ]* w8 `* w - printf("!!无效的逻辑设备。\n");
0 K+ M$ e5 o, b - break;* \0 T" V# `# z
- case FR_NOT_ENABLED: //(12). h" I D9 o' }( {3 d* I6 M
- printf("!!无效的工作区。\n");
$ T9 \( d, Z6 I/ @4 I* q, e - break;7 g/ }7 q( p, n& f/ {8 @" m' t$ `
- case FR_NO_FILESYSTEM: //(13)' }1 {8 A: P' I5 e1 G# K& m. J# v3 r
- printf("!!无效的文件系统。\n");$ I( c- f4 x; o$ [# W
- break;8 I0 h% r) {5 E* I% l
- case FR_MKFS_ABORTED: //(14)
$ Q# g' d- M" r; K* \' i5 b - printf("!!因函数参数问题导致f_mkfs函数操作失败。\n");5 m1 H/ N7 q C# b' P
- break;
. I5 }: V/ J/ T2 T3 O: |7 S - case FR_TIMEOUT: //(15)3 h Q) H' u G1 R
- printf("!!操作超时。\n");
1 H3 }, e( _0 ^; n - break;6 F( p4 q+ T+ N2 Y
- case FR_LOCKED: //(16)9 u! y- e- Z- j5 v+ z+ v
- printf("!!文件被保护。\n");
0 b' M& O7 ~6 o4 g - break;. g+ `- ^; A. s3 {
- case FR_NOT_ENOUGH_CORE: //(17)1 [# N6 h- P0 L- `. b7 a/ {
- printf("!!长文件名支持获取堆空间失败。\n");: z" \' Z- i1 |% Y6 x! ~1 [
- break; h3 u0 T6 v( y) x& U d6 c
- case FR_TOO_MANY_OPEN_FILES: //(18)9 a+ V% R% O* t4 [+ ?$ V3 K6 k
- printf("!!打开太多文件。\n");! P- _ l4 I$ }2 P' U
- break;* K$ Q1 v2 Z; W) Z, p: Y8 X% A) C3 e
- case FR_INVALID_PARAMETER: // (19)
$ i6 h5 c8 l6 D3 o6 ? - printf("!!参数无效。\n");8 b: \6 N) a) K Z G& F2 k! T
- break;
% i! Z' q- f4 t: y - }4 l! B" ^+ @0 X* B j
- }
& C3 @; v% B- A& \' N0 b8 j - 5 o: I7 I' B% C! i
- /* FatFs多项功能测试 */2 p ~% t, s5 ?# _7 G. x+ [: d
- static FRESULT miscellaneous(void)
& m' L3 R$ P/ j: t7 U - {& D0 F' B' G6 `, S" E( y/ {' {7 h
- DIR dir;
% I$ z2 D6 U/ _/ A - FATFS *pfs;" u! V% M" I- y0 v' ^4 L
- DWORD fre_clust, fre_sect, tot_sect;* V1 E4 i# j+ E
-
. e, U9 Z1 V3 c5 U: \& y8 `- Y2 D - printf("\n*************** 设备信息获取 ***************\r\n");/ Y! f' n8 {, A" J& |% ?- H
- /* 获取设备信息和空簇大小 */
! U V/ |. z1 ^ - f_res = f_getfree((TCHAR const*)SDPath, &fre_clust, &pfs);* T& P: s7 f w! I9 f
- ! e. B- T3 e6 M7 S
- /* 计算得到总的扇区个数和空扇区个数 */
0 T9 t" P1 c. j- Q- {2 y8 t - tot_sect = (pfs->n_fatent - 2) * pfs->csize;. w+ O6 X( T$ [7 @* b% [: ~; ^
- fre_sect = fre_clust * pfs->csize;
9 @ X% f+ o" ?/ i# A( `3 c7 ~ - & M( s1 R% K2 V1 t" x" R3 e$ ]
- /* 打印信息(4096 字节/扇区) */1 L" J- w& Y1 M+ ?& V
- printf("》设备总空间:%10lu KB。\n》可用空间: %10lu KB。\n", tot_sect *4, fre_sect *4);
& B7 e g8 S- F- s" n5 J' W6 e3 ] - " U8 S) `! n5 V: P# t$ u" B
- printf("\n******** 文件定位和格式化写入功能测试 ********\r\n");- z* U7 n. f- q D# `
- f_res = f_open(&file, "FatFs读写测试文件.txt",
3 B- [4 o9 o% H- u2 F - FA_OPEN_EXISTING|FA_WRITE|FA_READ );' M7 ~% V% p) b3 g
- if ( f_res == FR_OK )
+ K. N3 M' Y0 B$ j - {
. j$ f( |& S- P: j) o* o' h% q - /* 文件定位 */
4 g5 n7 Z' s2 m - f_res = f_lseek(&file,f_size(&file)-1);' I% L1 e% }2 O2 [, s# B
- if (f_res == FR_OK)
$ o4 I* U! u w, n - {0 N9 l$ J" G' l+ `* F
- /* 格式化写入,参数格式类似printf函数 */
9 C& V# T% ?6 n# F# N, K _ ^% S, S - f_printf(&file,"\n在原来文件新添加一行内容\n");3 u1 o2 q6 P |# R' C2 N
- f_printf(&file,"》设备总空间:%10lu KB。\n》可用空间: %10lu KB。\n", tot_sect *4, fre_sect *4);) r& W, }% W3 A2 d0 z
- /* 文件定位到文件起始位置 */, j/ U3 \; y! ^* H! c, U" B; A* a+ d
- f_res = f_lseek(&file,0);5 M# ~9 P; x: ~# f( N: T# `$ N% D
- /* 读取文件所有内容到缓存区 */
# \1 M0 ]7 _' W - f_res = f_read(&file,readbuffer,f_size(&file),&fnum);
. Q) @# O. N5 e) T' ?. V - if(f_res == FR_OK)! }3 M. [' T9 S! Q. e! i
- {: B6 T4 I0 ^* m! f$ j; N9 d8 n
- printf("》文件内容:\n%s\n",readbuffer);
) ^4 U/ h! }( C! q7 _5 ~, z3 i+ W" E - }" m- d9 @- e6 I) a7 q& Q
- }) o5 J) c# T! O
- f_close(&file); $ i! a$ m, m1 p$ _
-
) z' o) X; \: b1 b4 J - printf("\n********** 目录创建和重命名功能测试 **********\r\n");
" P4 h0 q2 |8 s5 k. }$ h - /* 尝试打开目录 */% @( @4 F5 s! z
- f_res=f_opendir(&dir,"TestDir");
4 A2 \% a# {6 E8 H' S/ _) r - if(f_res!=FR_OK)0 V% ^" G) f' R2 U& e/ P
- {5 T E8 h8 p6 r2 V( T
- /* 打开目录失败,就创建目录 */. e% f$ J6 _4 {6 R; T% l
- f_res=f_mkdir("TestDir");7 h& q% @& Z9 V9 [" _& d+ c4 z
- }) o+ n6 b7 U' l" N: a5 s
- else4 z/ k1 s1 g+ R/ l
- {
1 y# w* ~8 o* t3 n. {2 z/ e - /* 如果目录已经存在,关闭它 */( z$ u+ g! ~- k" j
- f_res=f_closedir(&dir);
w8 D0 r( k1 D, U; ~ - /* 删除文件 */* C: G/ v& U( ~- o) h
- f_unlink("TestDir/testdir.txt");
( I9 m- y: i: H8 \) _* y9 n2 A3 e - }
- g0 ]7 p$ ^2 {8 p' r3 p0 u - if(f_res==FR_OK)
1 ?% c0 F1 c' ]7 ^5 \$ D - {$ b$ {7 Q' `# b* u) P
- /* 重命名并移动文件 */
& y1 x- ?2 M/ B+ C - f_res=f_rename("FatFs读写测试文件.txt","TestDir/testdir.txt"); 7 ?; u t2 a, h+ T9 [6 j" Q# I8 o
- }
& p; x* B, t2 q \8 \4 o; @! l - }( e k' H- O: Y; H6 v" F
- else
$ z" x+ Y2 ?! {, F; y5 [ - {
# ? b q3 q2 p - printf("!! 打开文件失败:%d\n",f_res);
& G: D8 A, l9 \$ o2 p3 [5 W - printf("!! 或许需要再次运行“FatFs移植与读写测试”工程\n");
: |' O2 ~8 h1 ?, Q3 ^) ?8 y - }
, r7 c+ p- l% w1 P - return f_res;
& k: d M0 B3 l3 s - }5 T% U, Z9 {* f0 X8 E4 n) F7 x0 h, J
- / ^3 d# ]6 ^& N8 U! F
$ a3 v1 ]. |: ]2 ^; B- /**
3 L& E, ^* e( _% W8 J9 U - * 文件信息获取3 D0 S" e( t; M! ]/ i- D
- */
9 i0 I. y5 s$ T, Q( B5 N6 F/ j - static FRESULT file_check(void)6 u! i* Z) i( u" n
- {
6 O2 b# g* i- G8 `" m - static FILINFO finfo;7 \- H7 j+ d d' }+ u8 I! Q! }
- /* 获取文件信息 */, _4 f/ I% ]; j. q
- f_res=f_stat("0:TestDir/testdir.txt",&finfo);
: |7 j- z& f2 {0 u" x$ q - if(f_res==FR_OK): a) ?* z, k4 p3 e' M
- {6 P: h- B' S( l' z8 S( H( `
- printf("“testdir.txt”文件信息:\n"); i$ m$ X3 \5 v+ u3 D
- printf("》文件大小: %ld(字节)\n", finfo.fsize);) l9 V( |. T7 S7 ~$ t
- printf("》时间戳: %u/%02u/%02u, %02u:%02u\n",
5 o5 y8 _1 x- I8 P u4 s - (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 ^ - printf("》属性: %c%c%c%c%c\n\n",
+ P4 Y6 W+ i4 P - (finfo.fattrib & AM_DIR) ? 'D' : '-', // 是一个目录0 \) c) y# s0 h
- (finfo.fattrib & AM_RDO) ? 'R' : '-', // 只读文件. v" O v) b& H" W$ W' }* k( }
- (finfo.fattrib & AM_HID) ? 'H' : '-', // 隐藏文件
( e( j) C6 [7 S/ p& L - (finfo.fattrib & AM_SYS) ? 'S' : '-', // 系统文件' R$ O7 l" s1 j/ p- T8 m' S% _
- (finfo.fattrib & AM_ARC) ? 'A' : '-'); // 档案文件! d* {+ s; c v; P. x( `
- }; W" O7 Y8 {# V" A9 s" I
- return f_res;" r/ m; J1 `1 Q
- }" V# P% {1 [' ?* `/ h
- - j& W) g9 _" K1 q/ N% z( l
- /**
, C! ]* o3 q& i/ o - * @brief scan_files 递归扫描FatFs内的文件5 ]1 X( a( U6 B
- * @param path:初始扫描路径) d |7 S( [6 v1 c* U3 p; \
- * @retval result:文件系统的返回值
6 P9 @5 M7 U4 V( K: c* F - */
+ G3 V6 Q- b7 F8 n6 L5 I - static FRESULT scan_files (char* path)
$ U( s6 P9 F9 J2 T) [# u - { " K3 a( Z2 W9 @1 q8 S8 e
- FRESULT res; //部分在递归过程被修改的变量,不用全局变量
$ |* h3 ~0 \6 l1 {5 S - FILINFO fno; $ o# H5 Z+ v. i9 M
- DIR dir;
1 a6 A. V( n$ C9 T* e - int i;
9 E+ c- I |; Z. A- { - char *fn; // 文件名
# v. [; A* I! l) H# s% P - 9 q2 q. [6 l+ W0 W _& A
- #if _USE_LFN
/ R+ I G5 x0 H4 U9 f - /* 长文件名支持 */- J$ Q. j& M# i. v3 C6 d) }
- /* 简体中文需要2个字节保存一个“字”*/
X0 T9 Y3 |0 N; W) _ - static char lfn[_MAX_LFN*2 + 1]; 7 B, u* s% p% a% S- e/ w2 `) T9 T
- fno.lfname = lfn; 9 T" y% y- k2 q% Z
- fno.lfsize = sizeof(lfn);
: Q* U& E. o2 D0 U) A. J# l - #endif
3 {1 D& \5 f; J4 \/ I - //打开目录
6 |% U4 P H' ]) [( ^! R+ e - res = f_opendir(&dir, path);
3 q9 u: U9 J l4 V1 _. ]/ J& t - if (res == FR_OK) - H. M( j. y9 a/ j% e7 Z; K7 _/ \+ w+ L4 ~
- {
8 z0 |2 U4 ]; S& w8 k, c% P1 ~ - i = strlen(path);
, h8 e# K, N3 E; s$ {0 p - for (;;)
/ k k1 ]' Q5 j4 I ~& F. e - {
6 e4 `, x. G3 Y" a) y" t - //读取目录下的内容,再读会自动读下一个文件, [/ `1 M+ @/ o$ N' g
- res = f_readdir(&dir, &fno); $ O8 w4 X- `7 \, r O
- //为空时表示所有项目读取完毕,跳出
4 T6 l( Q( i5 | - if (res != FR_OK || fno.fname[0] == 0) break; / m5 y5 i. l; F8 W1 T! C
- #if _USE_LFN & c2 E; t ]; H8 x6 ?
- fn = *fno.lfname ? fno.lfname : fno.fname;
% V" X. {, ]5 ~) A5 e8 C - #else 9 P' P: |" G% P' J) q# H) y
- fn = fno.fname;
& y' Z' W# U5 I. U - #endif
4 G- ]1 R4 `6 r - //点表示当前目录,跳过
2 s* e- k0 F$ R, E( W; s! a0 ~( V - if (*fn == '.') continue; , u0 ]! w" S2 U* ?
- //目录,递归读取
! p4 c. t% ?: y, w - if (fno.fattrib & AM_DIR) ; u5 k" e2 |7 I4 K( y
- { ' A7 g7 Q7 c. C) d, d* P2 `" Z2 [
- //合成完整目录名 6 v# t- k# U$ t1 l4 k
- sprintf(&path[i], "/%s", fn);
) r% i+ J9 X0 \1 _1 l# I0 D - //递归遍历
6 c6 y) V( P% C* M. F g - res = scan_files(path); ! `, \7 M( |) P% k+ g
- path[i] = 0; 9 k K6 h9 W& B# J3 n, m: @5 i# F
- //打开失败,跳出循环
. _/ r4 Y# U' W& U5 P! ~ - if (res != FR_OK)
2 L' U" G O# u2 l - break;
- \# i2 l" x1 i1 R$ `9 M3 ]5 E - }
5 Z, U* A3 i. [! Q! \. P0 @ t1 d - else " Z/ F/ Z& A. C( M$ l% c# m
- { 2 V {% \. [; s N" S( O/ y
- printf("%s/%s\n", path, fn); //输出文件名
2 A* H1 j7 d) C: [ - /* 可以在这里提取特定格式的文件路径 */ # b$ Q; u3 X/ V" _3 }
- }//else; a) R0 n+ A+ |* g0 W+ \# d; l
- } //for
9 z1 l; l5 G9 {0 G$ [& `* H - }
2 \% b- F. D, ]9 p - return res; " T- [3 m- W! I
- }
5 ^' ]. L- l, s; x- O - - Q. g. R$ e) {" ]
- /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/' a! u( m& x" O6 l7 Y$ I4 o
复制代码
, 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 |