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

【经验分享】STM32H7的SDMMC总线基础知识和HAL库API

[复制链接]
STMCU小助手 发布时间:2021-12-26 16:43
87.1 初学者重要提示
# }7 ^, Q# G# l. H" ]  i# w/ x  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
- y' [4 _6 J2 I0 J+ n: a  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。
1 o7 R! h. z1 i  v) p  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。1 E' w7 }0 i' W! X' k% ?2 N
  SDMMC驱动SD卡支持1线和4线模式。0 }4 R- `9 ]) ~+ y
  STM32H7的SDMMC也支持eMMC:
+ D& U$ _" Y" ?! k) p1 H$ g' J
2 I& x  F9 T, v5 u. ?87.2 SDMMC总线基础知识" Q! I9 n3 k2 ]3 m  k( w( g
87.2.1 SDMMC总线的硬件框图1 w9 s( }9 N  U( M% o* w4 f# C) }7 T
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。7 U$ r  b$ N+ f( g' A

! w) B4 }+ S, [! x5 v2 g) G; [
6eea62abe623396815a50adc87205b83.png

8 ~: U! M# [; f% M; h# A* W* F, S+ r7 Z! }4 o
通过这个框图,我们可以得到如下信息:  ! b% \' I2 B: C! w& f
   sdmmc_ker_ck输入  R; k* p. H; O
SDMMC内核时钟。
; l  w+ B& k- n& ~9 V/ N- ?% k: C4 Q; H2 p
  sdmmc_hclk输入$ q# r( ?( Q& p# h1 c
. x0 @3 `7 w6 C, Z
AHB时钟。# E6 o) h- x* O

$ B* K! [6 i/ _' I" g  sdmmc_it输出
: u. z6 [: e7 X; I2 h
& S7 [1 g/ ?6 f- B8 U8 wSDMMC全局中断。
) H* u  G- |: q6 q9 d
2 V) q( s3 h. e6 h2 n6 \5 i  sdmmc_dataend_trg输出7 M5 D7 P* i' ?- A* J
0 c2 F8 w/ i7 L0 i5 [# z0 x
MDMA的SDMMC数据接收触发信号。/ V" h8 g+ r  u3 o1 _# Y' q
: s0 N" x  C' \# d; l
  SDMMC_CMD' ?: m8 s1 q1 m- G' Z
1 M+ S! d3 [5 V% u! L3 i
SD/SDIO/MMC卡双向/响应信号。+ J- r. {8 ^. [# t0 q
9 U" ]" u5 q, X! I
  SDMMC_D[7:0]
6 ?; a) \! F- U& k$ y+ z( f8 \. `8 Z8 L6 r7 g8 K6 a
SD/SDIO/MMC卡双向数据线。
% k* I1 A1 d5 \/ g) E
2 d* Q$ c) |8 I% T1 h, D  SDMMC_CKIN
% h; e. c' A# x' c0 R1 S$ W! O
$ z. {4 s' L! ]! y3 l. c8 K来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。% a0 z6 b7 L7 i: J, X, R
. C0 ?7 O7 M; j( l3 ?! U% z
  SDMMC_CK6 B/ U9 D9 }- M3 ^; |
2 M0 s! t! `1 A5 R1 ~1 @; F4 M
SD/SDIO/MMC卡的时钟。1 w! l) v  |. c; I# p8 R' h
3 G2 x6 N7 f, K  j4 n
  SDMMC_CDIR9 P. D% R$ M2 ^8 @1 q# d

3 w5 J; i% Z8 E0 t. r, `  sSDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。
, x6 j: Q& J$ b) i+ S, p% @
4 S, T* f; L& ?$ }3 u  SDMMC_D123DIR
4 \0 m% P& _5 q
9 E/ b$ V2 P% t+ ESDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。1 u3 Y4 n" v5 H5 e

: ~* O  [  w; H; [& A  SDMMC_D0DIR
  S) L1 U0 L) \7 b2 k7 l$ B5 E' N" S' e
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。% i' O: o, w0 b$ l# m
+ y' r5 A6 ~/ j: E
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
4 e5 |( t6 v  e' q% Z  e8 i1 f8 t7 c# h% X. S; k. @
87.2.2 SDMMC时钟
3 _$ `0 x# ]4 h$ ySDMMC控制器的时钟来源:
- S; `4 D& q& x( S0 |" X7 O0 {$ q% s8 H
676ec31792fcb80bee640ed979d48084.png

) Q& j3 R' ^( j8 }5 D7 P+ n) v- L/ E
SDMMC1和SDMMC2时钟源是一样的:
% r2 H6 x3 Y6 w- b  x
0 H: C% f/ j% Q* F
79b1c69986d1ee5bc090bf1676f396fd.png
* g+ o3 S8 K6 k. \/ @
3 s. f5 a; e0 y8 |3 _. W6 R  q: J
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别( _3 @% B2 b: u( r$ @: q
注:大家应用时要特别注意这个问题。/ K3 T. v5 t0 ]8 _
7 f* n9 n4 r4 A9 V$ w; n: b7 X
使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的3 }6 i& S2 V) W$ M. K" I* |7 Z
# x& D" ^+ [) s: q  u# M( j
6a5491d2f4a8740d838af58d034b7597.png
+ g2 d( H0 c4 x6 {; p
% ~0 n7 d5 @( G$ ?7 L
87.2.4 SDMMC支持的速度

3 _. G  a+ ~3 `! u/ l4 V驱动SD卡支持的最大总线速度:
0 v  J/ }5 k0 _) d* a2 o  O1 m
% T# h9 V, E" v3 b2 }' \5 y
b70ce31107b38ea820dbc28c3caec38e.png

& U: e3 p' r- z+ v; X
7 X6 f2 i( W# T3 N& @/ N驱动eMMC支持的最大总线速度:- a# A0 Q$ }3 o9 y9 b5 \( `/ P5 f' L

) h" `0 [  e# K5 K* |  \1 [3 S  i
843bf7a054944ba7d5d137ca84e1d4ed.png
6 K0 O5 n& V2 Q! F7 V6 p$ Q8 F& R% l% I

& z( I* a+ J" k- q' g; f" |4 P关于这两个数据表,注意以下几点:
# Q4 J# I8 F; K* d2 a/ Z( F9 ?2 k! N  P6 `7 q2 l6 [+ i: i' W
  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
; r: d9 b* g# ?; y! k5 Y  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
* L& y" v5 w. K& c" d7 C  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
4 n  {' r; {2 U1 r5 ?/ T1 B8 v: Q; W7 J2 W( x
87.2.5 SDMMC支持UHS-I模式

3 O( b& i/ N  i) t- Y- fSTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:, u- U3 p7 P( F) e
6 |6 m1 |& f7 e$ v
2b8e4430b8a60dc5a1b342d7c7f75f52.png

6 P$ n4 q+ r+ H4 f
" b8 C- @. r; \/ s
85f975745619c9afc64f8889289dad58.png
, X1 {! w. t0 b1 ^. y- U9 u0 M
0 @) r" j% ?0 `+ O% Y7 v
87.2.6 SDMMC自带的DMA控制器IDMA
# \$ Y/ a% B! ?/ Y" L0 j) y# Q
STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。8 K" D2 _- A! A' y2 P: k, F+ \

8 K7 i, u) \+ S' ]: d  @87.3 SDMMC总线的HAL库用法  S6 v4 S# _! d2 o$ ^* z. S
87.3.1 SDMMC总线结构体SD_TypeDef
( t# @+ b; W1 I7 L1 o  CSDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:8 K. M& I* E5 q  K
. K- P1 K* D5 z) e6 [
  1. #define SD_TypeDef          SDMMC_TypeDef
    * Z# Y8 Y- ~1 W
  2. typedef struct6 G( J- Z1 X" K; v9 N1 y
  3. {
    , m  U* W  D. k% l  P2 h
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */" g. n  k; _3 g+ }5 W( F
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    ( i3 S* k. ^$ L- V
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */* D2 X# ~5 N  ?; p* ^
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    6 Y. F- ~4 M, d7 r# z7 d* F
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */4 Q( ~( C9 ^- W1 W6 [& F: V
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */6 D, _4 v4 q5 b& E
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */9 O* I6 P4 C! u: R, R
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    - y' n) H: a/ B4 q! J, s8 B, z4 c
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    1 h* h* d0 b  B" @7 p& V
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
    3 G. n0 C0 f$ n( i
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */
    . x8 }+ G9 Y6 b+ ?# E4 Q. Q
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    & z% \" |( |' o# _$ W# K7 `4 R
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    5 p; D# y% T; ]6 S/ q# R
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */) N% b% [$ y3 s/ r' m$ x: g" |+ k
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */% l& P9 s/ y) ^9 z0 L* E
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    ' X- d* s, T) y( H5 h- O6 m* n0 _3 p; w, G
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    7 t5 X+ @4 w( Z
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */! B' ^! D! u8 @4 S9 y7 M9 n: R
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    ) |: U3 f, p$ r# e" A
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */( H( J1 j' g, v# k% P- g
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */8 j- i' \! I  d% R- u% A. `) h6 e
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */) `& R/ O# I. k0 k6 M. |$ g
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    6 G' o3 C3 y) ~3 |
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    / _3 |7 v( T( x7 j/ e8 c  F; a
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */5 K' `. T* u8 ~3 x3 v
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */
    : t5 C4 O" l1 h7 S& A% E
  30. } SDMMC_TypeDef;
复制代码
! J, T. w" C: E8 A' v
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。. x9 K. D0 ^8 F5 x! c6 Y
2 P$ n8 o) v, t" \# y& V
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:" p& ^+ m! H- C5 {
) m" i5 }. n; H% ?* t9 U- D# _
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */9 z% E* j& x. G; q( W
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

) M- y: b* r2 \下面我们看下SDMMC的定义,在stm32h743xx.h文件。1 a' e0 K9 b0 l9 A' b
' y) L4 R2 B  W9 x
  1. #define PERIPH_BASE           (0x40000000UL) 4 e7 K9 C, ~) `9 v( j7 [
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)% D0 w( X0 K8 K& ?- F
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)8 E. B# N$ h$ s: i. x9 c

  4. 7 W# g' W$ d' X; u* U* J
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    ; [1 C5 k- V2 T2 }
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    6 s  V7 }. p' C- E% r1 w
  7. 3 ]" l/ ]& y: y% n
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)8 g- X, {" v5 F8 ]# O
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

9 J3 V1 Q( i5 C$ R% A( a; m/ l9 p+ M+ w我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。# l( B  [) m6 q( y- n
+ F* v; a/ S) o
87.3.2 SDMMC总线初始化结构体SD_InitTypeDef3 k/ F! J! Q& N2 i" g
下面是SDMMC总线的初始化结构体:
4 Q" J' |& M4 B$ t8 m" p
0 s; n0 U4 M7 U8 M
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    + r; Q; L7 u/ c& q6 _/ x# P! u
  2. typedef struct+ d" b" K. s1 L  R
  3. {
    - v* m. x" p0 b7 f( T4 O, h
  4.   uint32_t ClockEdge;            ! c: n; k& {, ~/ h
  5.   uint32_t ClockPowerSave;      " F7 ^$ y% V$ @- L# n$ U/ m
  6.   uint32_t BusWide;             ; l& g7 W' D$ h* k$ a
  7.   uint32_t HardwareFlowControl;  " W# o1 t0 w% m
  8.   uint32_t ClockDiv;             4 Z2 R! z5 a4 ~& |7 g0 s$ _
  9. #if (USE_SD_TRANSCEIVER != 0U)
    ( x' g, f0 s9 z6 e8 ]) W, a- j0 ~
  10.   uint32_t TranceiverPresent;   
    , N& o( x" j/ U6 d' h
  11. #endif . s- f. \; s. I8 A
  12. }SDMMC_InitTypeDef;
复制代码

9 V7 _- a9 C0 T5 |( H* e4 i下面将结构体成员逐一做个说明:5 i8 [! X+ U+ ?' o
( U$ r) i2 E- Z  }! F' K: c
  ClockEdge9 `1 V0 [, B1 Y' j. s" O: ~
用于设置SDMMC的数据或者命令变化的时钟沿。& s# R  `" p. J# G' j
8 M+ b$ v: r- M
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    3 V& t( C; ^) y+ T4 f9 y' Z
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码
. |' e! }1 C/ x( Z2 {8 U4 P+ r5 a
  ClockPowerSave
/ R, R8 \- a$ }' E* `" q7 f" ]用于设置空闲状态,是否输出时钟。& O6 I1 ?$ f4 j! V0 Z
: o% L3 q2 O& T' n
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)
    5 [* K! s* V3 g7 O. M0 ]- |" W
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码

5 N* k8 k: C0 c% c  }; I3 ?" B: ~  BusWide" z, R$ k  N; q0 i" K# O- a- m
用于设置SDMMC总线位宽。
/ |; g" S$ ^$ p' ~9 D  k" G. f6 ^' B; L/ J2 W
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    $ L2 H& v$ B4 \* X2 S4 Y5 E1 z- P
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_04 ?2 [& H8 }# L! w, f
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

8 W. b. x, q" Y! d% \1 J. w  HardwareFlowControl
9 t) {  g, B: M! R: x  M用于设置时候使能硬件流控制。- j+ C9 g5 Z( g3 z  j; K) J
9 S0 N7 R0 i6 Y5 A- Y5 S
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)
    ; d' K1 a& i, ^0 F
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码
* U* a( X8 B+ M. {- z# _& X) W
  ClockDiv' s# K  W5 T& d; E# [' P
用于设置SDMMC时钟分频,参数范围0到1023。
8 ?- u( y/ o1 K) R' T6 }3 N. Z. G% i  D( v8 V
  TranceiverPresent5 b. c  H+ N2 F6 k  u
用于设置是否带1.8V收发器。
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    ( X0 G) R% O0 x) I- Y; d
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)8 I' o! u# D6 s3 X0 h7 |3 C4 w4 y# T0 C
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
: R* j2 h" K# T% Z+ H' w  _
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
# A- [: v6 [$ o) B$ c
下面是SDMMC总线的卡信息结构体:. e) Q) Q7 T5 u' y. k2 x
. b3 o7 h1 J, G& F, k
  1. typedef struct
    2 P. `: c5 H9 r( @
  2. {
    ! _3 y" ?6 P, D& I5 H- F6 x+ s
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    # U0 \, r3 e' h
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
    ! R# p, q5 d4 @1 ^" S
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    ; h# C. E( W0 d( W) L4 r& l8 \# d# K
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    . {$ u0 `) {$ m+ q
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    1 p$ i& g* O0 R3 D9 [3 q5 l$ N
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */+ l0 s& r  j3 T! h. V2 S
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    . R) Z7 f  {# \9 o
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    ! k" X* B2 i: S+ i3 _; M
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */# X( w5 M$ R9 {9 a; Q5 D+ o- m6 _5 c
  12. }HAL_SD_CardInfoTypeDef;
复制代码
( `1 {. ]8 t$ t% a
下面将结构体成员逐一做个说明:
3 O/ O/ h( d' g8 C
) Q; Y/ {% `3 @, g% R8 i; m CardType( N, l8 p- f, G$ f6 c
卡类型。/ p1 f+ Y( Y6 H) @

4 M4 X1 k. K9 \, N" y
  1. /*!< SD Standard Capacity <2Go                        *// q1 d; Z+ I4 n7 i- i3 ~
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U)
    7 f5 Y+ e3 g. W: H5 }; C: h
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    , y! m0 z5 [' r/ v
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    ; h3 j/ D- j( M- T  f/ ^+ ?
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码
1 q) O* r- B7 b! n/ z
  CardVersion' ~. q" a* j, d; w4 ?
/ k3 K5 N: V! [% L" u" S3 F0 u& _

& W$ E* j. w4 T. Z$ P卡版本。2 i! `( R& B& F- _1 @$ M" t3 q
. M2 M3 `2 i+ Z
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)9 e2 @+ i) I2 r- t/ f
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码
  T( C3 y/ X. W  j4 k* w
  Class* x9 X8 a0 n. ?3 \- D7 G0 ]

3 T% t; C+ }6 f' M
& o, H2 E' d$ }( S& H+ Y卡类型。0 c. E# B0 }, L+ c
" o/ m& a8 d* P" ^1 x. }) ?
  RelCardAdd9 @$ L5 R7 U, b- a$ z3 \! ~

, Z. e3 c6 `8 D9 j* v7 _: u2 }$ E7 C, ~3 {$ `4 t/ e2 C) d! v
卡相对地址。
/ O/ m2 t5 {  H/ N" N- w! c; a6 d; k4 [9 ?8 A
  BlockNbr
+ e8 `! Y- r8 I9 H5 ?整个卡的块数。( Y; Y; A. C3 X' S6 n7 b5 `4 i  ~  z
$ b$ j  P$ H& L
  BlockSize
' y5 `% x. o2 j. W* H$ P( v' I4 e  O, d, G$ g$ ^6 B

6 m' W! k! E/ I; G每个块的字节数。
: U0 u, D: q; p# t5 Z( n3 N0 X3 B! L  z
  LogBlockNbr9 }; G, N( E5 v9 l6 e

- l1 X/ @8 z0 X3 H- v% {! |
' i. F2 C- L, n- |整个卡的逻辑块数。
# z* J- V& Q* X8 s3 v. @6 J
6 H: M- @, M+ K( X+ |  LogBlockSize2 K3 i+ K7 {7 K  r* S; N

  O1 F4 }5 q8 R7 f9 N+ e/ }% W! u* X1 k1 w
逻辑块大小5 b% T4 G+ m. [3 @- [! k
, K5 R( o! v( C1 U- a
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    & v: j' o  y8 H' j7 T* X" G
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
/ E6 T1 G- R' \" Z4 o" ~
CardSpeed3 @6 m9 O6 Z5 e! p" ]- ], A( z! I0 C
用于设置是否使能SPI总线的TI模式。
1 `7 N$ D) _& X' F2 G6 z
8 `% I! z5 z2 U2 z, Z0 R
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */3 ^0 D; n3 p6 y! m
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  
      l  P+ @& t6 P

  3. / V( t8 V) @7 f4 F
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    ( g5 w' N! U7 a  L
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    . l! A' ^/ W; @9 U  X9 C& V! \

  6. 1 {, h: t+ D/ D
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards
    ' W) c* g! I9 S2 ~: R1 u1 ~
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    ) D( s2 ]0 b% _. R& s/ [1 Y4 U
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码
5 i4 U9 z8 u( [+ v
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef$ w  n% L; X) N& _) y2 o
下面是SDMMC句柄结构体:
2 V  m  D. H6 I4 p0 |4 ?5 I) ^% e+ P& ~) y
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)* B$ J: L, x7 g" j# l5 u
  2. typedef struct __SD_HandleTypeDef
    4 o. L8 ^# v5 o
  3. #else0 W  k: z, k& N% G
  4. typedef struct; v  b/ n% D) q  D# @8 s9 ?8 Z
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */6 b" O$ d0 L2 M6 U; _
  6. {! R& n( g, ~: ?7 l% t/ Y! s
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */
    , d! q" \( [4 b- f" g3 }. K' C% w
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    ' W8 R8 i5 b$ \
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */3 Z( j1 Z+ M# v
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */" Z# X  c( V1 E" s% G
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */' O# G) z$ v4 k- C/ q( w1 n
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    1 g+ Y8 b: r+ C& {  s" D
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */) Z' `  s3 S/ D  }1 k; K
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    * G3 \9 e% R+ m# g+ M
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    # s8 F9 \& Q; ~( P: [) a
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    ! ]' `  I% M0 T6 L. b
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 *// W. S+ s( S" S% T& f6 k
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */8 i; L0 ?2 X9 L0 t
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */5 k& M8 ?+ x8 W& s. k

  20. * u/ p2 x) ~# r+ T
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    4 g5 c0 W7 [8 y
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);" ?! v, y9 q  l7 G
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    % ^, w# T5 @2 y+ i
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);+ e, W1 o9 ~* J0 |0 \
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);
    % W. ?" F$ r- j. R( ]4 p% h
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    & o4 S( Y; V) O. p7 e3 C' B
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    ( b, Y7 Y! R7 }7 C6 l  V( {
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);4 ]9 a; o0 o. `1 w
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    3 j1 J5 T- e7 n% n
  30. #if (USE_SD_TRANSCEIVER != 0U)( |5 E4 ~+ a! t5 H9 ~" O9 r
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);7 }3 }; Q3 T. v( S
  32. #endif /* USE_SD_TRANSCEIVER */8 d* N. g$ Q5 @! l2 D
  33. 0 T6 ]% ^7 r7 i  d$ o+ H6 l
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);' H* y" ?8 G# E5 j7 u$ U# A5 Q  d, |
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);- f2 y7 b  T. G! W9 n$ j1 [) k8 ^
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    ! A7 x8 N! X; s' P. x/ q7 I
  37. }SD_HandleTypeDef;
复制代码
, n( J0 v2 ]* M
注意事项:
% e# l+ d& E* o- D
4 c* u3 W4 k8 w3 ^& H条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:+ n/ U0 x, T, }  P7 `7 @7 z
4 s5 T8 V1 f6 U' y, C! E2 O
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1) X# [1 \) T& x& D, ^. B
3 r5 s. M& Q* F1 b. Q3 K
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。: M" V3 W/ Q5 W. b$ t  d

4 P2 U( O. R  J( L4 K; s这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。. E, c+ k9 w2 ]% E$ O! ]

* ]! [' j# J! V" ~# S  SD_TypeDef   *Instance2 ]; C5 f: h2 k/ t/ W
这个参数是寄存器的例化,方便操作寄存器。# P4 d7 @& I7 p& f/ O' F  p

/ I1 m% t% B7 q* F# `% m- |4 f9 e  SD_InitTypeDef  Init
/ I8 X" A; |8 T: [这个参数在本章节3.2小节已经进行了详细说明。$ ^% |# O% X, n, G  b
4 \3 P3 W& W; z/ v3 G
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c& J4 V+ Y+ S. G: A
此文件涉及到的函数较多,这里把几个常用的函数做个说明:
3 H/ Z/ X8 z2 n* I9 d
7 f* Z  {7 K7 Z6 V  HAL_SD_Init6 d. U3 b1 E8 w! O# i" S1 G0 i0 z
  HAL_SD_DeInit+ a0 x1 @: I" t
  HAL_SD_ReadBlocks
/ i6 Q/ p1 C/ o- d* D9 Z3 u+ Z! B  HAL_SD_WriteBlocks
6 k% @, |  N3 a8 n0 h! }9 |  HAL_SD_ReadBlocks_DMA
. h) y  Q; p% \: b" c9 j7 @( }. A" ]  HAL_SD_WriteBlocks_DMA$ {  B9 |7 v5 L$ V& ?8 P6 I
  HAL_SD_Erase2 Z0 n9 Y; {, S8 n
7 y3 i; d/ `6 ?. H; v( o4 h
87.4.1 函数HAL_SD_Init
! g0 v7 D2 i9 U6 S! w函数原型:
. M( O& E3 D1 j. `, W. P5 S0 E7 g6 P- i9 R( o  O
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)4 ~. ?" e) k/ y5 x3 s( K6 U! E
  2. {# G9 K5 H7 t3 m, B( R4 y" |
  3.   HAL_SD_CardStatusTypeDef CardStatus;8 p7 M9 m7 A  |& E# z* U% n8 f
  4.   uint32_t speedgrade, unitsize;$ a' o; L/ h6 y9 b: }8 j' m" a
  5.   uint32_t tickstart;+ h. F7 E- \9 I% v% W

  6. % t/ _! [8 P+ u6 t( d4 V3 }) p6 V2 f
  7.   /* 检查句柄是否有效 */
    # h- b/ K. _5 f& ^" z  A
  8.   if(hsd == NULL)9 J. x+ v/ ^5 i, O% S
  9.   {
      ]# m+ r6 x$ w" B: |! w
  10.     return HAL_ERROR;
    & m  [7 [. w- k# m, z
  11.   }
    $ }" K4 {! `1 Z$ d, v6 w
  12. 3 \0 s7 S1 h2 I5 I% E
  13.   /* 检查参数 */
    & y. O+ J( |# q; c  H7 s
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));2 o, K: y. r9 v/ B; D( G, ]
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    2 g* i3 y9 {- l1 g0 Q: q
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));0 J1 q& o' w* T0 V+ I
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    - s5 ~$ R3 p3 g0 l. Z3 C; m
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));3 l% d! |: }" \# V) j
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    , @$ V2 Z- b* O6 j+ Z9 }4 {4 e2 z

  20. * g! Z" v" H4 F3 u
  21.   if(hsd->State == HAL_SD_STATE_RESET)" d  T+ _9 r3 }. a) V  b8 P: W$ W
  22.   {
    8 Y! ^8 _; V; P9 e
  23.     /* 开锁 */: [' Y7 S5 u) ^3 M' u
  24.     hsd->Lock = HAL_UNLOCKED;
    8 S: a2 V5 x# |5 f% L0 D# L  I: f5 e9 w

  25. ' J6 d1 m; D% K. e
  26. #if (USE_SD_TRANSCEIVER != 0U)1 L1 F9 R6 f- ~5 b( @" T9 q
  27.     /* 兼容 */
    : l, U7 w. _) J7 y) B7 E9 l
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)0 Z) b2 j) v9 k) f' e. b
  29.     {* o* N' b9 A4 _: S
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;- E& B* \9 {6 W8 G$ r$ C: W
  31.     }
    . s& p) _" w, S* n: }" Z6 i
  32. #endif( g# B8 U! v0 V9 x1 r- j
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    2 R  o7 a( Q# L8 t1 f
  34.     /* 复位回调 */
    " G! W7 p, O  ^7 O9 |" B' Z5 ^
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;+ _1 I1 z" i& w, s+ N
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    " }* C& t  {# t! H
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;
    1 O+ g3 h# P& O' w4 y; w
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    % x8 k4 A) O' }3 R- @) ~" _
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;& ^' D, m- T: C, x. V0 f
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;
    7 T0 a5 h" C/ B4 }
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    $ l  P' K2 M- O% K% {! b2 J4 _
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;% _+ z( u1 j, Y. p: m/ D
  43. #if (USE_SD_TRANSCEIVER != 0U); A1 G0 y2 y+ J7 S/ Z
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)" ~6 f) s; P, g+ k0 k
  45.     {
    % H+ n; C- ~9 {7 ^- k0 I4 V
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    ) S9 L* F& Z4 H/ |: k
  47.     }
      |! L" j/ X5 R8 M) N" _
  48. #endif 0 |# m! m- _) l. m0 j: x8 X8 z8 o
  49. 0 R5 z+ Z5 _: N: Z. M2 F5 m
  50.     if(hsd->MspInitCallback == NULL)% [) M! A  m  p, h7 M& w: M( k" B
  51.     {0 h4 h: S" g8 `9 z0 e" D- f
  52.       hsd->MspInitCallback = HAL_SD_MspInit;
    3 D$ X, r6 l' J0 |: U1 E
  53.     }
    " H& `: ^& D+ i! E9 G1 i' q7 e
  54. ' @' ?7 I! R8 M/ c1 c. t& {* j
  55.     /* 初始化底层 */8 w1 g4 a! M) j( G2 ]7 ^* H
  56.     hsd->MspInitCallback(hsd);
    0 T% z5 ^2 y7 J8 }3 o
  57. #else/ U3 w& y: P& c3 U# ?
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    . Y$ N/ F; [1 f( b# w  u4 `
  59.     HAL_SD_MspInit(hsd);
    ( O. r+ R+ Q' Z/ ]4 e% g+ y5 p3 D3 x, q
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    * c4 d+ r5 h0 x
  61.   }( X! E0 T, W- u' ~( h
  62. ; l, o; a8 ?* z8 m
  63.   hsd->State = HAL_SD_STATE_BUSY;/ K# ]9 f( N. t
  64. & N1 P# `3 R$ o5 S" x' r9 E. b
  65.   /* 初始化卡参数 */3 F/ ^1 e" D+ x8 \3 o6 a0 p; e
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    # e6 \+ J1 ?+ ^" n( x0 i4 B
  67.   {  I4 w5 A* J3 l/ \" x+ O  R! a
  68.     return HAL_ERROR;) b4 e: \* r& f$ Y" t3 I
  69.   }' z2 L4 P' K1 F( I: l2 }" ]
  70. ( W: ?  A& y1 z: ]' k7 G# ~
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)3 h) y/ V) M9 g& ^# m
  72.   {" O3 h0 k' j# F
  73.     return HAL_ERROR;: T5 o/ M# @  f, R3 C* o! |
  74.   }) g& h+ Y% w6 x9 }( p) p1 s
  75.   /* 获取卡速度等信息 */9 M0 h' R' |* F& f  n& R% e% ~+ d/ V; I
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    7 a- y) x  Q$ ?1 P; ^
  77.   unitsize = CardStatus.UhsAllocationUnitSize;4 a9 [  `2 [$ o( |
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))7 t8 V! o" }5 f0 E/ h
  79.   {
    ! F# V) t3 X& B: I+ p4 s
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    ' X5 B' j/ V& a4 a. t1 E
  81.   }$ `# B1 ^* l7 c8 Q1 A
  82.   else$ X; B/ a" ]. q5 d, ]+ j
  83.   {
    % U, R1 C) p; A3 q9 K1 w
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)' w+ U& t. u8 b# F( Z
  85.     {1 g9 I7 \' j* ]- x9 t, k
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    3 ^7 _# P/ }8 k- u+ W% _  ?4 T
  87.     }
    ' Q$ m" }* S& \* Y
  88.     else
    ) {* q+ q/ y4 i5 N2 r) t, Z
  89.     {6 R; l* h/ D% y2 g0 h  e( a
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;8 i# S7 y/ B- y! e; @
  91.     }$ @0 k1 s7 m9 r; y, c5 \. F
  92. 0 N: w+ t" H, N% W+ i) h
  93.   }! Y, \0 g; X5 G$ H1 T0 z
  94.   /* 配置总线位宽 */
    , ?* Z, M4 z5 i  P' _
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    , d  }5 [6 F' x" j
  96.   {
    * o5 T+ X4 A# L. Z4 j; E
  97.     return HAL_ERROR;
    5 `* @0 @. K* p4 Z
  98.   }7 J% S( p' f% e9 {6 R* d# r
  99. ! F6 |- L) h0 [" b; Z
  100.   /* 验证卡初始化后是否就绪 */* c% z; e1 h4 P! N+ C1 g5 D& V
  101.   tickstart = HAL_GetTick();
    + n1 N1 m( [" u/ f6 g" S. ^
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    + B, m5 i* T9 R
  103.   {
    # H* F, D/ v6 }! [3 K- e# \3 m4 j
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    6 ^- H/ c3 I" P! W6 x
  105.     {3 a% a0 a+ L( B$ Z1 x
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
    7 ^' c5 p5 V2 _8 d; D
  107.       hsd->State= HAL_SD_STATE_READY;
    8 e5 c) Z5 Z0 w$ i: S% L! M
  108.       return HAL_TIMEOUT;
    9 w& l- S' r' h2 _
  109.     }
    . N) _* j. O- h* e& M3 g% j
  110.   }
    7 _& ~! v# \( n5 d: S4 h
  111. 0 C8 [. _3 G9 Y! v! k/ j0 @9 d+ h" h
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;3 l$ E, h; h6 C* V$ Z  \1 l& d

  113. 4 ~( _, }& I- A# {$ B/ m1 w8 [
  114.   hsd->Context = SD_CONTEXT_NONE;4 f. ?* [! H" w! Z! @' ^
  115. - o( a, [7 m+ [- I7 h
  116.   hsd->State = HAL_SD_STATE_READY;  ?; G/ U1 i" m) l& X1 m' p
  117. - K5 n* _0 c: J. n! R+ e
  118.   return HAL_OK;
    6 d# N) b$ Q8 X1 Z3 v/ |
  119. }
复制代码

$ K# C, C* A4 |4 b函数描述:1 M# z9 Y7 W1 Z# P, Z) x$ A

4 Q2 `5 d' Q  C2 Z此函数用于初始化SD卡。; B& y9 ]- ?5 W% S  e

2 A: {- I$ @* ^$ ]6 o- R, D0 F函数参数:6 {( R5 O  h: k2 J) C. ~
9 U% U3 G1 r' x3 ^6 V9 u& ]4 D
  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
8 y; T! M9 `) X* {/ }  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。5 j5 l8 |9 I! x4 m
8 K9 F( B/ x  x  J; O, C! a

0 ]9 Z# W! v+ v+ `2 @# @7 \) F8 [' {注意事项:
4 ~( q- Q( H% u1 j& ]* ~- X" z# B函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
7 q3 d: c& \  P1 m8 A! `7 e2 V如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
5 i5 ^' [, x8 ]# Q对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
+ p. V9 Y' C+ m6 P/ W1 [0 c5 k
7 d# r# |) q5 I1 H* N: g' c2 W* H解决办法有三2 ~' M1 R& L' y8 r# a( `

+ z$ j" x: W- M# P5 a方法1:用户自己初始化SD和涉及到的GPIO等。
/ o! l* N' k$ a% v  s0 y' ?" ^5 @& {% r# e! W! F; A7 q( D& Q
方法2:定义SD_HandleTypeDef SdHandle为全局变量。9 k; z% R3 `1 `( l9 u. I; |

7 ?2 P0 L; x$ _' C! F- \; U( ]方法3:下面的方法
1 w; T4 U0 J5 c, D; ~8 P
  b( w; r) P8 ~: ]; T
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)7 F7 ?! X+ Y/ C3 s' {% Q
  2. {9 y* A" d& s8 `  b
  3.     Error_Handler();
    , I- @9 }/ a) H  G( m/ L
  4. }  
    + ]( S+ I& c" k# y
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK), o% P  C% `7 D
  6. {9 b* z1 R( B. J
  7.     Error_Handler();
    * q3 D( j" Z( Y& _7 d2 ~
  8. }
复制代码

; n7 d8 e# c3 H0 }  P使用举例:3 d* V2 ?# S* o, @, K

, ]9 ]* }9 E7 l" U0 K" a6 O) Z" S
  1. SD_HandleTypeDef uSdHandle;# Y6 {2 B1 M# F6 E; E: h5 \

  2. * F) i  [& U/ O$ F3 Q3 g
  3. uSdHandle.Instance = SDMMC1;
    " i+ l+ M6 d7 N, j

  4. : l. v* a. u3 e0 C4 t+ }
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    : @5 Z! e1 f: d5 z6 o8 t
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].
    + X$ w& }/ @. p. l
  7.      200MHz / (2*2) = 50MHz: Q8 e( N) P$ i. Y
  8. */7 [/ V! V, b7 E) r2 j
  9. uSdHandle.Init.ClockDiv            = 2;
    ' e- x; y; k) t
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    # S" w- ]( n. n% s' d6 y% b
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    : j. e, l: X: X$ K* [
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    : e; O2 {- C; t  ^/ Z6 B9 p
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;' Y7 J9 V$ f  V* O& H6 q0 T
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    ; K: o5 t% N/ ?3 `7 r2 n2 Y/ G
  15. {
    2 a# r8 p  e( k* m, _
  16.    sd_state = MSD_ERROR;1 Q; Q5 W' ?0 \9 }
  17. }
复制代码
* i4 b# J+ Y3 g# Y. x
87.4.2 函数HAL_SD_DeInit

3 W0 h# G- t8 V' F2 |) t$ s函数原型:) }& N: t1 R3 Z1 \: ]/ d, x: {
4 C0 [" k0 u0 e1 b& Q7 v% L
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)* d6 D! u6 z2 X8 e
  2. {- U/ Y1 _0 t! |" F; }+ L# ~
  3.   /* 检查SD卡句柄是否有效 */% Y7 {2 `/ w+ A5 a) R; n2 M
  4.   if(hsd == NULL)
    + K( s& S4 |1 t
  5.   {
    3 p9 q# z( C- D$ Y! R, N4 ^1 p
  6.     return HAL_ERROR;
    ) t& @: }4 t9 X* s( a' n) F& V
  7.   }
    / C- a- p, y9 G, |0 l

  8. ! D' L" ^- S* N3 |; Z6 G1 [9 K& ?  f
  9.   /* 检查参数 */
    . M7 N# Z) N% @& L
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));: M$ y+ l2 m/ g# j# ?9 p4 f
  11. : F. \# ]0 r2 f9 q# x1 Z
  12.   hsd->State = HAL_SD_STATE_BUSY;2 @1 |8 l' M( T" z8 j
  13. * o( B0 w- X' N! W
  14. #if (USE_SD_TRANSCEIVER != 0U)
    1 @& c2 Z+ ]  _( O4 n
  15.   /* 关闭1.8V模式 */4 W# b- |8 F% G% p7 o+ b
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)$ l6 b, y; F! r3 p* l
  17.   {
    - s! S$ o; a* P- _, V8 G7 J1 f
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)5 ^" a' Z+ R  E8 e
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)3 o# x# E, b+ ^- x: a
  20.     {0 G# L8 N) ^& B% N* }9 a
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;1 E8 K4 z  q4 ?; v
  22.     }$ S, X: r" _$ R
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);
    ( J0 r$ T5 k& G
  24. #else
    2 H) _# p3 Q# ~4 ?" v
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);" @  d& ]) c0 G
  26. #endif
    . d, _# S- B& ~! e% a* T6 m3 x
  27.   }                                                                         2 g/ h/ M5 w6 Y  w; ^
  28. #endif
    8 b+ n* g% `2 o! k8 Q& d( t
  29. / W( v" ~: j7 y( F
  30.   /* 关闭SD卡电源 */  c7 M7 }& J; D
  31.   SD_PowerOFF(hsd);2 X' p' A& O+ c  T6 S$ [

  32. ( j' C; C! |3 U0 F! {! l9 v% r/ a  k
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    . a& P$ _! I5 ]2 h5 F4 _; N, I
  34.   if(hsd->MspDeInitCallback == NULL)% F) W8 D. q/ @( Y9 P
  35.   {/ T6 r. q' ]) g* ?- q, {
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;/ K  m0 A8 \! y3 Y& ?" Z' D
  37.   }
    , w! i1 Q, s& [7 Z- U
  38. : v6 v( r/ f; R  V
  39.   /* 复位底层硬件 */9 t9 r3 i; w# \: @8 ]7 N
  40.   hsd->MspDeInitCallback(hsd);
    6 J$ Q* f- W3 A# n
  41. #else4 W; v1 i; S* i- V/ c. |, \  B3 S
  42.   /* 复位底层硬件 */9 [& U* S% e& B! P# \
  43.   HAL_SD_MspDeInit(hsd);( ^( z: X+ k% r, f( e% I
  44. #endif & L) I) n. a- j

  45. # P' j) k- ?: J5 y: i* P" y# E
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ; M% j3 a& \6 R
  47.   hsd->State = HAL_SD_STATE_RESET;8 S9 ~* I6 O# C- N3 M

  48. - m) J6 d* H* |! d
  49.   return HAL_OK;
    " E) `9 w8 z1 f' O" D( X
  50. }
复制代码
* j( e' p- z/ Q5 ~6 I* q
函数描述:( p' u, G& v% K9 ]1 s0 E
& S& {2 c" [& j- L
用于复位SD总线初始化。: ^4 T1 x, F' V' z3 Z

' B5 o& ?, I) q  h1 g! |. Z6 O" U函数参数:
3 N# F- X$ S2 F& |% `" g3 W2 \+ d. \( H, Q
第1个参数是SD_HandleTypeDef类型结构体指针变量。: Y% m3 R; s! }6 v" L
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。; E6 P$ Z$ ~1 H
4 z1 b; y6 J- U( j% M* c: t
87.4.3 函数HAL_SD_ReadBlocks* b- v" H# u4 r5 U. W. A& a
函数原型:. {, D! M) U% c" m: F: v0 G

3 f1 ?9 |+ c: i5 B0 h5 ~$ W0 ]
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    . m7 O# H5 N& p7 B$ l. B
  2. {. b" D5 r5 }6 S1 b2 u
  3.   SDMMC_DataInitTypeDef config;
    ' G1 u9 h( h4 R, k$ J6 A( C/ ^; `% s
  4.   uint32_t errorstate;. G( I4 N6 E2 Y1 V& _' m' a7 ^) k) y# M
  5.   uint32_t tickstart = HAL_GetTick();1 Z  ]9 D2 b) M, t# x" r
  6.   uint32_t count, data, dataremaining;# \- |& W- C' {8 R
  7.   uint32_t add = BlockAdd;
    - a; q  F9 H; V' T0 ^
  8.   uint8_t *tempbuff = pData;& Y& i) t# g! ]8 n1 c
  9. $ h% @8 x+ v/ I, @1 R2 g  ?2 ^* v0 E
  10.   if(NULL == pData)
    ! J$ D9 }, {) M9 o. i6 Y
  11.   {) m9 ^3 O, B5 G+ y) u  z
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;% D0 @% V9 I! F' A# I% E% d3 G
  13.     return HAL_ERROR;
    2 U% t3 A( o' E% k$ n9 J8 y6 t
  14.   }. G7 B2 g* {9 \0 V. ]! m; ^) L0 F& D  N
  15. ( _- U0 G0 |  r" r3 K9 F; i
  16.   if(hsd->State == HAL_SD_STATE_READY)
    0 m( |, ~+ M6 D$ ~2 c
  17.   {
    - G7 o' |% U; D1 ?& y* Q
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;& C( y, ~- {/ u2 A7 e2 f3 Z

  19. " ^* W# q- P' w2 M! U. B
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    2 q& l2 C5 ~, P* g
  21.     {
    + z2 S* j( g3 d+ G4 W. C8 e$ _
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    7 Z$ v8 }* m" Y+ C$ ~
  23.       return HAL_ERROR;0 c, l/ N+ o: f
  24.     }
    4 Y/ s5 G5 k; Q! i. ]4 r- g: h

  25. $ W2 Z: t" A$ S2 N1 C& t
  26.     hsd->State = HAL_SD_STATE_BUSY;
    " T# z0 q# p' H, v
  27. ( G; x: [" @0 |' |2 ?3 d0 K7 h2 S
  28.     /* 初始化数据控制寄存器 */
    . @( m& |: }6 {% n2 M- O
  29.     hsd->Instance->DCTRL = 0U;
    - }3 R; @: r6 K% u, T/ I

  30. 3 C2 r& _, ]7 M9 N/ q$ m
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)9 F9 ]7 A3 ~0 Q
  32.     {& e  |# t8 b* x. f! c5 O$ E6 S
  33.       add *= 512U;4 |; V2 m9 X0 f, ]8 Z7 `. D
  34.     }
    0 C6 p0 m" J8 x; F3 E8 f
  35. $ @5 P* @  V; d2 M' N
  36.     /* 配置SD DPSM (Data Path State Machine) */1 g$ i' T9 p/ ~7 B( _. R7 W
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    . T3 h* D/ h( j1 h
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;& ]& l% k% o/ R* u8 X9 E
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    2 B) W# }" l# O
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;, s! E: a( }- o1 P
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;6 F. Q& X0 f9 ?* j% W  x
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;/ ?0 {9 \* ^5 z( X8 f+ r+ t
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    , J+ j% y# y$ V) Q& L/ h# V
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);  [1 [# I' G  Z) F

  45.   d! }. Z. v; G( n; i7 U2 f
  46.     /* 查询方式块读取 */  w* A( H/ B( M- r3 S  y0 S; K
  47.     if(NumberOfBlocks > 1U)5 x: Q0 e* O" h; J$ h
  48.     {' S. z& r5 }2 k) l  q) x# n
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;; e) N  n$ q  l$ @  E

  50. ! k5 }( Y8 E  @1 z  G
  51.       /* 多块读取命令 */8 F: o) h2 H5 }! N# g2 _
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    % E4 B/ z2 ?: @* |+ F) M
  53.     }- X0 B: c' c$ N8 h; N0 l
  54.     else
    4 r4 f0 I5 J1 A7 b, L
  55.     {
    ! ~5 g+ }2 v8 D, n9 @2 s0 R8 R3 P0 v
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;% H4 W2 ]- Z. ?; E+ |$ D
  57. & @9 y6 n# U3 w* g, b: b0 K
  58.       /* 单块读取命令 */
      m# t- g1 V$ M: n& X
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);. n+ f( d7 X' m7 E) a# ]
  60.     }
      l( D) ?" e$ q
  61.     if(errorstate != HAL_SD_ERROR_NONE)" Z' |% P. B; Y% o
  62.     {
    " t2 }) q/ f+ Y, r
  63.       /* 清除所有静态标志 */
    4 z( K5 N( w) b3 y( s$ d6 M
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);- y7 ]: k8 n1 D6 Q9 }, i* ?7 t
  65.       hsd->ErrorCode |= errorstate;$ d( H& p6 U& J3 S2 D5 ]
  66.       hsd->State = HAL_SD_STATE_READY;
    / g+ I( k5 V1 ?
  67.       hsd->Context = SD_CONTEXT_NONE;
    * u9 \2 f7 k4 C
  68.       return HAL_ERROR;4 {4 q/ k/ d# \( i  R6 h1 b
  69.     }
    / E$ S8 E* _# C) c+ ^
  70. " Y% f5 a6 P8 H! o, H/ }
  71.     /* 查询SDMMC标志 */% k* h$ |% ~1 B7 D: }
  72.     dataremaining = config.DataLength;
    9 D9 \/ x. n: Y; P4 w5 R4 W% n
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))# K% w/ g+ w' X' S' Y
  74.     {2 X- C0 m8 T+ i# Y! n
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    ; Q+ \; V. j- g' s8 A1 D4 ?: S
  76.       {% q- o4 F0 y% x4 [. M
  77.         /* 从SDMMC Rx FIFO读取数据 */  a9 @# v4 F! H7 J+ E
  78.         for(count = 0U; count < 8U; count++)* B9 H* _, P+ V& Y$ x, g" n
  79.         {
    & r5 ]1 W! f. G! f5 V/ H
  80.           data = SDMMC_ReadFIFO(hsd->Instance);, I) q  b" h" G. Y
  81.           *tempbuff = (uint8_t)(data & 0xFFU);5 y, z) A3 g9 r" e- Z
  82.           tempbuff++;
    * \/ z# k1 m# O3 h8 H( S
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);, s0 Z! B& p' a! S# {
  84.           tempbuff++;' E5 e/ L1 F3 j
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    5 p1 G2 [6 g/ o# \  P- B
  86.           tempbuff++;
    / x( U7 `; \" P/ B$ r3 E3 U' A
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);# [, d, Q3 @" o5 |5 d
  88.           tempbuff++;
    * X, X! [* y# W+ d* @3 t' s
  89.         }
    ! I( y1 I, ]/ I8 R  M" M! V" O  b
  90.         dataremaining -= 32U;/ v  h8 H9 A' L; n1 S- @& R
  91.       }9 @' i. [6 m$ o6 r

  92. 9 _, |4 n" T0 u; M4 [+ {" R4 g
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    ! j- r0 v* g5 R/ [3 p9 k" g
  94.       {
    ) C7 ^6 ~+ i! g$ W
  95.         /* 清除所有静态标志 */* U6 O- N( T& f8 {
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 ^% @, X: e+ \3 V* l
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    3 P5 _) S, W# E) {% T
  98.         hsd->State= HAL_SD_STATE_READY;
    9 s) k+ j/ K6 }4 o$ `  m( z
  99.         hsd->Context = SD_CONTEXT_NONE;
      k1 H: D6 W. L
  100.         return HAL_TIMEOUT;
    1 M) u; R* b. G2 X; @
  101.       }
    & N  s* P2 d5 R
  102.     }$ V0 F: D( f' I( E+ x( }! Z* P$ P0 X
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
    ' U% G6 [) D4 Z% i$ ~  ^0 O
  104. 2 @6 r2 b/ T2 t: L% [
  105.     /* 多块读取发送停止传输命令 */
    + F1 K5 ~9 K2 Q9 d2 L3 |
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))$ o- E" f# d7 T
  107.     {
    # y$ S8 P% j" T$ Y" {' o* Y
  108.       if(hsd->SdCard.CardType != CARD_SECURED). z/ D- D: ?* N: D" Q
  109.       {$ A, J2 {" M: b8 d" Y. K
  110.         /* 发送停止传输命令 */
    7 O- q1 O7 ^# J/ q+ }  x6 P
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);8 R4 M2 t# n8 R5 w& |. @
  112.         if(errorstate != HAL_SD_ERROR_NONE)( }0 l; P! z$ {2 p# e% ~0 |4 M* m
  113.         {
    2 C# d$ v2 E2 Y+ `& S5 f/ N" D
  114.           /* 清除所有静态标志 */6 j1 z4 g( M- Q3 A
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: N- M0 a- W! x) R% V
  116.           hsd->ErrorCode |= errorstate;
    # A3 b$ a# ]& T& l9 E
  117.           hsd->State = HAL_SD_STATE_READY;3 I' d, d4 B3 U& @9 i
  118.           hsd->Context = SD_CONTEXT_NONE;
      d! A6 p3 f& q. W, p- Y1 C3 O
  119.           return HAL_ERROR;
    9 Q9 b. i" {6 o, L
  120.         }' w% q& A# S+ ]' H: f8 f9 |
  121.       }1 u0 `# c: {1 _! b# ^
  122.     }
    5 k1 L3 l, O  F( ~6 q
  123. $ F4 B+ j5 t6 q% b2 i
  124.     /* 获取错误状态 */' T% P5 w; x6 K! D+ J3 m
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))/ S. L( E$ l5 l0 {" Q6 W
  126.     {/ L( F+ A$ u2 M! F3 m
  127.       /* 清除所有静态标志 */
    0 ?% b$ Y& f8 W
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    3 g% x8 l. h8 N. S; ^3 P6 c0 O: c
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    7 e" |) p. a& R3 N2 t. r
  130.       hsd->State = HAL_SD_STATE_READY;$ E& h* u7 e) A$ v3 V
  131.       hsd->Context = SD_CONTEXT_NONE;9 I% F! e% {  ]) a' \
  132.       return HAL_ERROR;
    7 N# s; h6 q8 P9 Z! W
  133.     }
    / O6 h6 N' _2 j  x( \
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))* N1 m9 e% ?' b4 H6 f5 ?
  135.     {3 ?0 Z8 f: s) R4 A6 E3 I
  136.       /* 清除所有静态标志 */
    3 h3 y# R+ g) B! Y; ~
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: u2 ^6 ^5 d0 i# C  {9 z
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;: p. O+ D% f" n- P  d- T
  139.       hsd->State = HAL_SD_STATE_READY;0 T) x. f: {7 C. U% R' h3 j
  140.       hsd->Context = SD_CONTEXT_NONE;0 f: X0 [5 L6 I) W& v6 G. _8 w- m
  141.       return HAL_ERROR;% t% _# v* }$ V  r$ s) g9 |6 A
  142.     }
    . P  e9 c" p) X* r+ X$ e% P
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    , q, m# k- W# e* ^: I7 z! J/ d0 r
  144.     {. [  K( p0 ]; `) _! y
  145.       /* 清除所有静态标志 */' Z* q( n% O; d7 r
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ' ]! B, I3 H( q2 |5 Q
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;, c! c" G$ F/ o- f* U
  148.       hsd->State = HAL_SD_STATE_READY;
    & D" R( ?0 F. x1 S' X$ T
  149.       hsd->Context = SD_CONTEXT_NONE;
    * y7 I# h5 H; Z" O
  150.       return HAL_ERROR;5 C4 d9 Y8 Q7 j2 P) B, `, g7 C4 D
  151.     }, s6 b$ E$ [. o2 m) S
  152.     else: B* Q1 I3 [5 H4 `% H( I1 W
  153.     {
    + u2 K" I1 D8 I$ q5 s
  154.       /* 什么都不做 */! x+ t  ]5 i9 t' x) `3 F1 J  Z8 }0 `
  155.     }
    $ c- o' K& P" o: W, B$ `
  156. ' ]6 T0 G6 I# w; R$ M
  157.     /* 清除所有静态标志 */
    8 L! q( _  ?. v: C
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    9 a  ~' p5 s# m
  159. 2 Q# E' |1 K/ J
  160.     hsd->State = HAL_SD_STATE_READY;/ A  G$ h) y7 ~9 d- c; v
  161. & ?! @# |$ x5 ^5 R
  162.     return HAL_OK;$ e' @6 f$ y" i7 ], C& w' f9 n& P
  163.   }, a2 V& Q1 K) L
  164.   else+ t. S- U$ l1 Q
  165.   {
    # v- B; i& M$ D# K# N! @
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    , {) L7 C; t- \' |" B; x
  167.     return HAL_ERROR;
    " I/ J5 v" Q/ |; r/ C
  168.   }& W& Q4 Z; w" k# W+ l
  169. }
复制代码
: l3 d- T& p  Q
函数描述:& }# _( ?( r4 \8 F; F
" o* o7 n5 Y) X0 m% L0 ?
此函数主要用于SD卡数据读取。) g+ @, \; ~& n# M& {

9 D* H' N9 S8 M( d4 g  b函数参数:% C+ J& a0 V6 N* s2 k

. [" |" h) ]6 J3 ?( i( Q  第1个参数是SD_HandleTypeDef类型结构体指针变量。
& s) y. U8 F- `4 _2 P3 S. _  第2个参数是接收数据的缓冲地址。
! C0 ]3 ~6 H, O$ N( B  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。$ z8 v+ y5 P( ]  u3 s, O' V
  第4个参数是读取的扇区数。3 e, B4 c- x' f3 A% P+ O' `
  第5个参数是传输过程的溢出时间,单位ms。9 B$ i* L  R1 U5 E) O4 d4 a
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。2 l  Q/ }1 i( ~0 t8 E) S3 x& u

. v; p# C9 M+ W) v( {
2 l& R$ G2 t+ ~, @. E& Y  N使用举例:
9 H% L( U7 E- M9 u) {0 Z! d. s+ o
  1. /**
    / q+ s: k. s5 ]: U2 D- N2 F
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
    1 @5 l+ \0 y* U) D
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit0 s: p8 O; |* T% A/ y6 g$ ^
  4.   * @param  ReadAddr: Address from where data is to be read& U0 w* ^0 V, L  g, i2 C; M
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    " j% P1 _/ p' A5 H
  6.   * @param  Timeout: Timeout for read operation
    7 D  f; G1 w- J7 B
  7.   * @retval SD status) f/ V; U7 w$ Z7 a
  8.   */1 I8 p$ S" m" x# d- d
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    + X3 r, L$ o2 j# a) v, q( h% [9 y7 X
  10. {
    + }/ o: W6 d& G9 J

  11. 4 X5 i) x, |* U3 A% r5 M8 P6 p$ m$ m
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    $ y0 K7 @5 F4 \
  13.   {( h& M! f( g: M8 `5 z; g
  14.     return MSD_OK;
    / q3 z" k6 U* q4 J' m
  15.   }7 b' s) l7 P% Q+ J
  16.   else
    % [9 ]9 Q$ }$ x' Y
  17.   {5 L$ R, K2 G) B8 X/ p
  18.     return MSD_ERROR;
    : S0 \$ W6 A  Z2 w
  19.   }. W$ o7 ]+ ~; j: C

  20. ( f1 M! I1 T$ ~
  21. }
复制代码

% N% A1 A' G4 M7 q87.4.4 函数HAL_SD_WriteBlocks
( p7 N+ Z8 G0 ^  s2 b函数原型:2 B2 i+ I3 s* w6 }6 T2 ]! A

. X, {: f: @" J" N( w0 A4 A" o
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)% q& K2 n% |& A& r  j
  2. {
    " o, h. Q, d9 j  u: \/ E
  3.   SDMMC_DataInitTypeDef config;
    : F+ d0 h( e6 B% |9 G
  4.   uint32_t errorstate;
    9 P- K) y: [7 X. E7 ]
  5.   uint32_t tickstart = HAL_GetTick();! Q# z5 G% u  o, f2 F/ \
  6.   uint32_t count, data, dataremaining;+ ~" B; B9 J/ o( T
  7.   uint32_t add = BlockAdd;
    # X, q/ G# B6 [# u0 U" N
  8.   uint8_t *tempbuff = pData;* N: x% Z7 L' u/ Q/ j( ?7 w% A

  9. 4 o3 b# T, {4 @% V; a% g& }
  10.   if(NULL == pData)0 b8 D% _' ~, h
  11.   {3 x! B3 t7 s4 @
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    * x0 \; |# u' w) E" i
  13.     return HAL_ERROR;, ^" n3 X4 I8 @
  14.   }/ n* g& T+ j! l- ]! q. n5 e5 Y
  15. . a$ o- G  j' t! r1 u
  16.   if(hsd->State == HAL_SD_STATE_READY)8 d' b0 K+ g- h6 Q$ X( W
  17.   {6 h* ]! `) m) {2 G) Q9 v2 l
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;2 G& ^1 {. Y' t4 A5 S
  19. 9 \$ }  y5 r) J# U5 k7 z; l# k
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    + a6 c$ E/ _# \0 w' w/ p
  21.     {
    / w; l9 n4 B7 B' f& q+ F
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    % H: C: L2 c. ?$ K, k
  23.       return HAL_ERROR;* Y! R' a" {% }' d' p: L4 u1 C
  24.     }! z' j/ @  m- z, V+ X" O& D
  25. % R6 i2 |2 v3 N) V# {6 I
  26.     hsd->State = HAL_SD_STATE_BUSY;0 k7 U4 Y) ?+ H! f4 `0 x. X  r

  27. 1 h' \0 I6 V6 |' m) U
  28.     /* 初始化数据控制寄存器 */* h, K, ]4 O+ h8 Y
  29.     hsd->Instance->DCTRL = 0U;
    1 T6 H. \+ ?& k& ?- M' }

  30. # v- [& g3 d+ V3 q' Z% a
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)! P; J- Z) ?! l% k" ^
  32.     {1 Q  H& @' k' \7 F
  33.       add *= 512U;
    ; v  U* T+ ^9 O# y' c
  34.     }
    6 R, ^* p7 J# G/ E. Z$ t/ L
  35. & p2 j6 A) R1 E( A% o& ]
  36.     /* 配置SD DPSM */
    4 ~9 j3 ]* `$ d( x5 y& {) }' b$ ~& \
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    7 y% m( Y5 P0 t
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    ! q3 q+ E+ J% k7 Y' F
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;: T, v+ D6 z6 C5 S+ K% {. m
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;7 @% E% E* Z/ k) Y6 W1 \
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    1 B# b, p" Z: a4 J: k) p
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    ; R* u) f( @, y
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);, w7 ~' a. P9 S' F1 Y
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
      {; W" ?+ q$ s; ]2 w

  45. 9 w' O$ S: m$ U% Z& @4 j
  46.     /* 查询方式块写操作 */  e" P+ b6 C6 W! J/ R3 `% z" H5 @
  47.     if(NumberOfBlocks > 1U)
    / ?0 N$ Y5 J2 T+ E  d+ ?1 L3 p) [
  48.     {
    , n1 L8 D3 M$ K' c- ]8 Q
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    : ~$ a3 P  Y  u& m5 {3 S, h" j
  50. 1 I0 z6 A  j4 u
  51.       /* 写多块命令 */) x4 t0 s  F  I- I
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    $ [0 E4 j7 h& Z
  53.     }4 n% J- ~: \0 C, }0 o- L
  54.     else& J$ D8 }" x* Y$ d; J; D( M' E! {
  55.     {
    " C9 F7 b3 ]0 g. \' k/ F  M
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    - j8 W+ {# i' V/ }3 w5 P
  57. 1 @7 i4 j% a5 o0 @/ l
  58.       /* 写单块命令 */
    ! L. h. B+ ?7 v; |. b7 U! I! k
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    ' o! [; G. S( s- u
  60.     }
    / w& }8 e! R; L  w
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    1 j8 K; _# z+ [/ v: a  P" `) U
  62.     {
    7 ?4 _, t, q' r; {1 W6 Q
  63.       /* 清除所有静态命令 */5 h. q7 }& g9 k: |5 J
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    6 ]" g: m1 l4 K7 |+ B
  65.       hsd->ErrorCode |= errorstate;# N* i" j$ X! ]
  66.       hsd->State = HAL_SD_STATE_READY;
    . k$ f4 n" b' D2 j( C
  67.       hsd->Context = SD_CONTEXT_NONE;
    1 C) C6 {# C! m- `# U( j2 a
  68.       return HAL_ERROR;! A) y5 a; C/ q; [) r% g
  69.     }
    ' X6 c& \/ k* ]; ~" I
  70. ' U9 V# ^1 ~1 d3 b: n
  71.     /* 查询方式块写操作 */% K; i' l3 c  P( y/ m+ ~( F: F
  72.     dataremaining = config.DataLength;' n! p# L9 H( e% z$ R
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    5 a3 Q* o* F' u2 I7 F' A
  74.     {6 f, e2 [" B6 d. `9 \, G% a6 n
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    ! b  u+ H! m4 E+ C# ]3 ^$ [
  76.       {
    7 D  C. g6 u5 {
  77.         /* 写数据到SDMMC Tx FIFO */
    6 A5 g4 q; x6 c! C9 k% z1 F/ V- ^+ |
  78.         for(count = 0U; count < 8U; count++): B( d+ l0 V" K0 s. B! H7 @
  79.         {
    4 O1 ?' a$ T1 B  z) N2 Q) J
  80.           data = (uint32_t)(*tempbuff);
    + E6 }: n! s" ~1 i, G) V
  81.           tempbuff++;0 Q! A0 q. ~# j# V
  82.           data |= ((uint32_t)(*tempbuff) << 8U);
    9 p3 l2 K% A; g) B* e( y9 w
  83.           tempbuff++;; F% J8 K9 a7 J1 Y1 K6 {! _; F% p
  84.           data |= ((uint32_t)(*tempbuff) << 16U);" c* n0 D+ o  b) |) [
  85.           tempbuff++;
    9 `. `) B5 z: p* F( j: K
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    5 d1 ^( ]2 W) Z3 I
  87.           tempbuff++;
    ( y' B  b/ G/ a2 T& c
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);
    - y8 k- q( i( V" C6 _
  89.         }# @# a7 A2 G6 h. J% y: v: `
  90.         dataremaining -= 32U;
    & T% d6 a! ~0 U. [; m
  91.       }
    , t# A5 {+ E3 F

  92. + G4 p& o6 |2 }) N% T
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))! f% H" q7 o% b) e5 u+ B
  94.       {. d& L1 a; W2 k
  95.         /* 清除所有静态标志 */
    " S3 A  p1 h3 p. }- F& K6 w' {
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);) S0 q6 O0 m' y! M
  97.         hsd->ErrorCode |= errorstate;
    ( @* E8 N+ h, a+ o- I' M* r' q; r
  98.         hsd->State = HAL_SD_STATE_READY;
    0 N) b+ a; ?8 ]$ N
  99.         hsd->Context = SD_CONTEXT_NONE;! s4 W8 n8 {2 l% ]; ^3 v
  100.         return HAL_TIMEOUT;/ g+ s! d9 X! ~; Z
  101.       }# ?6 C& A5 t- e$ y
  102.     }
    . h8 v+ o/ W0 |$ t% L, k6 R' k
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
    1 h! D$ D" ^& |; M+ @
  104. 8 x1 T' g3 L1 J( b$ _& q5 t$ h
  105.     /* 多块写操作,发送停止传输命令 */0 v' [# L# q7 b
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    $ o8 Z& p/ W# Z
  107.     {
    ; Q, R$ e8 q. h5 ]. h( ]
  108.       if(hsd->SdCard.CardType != CARD_SECURED)& W* x: o" r1 T& F' Y) U+ ^9 B
  109.       {; D, s& L, e2 L
  110.         /* 发送停止传输命令 */
    $ |% V: h  E) A: _! z8 m1 V
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    ! @" ?+ ?# d3 U
  112.         if(errorstate != HAL_SD_ERROR_NONE)! n* `5 \9 n( ]+ A, h6 g( L
  113.         {; O. Q% A# ^  k7 j$ d
  114.           /* 清除所有静态传输标志 */$ [7 g7 G6 w) O" R" N5 A
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    0 q* H- @: T7 L3 I/ W4 U
  116.           hsd->ErrorCode |= errorstate;
    6 }  |: V0 S3 n- u; M, }' A
  117.           hsd->State = HAL_SD_STATE_READY;
    3 z( x0 S/ |" W/ u
  118.           hsd->Context = SD_CONTEXT_NONE;, m; m: P+ I/ Z1 n# Z
  119.           return HAL_ERROR;+ I  O8 I! H4 d( F: G
  120.         }
    ( z/ b8 X. J& Y) ?2 x
  121.       }
    5 [1 ~2 v+ w9 {
  122.     }
    1 p" X$ V: \5 ]) f$ L, K; a5 r

  123. # N- N+ L0 S. G
  124.     /* Get error state */
    / ]& S( I0 q- t! a
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))* @, j* o8 W+ }" w6 H
  126.     {' Y1 Z0 O1 {  h# M9 y* Z0 F
  127.       /* 清除所有静态传输标志 */
    7 d: K' p1 w7 n; K% U/ l$ Z# E0 q1 k
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);1 @( i' y, B( o) I& u5 ~5 s
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    : S6 j; Z1 s4 i6 ~4 c
  130.       hsd->State = HAL_SD_STATE_READY;
    ( j  N5 q6 V: Y4 M1 V
  131.       hsd->Context = SD_CONTEXT_NONE;
    # ^2 c8 c! L. D0 m3 m
  132.       return HAL_ERROR;) p, f# T; \* Y* G
  133.     }
    7 L1 y5 P5 s( Q4 O6 o( m
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    7 n! F# b7 I1 l
  135.     {/ Q0 w  A. x2 Z; q3 I( Y
  136.       /* 清除所有静态传输标志 */! [* T: x+ t0 g1 [6 a5 C) n0 c
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);  I8 v- K9 i4 N" z  J
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;$ k' A8 `# _/ }0 A% P
  139.       hsd->State = HAL_SD_STATE_READY;2 N6 d& |# d  ]& c0 V8 F/ s
  140.       hsd->Context = SD_CONTEXT_NONE;: b1 o5 p+ p8 H3 h
  141.       return HAL_ERROR;- r6 J1 b0 K: T0 I2 N- r+ m) K
  142.     }
    & ^: Y* r+ }: B; D! E0 n1 c) r- Y
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    1 O. P7 h- Y+ L6 E. q5 n6 u4 Z
  144.     {3 a4 p- I  {* f9 W, T3 T
  145.       /* 清除所有静态传输标志 */  u( r" O# `' `1 i- F: @4 d' i
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    - |% Z5 o! u# S: W) Z2 P
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;, s3 s4 d7 k$ F1 m
  148.       hsd->State = HAL_SD_STATE_READY;: s( q; l( o0 ~9 E" ^; Y
  149.       hsd->Context = SD_CONTEXT_NONE;
    ' O* E4 y3 \7 K# d3 O: {8 A" |
  150.       return HAL_ERROR;
    / [6 u, ^5 O0 b9 ?  j) C
  151.     }+ C8 }2 w+ a1 i5 q! K; n! F9 b* C
  152.     else
    9 M+ x8 e9 J4 R( ?
  153.     {
    1 V& X$ z' W5 w6 \/ C3 ~# H
  154.       /* 什么都不做 */8 x6 {% {% }4 O- l1 b
  155.     }" u& A- a9 {/ ~" d

  156. 1 O; T) E" C# f5 q
  157.       /* 清除所有静态传输标志 */
    8 ]& s( {$ \- \: A3 h
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    & X( B1 i" k7 h9 P* [
  159. 7 W; Z! J7 @) f7 N. P+ h" o
  160.     hsd->State = HAL_SD_STATE_READY;
    $ Z9 ~2 M3 J$ A6 t$ \0 }3 m7 N

  161. 4 d! r$ x$ z6 Z- W0 B: I
  162.     return HAL_OK;; V' e) y; \# s" a+ E- z* u
  163.   }
    + k7 U: r8 z+ H) R2 m# U2 x, _
  164.   else# I5 m1 G; F& _. N) X1 d
  165.   {  W* n  l: `, H/ a  a& x3 K2 j
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    6 }# m7 ^, N! f: O
  167.     return HAL_ERROR;( c" i  U0 E$ [' ?/ I# L
  168.   }
    2 }7 \# R. p* h0 V
  169. }
复制代码

6 e; q, R$ I# ]% e- R函数描述:  b, @+ Z1 P1 F9 I0 j

$ r7 y4 g  C8 ?) j' g9 o此函数主要用于向SD卡写入数据。
! l6 y) _! A) `/ s* _$ z9 q. ]+ h4 P3 d0 w& c: b8 @) d9 \
函数参数:
  {8 N4 u, _$ m- s
' F5 ]$ g& _7 f* H7 }; _% S  第1个参数是SD_HandleTypeDef类型结构体指针变量。
* w: @0 \" c% v7 t  第2个参数是要写入到SD卡的数据缓冲地址。* |9 V( v8 _% G, Q& Z! ~
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。' @: Z. Y# S  i5 j% T
  第4个参数是读取的扇区数。- f, R7 ^$ \2 i
  第5个参数是传输过程的溢出时间,单位ms。
- p4 D: Y  P5 a" Y- v7 S  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。) R  |. i1 L# [4 i' y

( l6 @9 ~; j* Y* ~$ x1 G  ?- n
' g+ e. a( Y- I& h9 [/ L2 L使用举例:
8 P0 t4 d% n. ~: t" Z, L
5 H  L0 @% ^! e
  1. /**( q2 d$ D7 N% M6 F) F3 H; J
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.
    , y1 H% v1 ~. k" `: F% U
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    % `& H9 K0 J2 G; ?- R6 H1 _
  4.   * @param  WriteAddr: Address from where data is to be written
    " s# C5 N  B* ]
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    ) [, v/ V1 |% V  o
  6.   * @param  Timeout: Timeout for write operation& `1 c! h1 g+ b5 }% b7 @
  7.   * @retval SD status
    1 f7 {/ k3 |) X( C7 Y7 v
  8.   */' [# K+ f2 ~' @5 G) L2 l9 D& T
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)5 t* B/ ?: Z+ Y: P( w
  10. {
    4 I( ?( b& g4 Z1 n
  11. : n4 f$ @, z% d/ w/ U6 j; e$ ~
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
    9 i1 W$ L4 W) N9 |: k7 T5 Z
  13.   {
    - o; z/ g  H6 e; F& i
  14.     return MSD_OK;
    / b: m" k+ P. |- Y* R2 Z1 ]
  15.   }: q, i$ P) N( i2 c- u4 o) n
  16.   else
    4 D7 k% r+ [2 C& p& d% _
  17.   {
    0 d8 @# _4 C; ^8 j$ M
  18.     return MSD_ERROR;9 L( m+ {/ m, T. F
  19.   }
    # \# b/ k4 r$ t8 x
  20. }
复制代码

+ ?  [: y  {7 e* ]' O- [87.4.5 函数HAL_SD_ReadBlocks_DMA

  }$ |' J7 p0 Z$ K/ |/ ]函数原型:
/ y! H8 h: s0 g) d# r
/ f3 h: l( `! Y+ H  w- Y* t
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    ) a& g+ U* o5 |* O% Q
  2. {
    7 ^* @0 _) N% n6 f" U2 x
  3.   SDMMC_DataInitTypeDef config;
    1 r. Q4 q# `! Q% x' [" @) c
  4.   uint32_t errorstate;/ m- V( f+ n+ _7 T' u) @  M
  5.   uint32_t add = BlockAdd;
    4 J" p% {' \5 s' Y: l* F; @& b
  6. 6 L4 ^& @3 B8 |" ?8 h5 Z6 A0 `
  7.   if(NULL == pData)( p) F& C. ^, p
  8.   {2 E0 @+ g5 q7 m3 F7 c
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    9 X1 }# K2 ^* n& o: t! \! Z# E# `
  10.     return HAL_ERROR;
    + B6 C& s+ j; d- {2 p& c% g
  11.   }
    4 Y( J1 w4 q; J9 p
  12. - _+ `7 I/ @* y8 `7 P! _; J
  13.   if(hsd->State == HAL_SD_STATE_READY)
    " H9 t' Y5 T; n4 W- m* m9 m
  14.   {
    # {$ R. L! @$ e( w6 X4 ~
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;1 i6 w8 B& {/ k* e
  16. 0 u: ^( ]! y) @3 K# B. z
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    ; r. `8 z  E$ Y" `
  18.     {& z( g7 Q; G1 f/ Z7 C3 {
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;# L! S. q) \' Q
  20.       return HAL_ERROR;
    4 P4 C' T: r8 i; Z
  21.     }
    2 Z+ U! F: d, F
  22. " I) N2 O. r0 }- B5 n
  23.     hsd->State = HAL_SD_STATE_BUSY;
    # v+ d7 k; t1 q5 x( t4 |# p0 |. g$ E0 F
  24. 3 n2 E: t8 k' k/ T0 x8 W% v
  25.   /* 初始化数据控制寄存器 */) [- y# x  s$ K
  26.     hsd->Instance->DCTRL = 0U;$ c5 P8 h. l3 s& j3 L1 k

  27. & A# Y6 O5 G4 q- a
  28.     hsd->pRxBuffPtr = pData;) p/ b4 l" W) i$ q% q
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    ' Y( ?3 o$ R" o

  30. / u  E' A* V2 @9 L0 N, v' ]. \
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)/ _. R: E% f" d- J. s
  32.     {
    - ~: }5 U1 @$ [; z
  33.       add *= 512U;
    8 p0 |: K4 ]) G3 }7 f4 s
  34.     }# L5 a# F. z' W
  35. ( u8 D' V5 E8 r0 `
  36.   /* 配置SD DPSM (Data Path State Machine) */
    ! s6 x" F; Q" e' P8 f6 P- @
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    8 j" b6 r; E5 ^+ u: b  v! c7 g+ f# i
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;! f' [6 Q* o4 M
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    ( ^: I5 j. j8 u0 ~
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;4 H7 U4 P6 H/ _! G
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    5 C$ {! W- g2 f% E
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;- [0 U' C; \* Z1 S, S9 r+ N; Z: g
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);7 d/ F8 U3 z- k; {( D, m6 l# m8 t6 C$ q4 @

  44. . G; A( d7 n1 O
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ; h- Z/ ?' J6 g, [
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;/ a: c# Z+ A' D" _% N
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;" f# M* l, a2 `& R3 ~5 s* K: o1 o

  48. 8 y+ j, u) S8 G% W/ n+ P1 b
  49.   /* DMA方式读取多个块 */
    2 H9 g! `3 ]' k$ g
  50.     if(NumberOfBlocks > 1U)
    3 Y7 C+ M4 i- @$ ?: r# f% B, l
  51.     {+ H2 Q' S, U( M' U( S2 A
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    % l4 D1 h! K2 d

  53. , ^; p4 `6 i( j. H; w* U- x$ L1 b: ~3 ~
  54.    /* DMA方式读取多块命令 */
    ; f) h% d( T9 [: u8 F
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    ; s7 Y; W5 X0 a% |% j; t
  56.     }" B) j) A  O9 i  l2 \
  57.     else
    6 N6 O8 ]% `2 k- o
  58.     {
    ( o4 f, y# o) v5 A4 ?- ]
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);; G9 e  `  Z1 r9 u# b
  60. $ k* f. M/ I2 n! K
  61.    /* 读取单块命令 */# [7 i" X. l- C2 Y: {0 K: Q4 g
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);3 W& {% O( n5 D# I' T5 H# |
  63.     }
    + [# k- \  C  B
  64.     if(errorstate != HAL_SD_ERROR_NONE)) ]: W0 ^; Z2 S3 ]( Z* }- ^7 ?; a3 V
  65.     {$ R+ `7 m, C# M  [$ w
  66.    /* 清除所有静态标志 */$ _% `, E- P7 `0 x$ p7 d
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ _! j' l$ E( b2 L7 N# Z7 i% i
  68.       hsd->ErrorCode |= errorstate;& {5 l% B6 H! O5 q
  69.       hsd->State = HAL_SD_STATE_READY;; m. N/ x$ o% Z8 ~& E$ J
  70.       hsd->Context = SD_CONTEXT_NONE;
    - c$ t" U' x/ h8 G
  71.       return HAL_ERROR;/ c4 ]9 }% P+ S1 I. U
  72.     }
    - u( u7 s8 H0 m9 w1 W
  73. 1 s; `6 F$ {$ K4 m0 O; {) v
  74.   /* 使能传输中断 */. K. H( Q6 n( Z0 x% \9 I
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));2 W2 ]4 J9 M0 l1 y9 m1 R! ^

  76. 7 V0 ^/ n4 h6 ~7 Q' R
  77. 1 m, Z4 Y0 U8 J6 O( ?
  78.     return HAL_OK;
      _2 h" S9 X# k
  79.   }
    % S, F, k, A7 e) n" }4 H
  80.   else/ q( q& g* [3 F; \3 U
  81.   {- i; c" a! C3 t1 @5 E4 T3 i! p
  82.     return HAL_BUSY;' D: V; N- b* I& ]+ x
  83.   }, X9 b  c& K5 i9 w
  84. }
复制代码
+ T0 p) M$ K: B5 q1 ^& m7 T* |
函数描述:
1 q3 R9 Q& {  f- K! w
3 x8 S7 i# ]6 `! v此函数主要用于SD卡数据读取,DMA方式。* n' r. u3 k+ J& c( A  X+ |! P
. A0 z" _/ V  j
函数参数:) c* O* P5 p2 c5 ~6 j

! S) m' c* b" |  u& L6 l  第1个参数是SD_HandleTypeDef类型结构体指针变量。
+ A9 i9 d2 j; f1 ~' U! h  第2个参数是接收数据的缓冲地址。
2 a5 e' j/ C3 q& Y; t4 ]" g  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。/ z8 S! x! N% S  M, W& c: g
  第4个参数是读取的扇区数。
) Z( D' B+ o1 e( {3 `, R0 S  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。+ R4 n( s- y; T8 I
) h4 M% N( Z5 w! Z+ |1 w8 n
: C! `4 Y7 ^+ ]0 q! ?7 b  E
使用举例:, U; ~1 ~  I4 k1 g- n1 F# k; ^' ~

. Z$ u9 I7 ^+ C% p7 y+ u
  1. /**
    6 p1 |2 M3 C( t1 y  g8 Q  f
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.: P' A* s9 R6 J, R
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
      O) k$ J! @5 @$ a- s
  4. * @param  ReadAddr: Address from where data is to be read" V0 X# @9 ^* P
  5. * @param  NumOfBlocks: Number of SD blocks to read/ t& a- A" G/ `& R. e# R
  6. * @retval SD status% J8 [, G8 @% H, L8 Q% u
  7. */
    7 c# T) E! K  x9 q* \$ Q
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    " n( R$ z7 M) |, o6 H+ N
  9. {" Z- q( P" v3 I' x" d6 Q  `
  10. " F2 {; f5 P& a1 f5 E. Z! W$ f2 P
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)9 G5 a8 }5 r# {
  12.   {
    + I7 K% l  w2 f; n
  13.     return MSD_OK;
    6 u8 ?1 \$ D4 x% i- i
  14.   }+ P5 w* p8 r; v. _8 X0 x
  15.   else
    , x# o6 X/ S4 h
  16.   {9 K2 C" c5 i2 n
  17.     return MSD_ERROR;
    ' x7 D  ~) b5 Y# ^; d
  18.   }
    ) f% [7 x4 R9 Z( t" w) B  N
  19. }
复制代码

+ {  \2 K* |8 a) W/ f2 C% n- F87.4.6 函数HAL_SD_WriteBlocks_DMA
' [9 T* M7 M7 Y函数原型:
6 i& U2 p5 ~  B' n. \. @+ w% |0 Q7 z% ?8 z
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)$ I$ z' Z+ J- p0 p/ w6 [
  2. {
    . j  z: M* G' [) ^+ `; u
  3.   SDMMC_DataInitTypeDef config;1 W' I* p, z0 |; R
  4.   uint32_t errorstate;# W* l0 X; Q# g% X* g- L
  5.   uint32_t add = BlockAdd;2 q4 s! g  c/ W7 x
  6. # C( U" H8 p& I& S
  7.   if(NULL == pData)  G6 p4 E1 Z# H8 S+ x$ g) T: t" @1 e
  8.   {
    6 N' g9 X' y2 x* ~1 l
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    , [7 U4 t$ w* F' t6 v2 g) ?- H  f
  10.     return HAL_ERROR;
    4 U6 S# T! j6 s6 |
  11.   }
    ! b. L7 @) o- p

  12. ' j0 t" ^; t, H# W5 a+ v3 r
  13.   if(hsd->State == HAL_SD_STATE_READY)6 F- g! U/ ?# s/ m* F! S
  14.   {
    $ H, |, o% B$ {# l* [
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
      U( V) ^* N9 X* ~% t- S  _0 J- t' K

  16. / d3 u0 ^: M: M: D2 D
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    ; G1 i: h3 s' }
  18.     {  B* ]! C% s4 w8 V6 I* c( S
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    * {$ H: G* M8 \0 p) t% e+ F1 R
  20.       return HAL_ERROR;
    # z4 V- w0 `. o3 a
  21.     }
    $ ]7 Z' ?' G- w

  22. ( ?3 j, c) {" ?# G# x# @$ F
  23.     hsd->State = HAL_SD_STATE_BUSY;
    : v! y5 Y" y. `9 _! v+ g; K% C

  24. / l) |6 i9 |% s" l
  25.   /* 初始化数据控制寄存器 */  w, z# F: @: p+ l* |5 J9 ^; g
  26.     hsd->Instance->DCTRL = 0U;, x& p, n, z* {; K

  27. % y9 {% K/ j6 F, j# h7 J, Q
  28.     hsd->pTxBuffPtr = pData;
    ) e6 B9 }* U* `0 C  o  F8 A6 L
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
    3 y8 n9 ^5 [" R& f

  30. 1 F; J, Q$ N3 F9 _- d
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    / ?0 r' ^* F' c
  32.     {
    + j7 k! C9 V6 h8 Y9 v8 h
  33.       add *= 512U;5 J3 X) r9 g" _- o, ]+ F
  34.     }8 C" N! Y; X- z$ o5 p" L" u; a4 x; V
  35.   Y+ y2 f, s# I7 s+ F+ t
  36.   /* 配置SD DPSM (Data Path State Machine) */
    + k3 F% R  I! ?
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    3 A8 |- w" q( ]2 }
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;% b3 w7 y5 T& C$ O. H% x
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    3 J; _7 O6 G& G5 s
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    + d6 U! l" h3 z( D  e8 M6 y
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    9 |# l) u( M& ]7 W
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    # v/ p7 A8 S" c+ ~7 o3 M
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);& _' o* i' ?. f, R- \

  44. # l5 ?9 N% N! p' o- @

  45. 2 ~: c0 K' t+ Q* m: E6 d
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ) W- B8 V: j% X5 N
  47. 5 E* V5 T, ~5 v' w' G8 {# n% o
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    ! t+ `' Q# U' q2 R# x5 M0 ]
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;. `$ X. e6 X1 p" {+ R1 q2 {

  50. 9 G1 d8 B' \3 ~
  51.   /* 查询模式写块 */2 z) s2 K$ t# T1 a& `; O
  52.     if(NumberOfBlocks > 1U)
      V& _/ [) ]9 T9 ^  v! ~
  53.     {
    / e7 C, v( c. V: F
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);: {! H0 c! L$ E! T8 e

  55. # M" E, r6 z, i; c
  56.     /* 多块写命令 */, F# u, x3 f0 O( [6 k+ n+ l2 f
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    # R# S" y( g6 K5 r! ~" o' J" V
  58.     }
    : S# J4 \7 Q6 x8 _( v; S/ i
  59.     else
    $ A" e; Z( S! f% c5 X/ m
  60.     {) t, y5 U/ ?/ A: @
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);) _8 v7 O, `( e  p' l

  62. 6 l3 d% J* L9 @$ T% x4 g
  63.     /* 单块写命令 */# c2 F5 o' g  q8 V  e
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);$ M4 g2 B+ k  |+ T6 S
  65.     }
    ; k& ^$ m( U7 _
  66.     if(errorstate != HAL_SD_ERROR_NONE)' D0 p: r9 ]( r2 q& n
  67.     {8 ^, q5 n' h# N/ y7 G8 l7 J) l
  68.     /* 清除静态标志 */
    ' Q& ^+ L, d. i& b
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ( J( h  M- b' q; Z' @
  70.       hsd->ErrorCode |= errorstate;' n; V0 W6 Q2 s# P4 x
  71.       hsd->State = HAL_SD_STATE_READY;
    $ ~/ M9 M0 O' `! `
  72.       hsd->Context = SD_CONTEXT_NONE;
    $ L1 j1 P4 i* A) y
  73.       return HAL_ERROR;) ]# b7 [3 g! A: Y& _
  74.     }
    & k  m& o) R1 j  m6 r4 \: R6 k

  75. 6 l: e" @: h+ K% B% G
  76.   /* 使能传输中断 Enable */' L: K$ A6 [( H8 Z
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
    9 ]8 z9 {. U4 ?; N; a5 d. }- Z

  78. % }. `% [, o2 y# i! s3 Z8 A
  79.     return HAL_OK;
    7 {3 x, Y; P# p, c
  80.   }
    ( Q' y1 H2 f7 ?. I: ~4 i/ E
  81.   else
    + V; p& K5 b* A5 @2 f( B* R# \8 t* y
  82.   {; q% t7 T# Z9 l
  83.     return HAL_BUSY;" ?. c8 A3 x# X6 ^; a; ]
  84.   }
    0 g- s/ w) i# I; [* @& }8 q
  85. }
复制代码

8 a2 X+ }% R! F7 I$ g函数描述:
; @0 U  ?8 t- K' a8 t! q6 G; B2 @4 I
此函数主要用于向SD卡写入数据,DMA方式。
$ X, G6 ~# g5 \5 g; D+ z
# U1 d3 e1 l3 H  w4 B- d函数参数:" ^! f/ o1 N% G& R: y, O$ C
: ~3 Z! ?+ J4 F, O" Z
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
4 Y  A6 }5 d% q1 v* K( B  第2个参数是要写入到SD卡的数据缓冲地址。; _- c3 q5 `2 A
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
$ q4 [# w7 b$ a  第4个参数是读取的扇区数。
  I7 m0 K* F% C  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。7 h( T6 f1 g) g9 t# I' t3 V4 O

( B* v- D- q& R& P0 n8 q' d
3 C) l8 @7 Z! [3 m使用举例:
- q# r# e9 b: G+ R( k/ t' h" G' z
4 A0 c. e( H2 u9 }6 G# p' I, f
  1. /**
    5 e) m7 q% _$ D0 Y% C
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
    8 ^' a! L& c$ j% B. A, M4 X
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    ; ?" J! y% {. i6 d) r- w
  4. * @param  WriteAddr: Address from where data is to be written
    ) Q* I" ~! T/ R7 Q
  5. * @param  NumOfBlocks: Number of SD blocks to write4 F9 ^7 W% h( c( X
  6. * @retval SD status6 J- C4 O+ o6 A! W9 N* q
  7. */
    * e/ b0 z2 F: O: Y
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    : H5 K* }, C) {+ C  Y
  9. {+ h! \* Z2 W" \! _6 a) [+ n8 B
  10. - a3 W$ ?& y: t! R- N1 G& t1 L+ M
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)6 C  J. A$ B; ^- ^
  12.   {
    " z5 N8 t$ ~+ t! k7 _
  13.     return MSD_OK;
    ! X/ }7 H+ H2 \) L
  14.   }
    # P: g2 k* A/ T2 P1 k9 o+ |- p
  15.   else+ }% {( @. ~8 H% k
  16.   {
    , t) y. p4 W5 k! N6 P4 A
  17.     return MSD_ERROR;" |7 w+ V9 t! H, G" n9 q
  18.   }
    ; \! A0 ]4 V# Z7 V
  19. }
复制代码

. B; e( x7 B( f/ ~- u( s2 e87.4.7 函数HAL_SD_Erase
% U; z) i6 y5 L4 q1 {+ x函数原型:
1 ?1 C4 X/ l( i' l  V, t  f+ ]5 p/ m8 f
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    $ l# T* `0 f6 L! D
  2. {) w+ Y( N1 e; N
  3.   uint32_t errorstate;) [; P0 S7 j( R; Q: a2 j/ y
  4.   uint32_t start_add = BlockStartAdd;
    5 u  y% Y" E. g  b
  5.   uint32_t end_add = BlockEndAdd;# [4 X* c4 @% G7 l7 e# s. [5 \/ b

  6. # _/ D6 c) P( q, p1 h! B, Q
  7.   if(hsd->State == HAL_SD_STATE_READY)
    3 @& h* n# I  Z; L
  8.   {: ?: \! M3 a$ S9 G+ u
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    " H8 ?$ R: q- @" p; z8 c. Y6 k
  10. & k5 q/ a8 M7 U/ l
  11.     if(end_add < start_add)
    - ?; L% X' D" ^& l, s$ q
  12.     {) A# i3 T, S8 E) B. U. \- D
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    $ J, N3 j. b1 u- U7 g: p2 X
  14.       return HAL_ERROR;
    4 H+ \' W& x. E/ i- b6 M
  15.     }( U% C- Q  N5 i! {3 U
  16. : `# B0 ]  h- o7 O! X$ S8 S
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))' T2 X, }2 |8 w( _# n7 l6 g1 M/ z
  18.     {2 ], a9 m% y4 R
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;# d1 U+ K% U8 v$ k( ^
  20.       return HAL_ERROR;& _. _& N8 G4 J2 _9 w8 r
  21.     }5 P% k4 J1 B; u- y8 B

  22. 6 n3 E- T" C4 u/ ~* g: m
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ( V  L' s1 z2 t# N8 N" j

  24. # m! `+ ^. ~- G: F5 L- U% n
  25.   /* 检测是否支持擦除命令 */
    8 u. F' L: m( _# U/ k
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    ) }  A$ S2 ~# |
  27.     {
    # F) G2 z! P1 w/ e$ p/ G
  28.       /* 清除所有静态标志 */. t# E" S% o) A6 H
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; q+ e1 L1 f3 Z: b. Q# e
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;9 L7 x/ Y1 @0 x
  31.       hsd->State = HAL_SD_STATE_READY;% i# F  f0 @+ v' R4 C9 w4 N
  32.       return HAL_ERROR;
    ; x( R- W+ C1 U9 A
  33.     }
    * F+ i7 D5 {' s  }9 f- Q" _1 X

  34. 4 m8 _( p6 b1 F& P
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)- U% H/ o2 Z% t" N* a/ Q- v& N
  36.     {
    6 `2 ?: g6 |: B- Y* p3 l5 S
  37.     /* 清除所有静态标志 */
    / D, @  e3 L8 ~$ J* B! D* r
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    # @( `4 x/ q* n
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
    . d$ s' v; {9 s, @. C( V0 ~1 r
  40.       hsd->State = HAL_SD_STATE_READY;
    4 L  t! T0 F5 C9 w
  41.       return HAL_ERROR;2 y8 ~  N1 L( [8 [# K, T
  42.     }
      S' f' y3 B- [$ f7 i7 F4 M
  43. * }; `% ^6 l& P$ A
  44.   /* 对于高容量卡,获取起始块和结束块 */5 }6 @: t6 g& i
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    % J' A% b4 Y$ _) ?
  46.     {2 v+ }$ T: D: O
  47.       start_add *= 512U;
    / r) `' S  {6 J/ u/ d. A, K
  48.       end_add   *= 512U;
    5 Y! Z, f. y- h. f6 L# u6 N
  49.     }$ q8 T6 g9 V6 ?" _$ _5 a
  50. ' f# r! ~- g, x6 q
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    8 h) i1 P$ y* s: n6 U' c
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    7 t# B' p! T' z4 B6 k
  53.     {
    + S+ M. _7 R( l
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
    : g% j3 J: g1 _$ d+ }$ l' ?# ?- t
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    ' |; ?, S# w6 h1 z
  56.       if(errorstate != HAL_SD_ERROR_NONE)7 ~* s6 y& t* {) B: z
  57.       {8 ]. {; d* Y' M3 z- g
  58.         /* 清除所有静态标志 */1 p8 H2 S+ ^( Q+ h+ |
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);, Q) r3 J% ^' J. g6 x
  60.         hsd->ErrorCode |= errorstate;& o& e( E/ Q2 C) [9 m: P  M: [, @
  61.         hsd->State = HAL_SD_STATE_READY;
    3 C+ H- {9 U% X0 |( m
  62.         return HAL_ERROR;
    3 D; E! l1 _! J& W  w; g4 ^2 F
  63.       }
    6 H( \. m# o0 c
  64. 8 X* U, C+ Y3 s9 B' u& O/ ?
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */9 q! X$ F4 g, I  O; ?+ g) C( t3 n; j
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);3 c" I; n/ `1 f* T9 K
  67.       if(errorstate != HAL_SD_ERROR_NONE)$ Q; p+ K6 f0 g, o
  68.       {# T$ S. N5 |' [5 ~
  69.         /* 清除所有静态标志 */
    ! V3 t# b2 a; \4 s1 J
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);9 P; u! I2 X2 B2 J1 g/ b7 p$ f
  71.         hsd->ErrorCode |= errorstate;4 r' f6 p! v0 F! P+ j
  72.         hsd->State = HAL_SD_STATE_READY;0 L. a7 D5 u6 l+ k
  73.         return HAL_ERROR;
    4 |1 Z$ i( f1 |: G; g8 P  E% z
  74.       }0 q7 R! Y7 V# t
  75.     }
    0 `, _/ V, B; @7 D6 g
  76. : X, v5 C: t* z( P) d/ E
  77.     /* 发送CMD38 ERASE命令 */  v& A! E# Z* `, z9 V4 `
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);0 O" I1 z5 B3 t% u% i
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    * y1 M; u. Q0 [3 `% n2 B
  80.     {" j/ C- _4 e! n9 L
  81.       /* 清除所有静态标志 *// ^- e9 O3 N3 X  @# M" O$ N
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    + B9 J0 N1 w. r  A. M% I
  83.       hsd->ErrorCode |= errorstate;
    6 H& N, M; G) J  y; l' |0 |
  84.       hsd->State = HAL_SD_STATE_READY;
    7 \# y: c' Z( A$ b7 [: n; t
  85.       return HAL_ERROR;1 [; p1 k! B, F5 s* S9 Y
  86.     }# ]3 ^+ z8 d- P: s, D' O4 X  b4 ~( g
  87. + k# _% e" v' p
  88.     hsd->State = HAL_SD_STATE_READY;
    * `! y+ m# A  ~* q; u! g5 [" y+ Z! R

  89. 8 p( \+ ^, u7 x' y
  90.     return HAL_OK;
    / I! ^$ F1 |  A* \1 ~+ ~  y
  91.   }5 H8 x% r4 D! Z- \- V9 A  \2 R
  92.   else
    : M: a0 m, l3 H; [* z7 z+ n7 L4 p
  93.   {: t5 g- s/ C6 N; e6 D
  94.     return HAL_BUSY;! P# G  _8 P$ I
  95.   }( c3 W% U) V+ b: T/ T. U( o
  96. }
复制代码

8 {( M. N! n- h7 d# R& w! Z函数描述:
; h. p& R: a5 m$ z/ y4 }1 P
9 w0 L! I+ f4 `6 y2 t此函数主要用于SD卡擦除。$ [! K4 r  O9 I. S! _

+ {; `6 M; y& K/ \5 s函数参数:
5 g& V5 Y+ M" z# e! I: k
" L9 o0 C" I" E/ ?  第1个参数是SD_HandleTypeDef类型结构体指针变量。: W, t: u) _2 t, l# J
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
7 q! w: R$ w* {" I. L$ S- v8 J  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
- U5 @1 L5 K4 v  {% _; _& d  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
8 V- ^4 n& p! d2 w使用举例:
; x  f: z: ~( M: X3 f2 \8 H) F' ]2 _4 ]; X, r% m! S4 A2 K4 O
  1. /**
    % ^, d* S( F% g$ I/ N  |' _: f
  2. * @brief  Erases the specified memory area of the given SD card.# Z3 w+ b) a- k6 |0 f2 G
  3. * @param  StartAddr: Start byte address; E0 p5 `- P7 r4 l, l  a6 Q; E0 w
  4. * @param  EndAddr: End byte address
    ! A! W2 q. e+ W, A2 h- P' n
  5. * @retval SD status  i  n& y9 r9 s+ f( T" x
  6. */# U( E  E3 A$ P8 T7 Q6 r0 h" }. y
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
    " A- T( R( |' X0 a
  8. {
    + i& |" W8 P4 S% ?2 W$ C0 a& [; h

  9. / C' m7 F6 ?" G. i* r
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)$ C6 Z- _+ B; }, y
  11.   {5 N- S$ N* H/ j+ U2 u: {
  12.     return MSD_OK;
    9 v, ?. N, d2 N: q& J4 _0 L
  13.   }' P/ h2 E7 `: V# B! T. b
  14.   else6 d& {2 s5 @' c; e3 _" @, X9 f
  15.   {( E! F0 K% i& L" C2 Z7 V
  16.     return MSD_ERROR;
    # O5 R1 ?7 g0 e: e- K4 p. x; w# S
  17.   }
    # k0 H- \1 O/ b* v, o; f, P
  18. }
复制代码
; I' w7 o2 K; ~
87.5 总结
9 L3 I  h7 ^  ?4 T; @; ~本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。. n- ~9 P: e% M9 g: F7 J

+ q5 D* j9 Q( i5 Q0 k; H& @) U. b& J- Y4 R/ D: t0 U

- S) p6 h/ k9 ]4 q1 M) H! @5 H: u2 N# B3 g
9 E1 z$ M+ Q" C5 f5 W
9 m- i9 ?' i' x. O. l
收藏 评论0 发布时间:2021-12-26 16:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版