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

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

[复制链接]
STMCU小助手 发布时间:2021-12-26 16:43
87.1 初学者重要提示! c8 Z4 h7 P6 S% |: N6 T7 l
  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
& D+ p- |, N' r  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。/ I3 U" x% f4 M3 k
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。" ?# {: S# g- b* h
  SDMMC驱动SD卡支持1线和4线模式。
: n3 h8 Z  V- r3 l+ Z/ r) G  STM32H7的SDMMC也支持eMMC:' M- A+ L4 Q$ z+ G

  J( c' r( o# G, Q3 m0 Q# k87.2 SDMMC总线基础知识
6 c( |1 o1 Q3 }& z/ X87.2.1 SDMMC总线的硬件框图
* s8 [: H4 w3 L3 A# z8 J! z认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
; ]6 E  z# F: ~3 Z% A: K* w# c
; d2 W% L0 B9 I/ x% [3 c
6eea62abe623396815a50adc87205b83.png
* A& y' q: h1 P  j8 s( c7 L) |

: c/ D! k( A: e8 G6 T  X! S  \通过这个框图,我们可以得到如下信息:  
/ L- e" ~1 x8 h  h) B$ k- {) w   sdmmc_ker_ck输入
$ k" M# \( g: ?: ]# n: U  hSDMMC内核时钟。3 k7 G) x: J3 Z9 h) k% Z

4 T* [/ i& m4 @! |( m- L  sdmmc_hclk输入
7 Z6 f8 J" b( [& U5 S' ^7 y! ?' `6 \0 s* g% u
AHB时钟。
4 N' E# h% Z0 g. l$ A! O; P6 {8 b1 c# h& V! q
  sdmmc_it输出
4 J, t7 w2 O$ r9 P) m
! T8 d8 d+ H5 h; }1 sSDMMC全局中断。
! N; K* f, Y7 G( g) a# U
- ~# B: ^% a2 s  g2 }  sdmmc_dataend_trg输出
4 W, I& M9 r5 y' J! s$ Z3 @) D" R1 h! [) ~3 y( W
MDMA的SDMMC数据接收触发信号。3 @2 r6 J5 B# e1 P
  Y0 k# K$ n  Q0 f5 ~3 u+ I
  SDMMC_CMD
1 `) Y' X. Z5 u: ]. Y! G8 O  j4 t; P( E$ w$ z$ O4 p; j
SD/SDIO/MMC卡双向/响应信号。' R% D1 z5 A/ w. \7 U( D8 p. R
! ^5 S2 G5 N8 x; W
  SDMMC_D[7:0]
# t& G, b- `; p7 G( F
$ q, g# j% _% R8 I* vSD/SDIO/MMC卡双向数据线。/ F/ U/ Y' _. x$ v; k" G

; c( _" _6 l4 Y+ q  SDMMC_CKIN+ U; K! O/ n) q+ D; ]0 z
/ Y& z. ~; d0 v/ F, V( e
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
& [4 V/ X8 n0 q# S: j3 X
- K; {, |- P$ y' u/ C  SDMMC_CK
. k! g3 g& z9 Q9 l/ z: \; W7 g. H7 d7 w, i5 l$ D  `5 K
SD/SDIO/MMC卡的时钟。" C) |, |2 a+ A3 S& Y
8 Q6 z. g% L; g
  SDMMC_CDIR& y: ~% [4 v% ]( i! H

3 u" \! ]$ Y( S3 |" [# w: CSDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。) k0 ?$ u' }) V- f8 \" r

  Z  \% @3 c+ R  SDMMC_D123DIR
- R/ N# ]% y+ y2 R% ^
. Q! W) Y: W4 z+ W3 K  iSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
/ V1 x0 n& Q: g1 m" ~# ?( i. @$ w# B
  SDMMC_D0DIR! f( Z$ G( z$ F, [
9 G, E: L) y2 Z; A  {, q; t
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
- @: C5 @. x) i* l$ ?- h7 `: t% F4 M  A  d3 [0 p# q" z. h4 r9 P5 u
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
6 n( ^' q. M6 k: g3 i# A0 S* O2 i% Y! z. m4 {
87.2.2 SDMMC时钟
- q& p2 K) Z5 ZSDMMC控制器的时钟来源:# d% U. W, ], e/ i2 d

4 D$ \3 T2 U8 G8 i7 T! T+ _/ T
676ec31792fcb80bee640ed979d48084.png

( w5 K- V1 J5 C$ q/ s, y8 \; Y* n
  b+ A, K! N. [- e0 s- vSDMMC1和SDMMC2时钟源是一样的:0 }. f" T: p- Q) X# d

7 a2 K# o  \) c' S; d4 `
79b1c69986d1ee5bc090bf1676f396fd.png

1 B% q& V" [, }( o) s$ L4 m# k) A- F0 Y2 ^2 ?0 \; [
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
- _( c- s  U1 ~- G' I9 y& c注:大家应用时要特别注意这个问题。8 G: Q3 i* E8 k4 j2 W& y) r- q) }& o

. Q" q. P6 W* f% C4 Y# x' v使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的" o1 y/ g! F& s* @& K. R

3 m! @) m7 T- b: c1 _( x
6a5491d2f4a8740d838af58d034b7597.png

* |& O5 S% {1 {9 I" O9 T" y5 g/ P, h% a( s" l* e8 \
87.2.4 SDMMC支持的速度

% p. l; x  X& f' \9 Q驱动SD卡支持的最大总线速度:
6 x+ Q* S) \" t
) [0 W5 Q+ C$ r3 z: j
b70ce31107b38ea820dbc28c3caec38e.png

6 Y, M2 f: H! G5 w. }
5 U8 S- v/ r) @  h驱动eMMC支持的最大总线速度:  m3 o6 W% s6 G0 @. G5 d

5 A& Z4 S5 b9 C. u; h8 l7 Z
843bf7a054944ba7d5d137ca84e1d4ed.png

1 P; C0 B/ Z% `) E1 _" u
3 |$ D1 {8 a) I) \; r( H+ O  ]# C关于这两个数据表,注意以下几点:
' n) T/ V0 @) k8 ^( A. t0 I) J) O8 x7 p) g* C# z) f( |$ a
  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
5 F. n" Q- x0 [  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
. V$ ]0 m7 e: w# x% m" O9 s  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
$ a- d3 g* k8 I7 m9 l
( g; T; J/ N* c0 \& p87.2.5 SDMMC支持UHS-I模式
  k% b8 W1 o$ [0 M9 k! a- U
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
9 U' R/ `9 q' E$ |8 }" a
  c, U: ]" b5 C$ F
2b8e4430b8a60dc5a1b342d7c7f75f52.png
! R  G" b* G( J0 K+ g) A8 k- X1 }
2 m# q9 g6 T. q) e* B2 S( U* q
85f975745619c9afc64f8889289dad58.png
" j/ U% `9 l* C. j

, l: r8 A* w0 |8 y7 J87.2.6 SDMMC自带的DMA控制器IDMA

; i! S: s4 y' |: E" rSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。. d9 C9 A- |9 v2 q% w8 L

3 y( A0 M: M9 @1 g87.3 SDMMC总线的HAL库用法
8 M& s3 J. Q9 h" I$ Y) b# J87.3.1 SDMMC总线结构体SD_TypeDef
1 v9 T% R( F+ Q  H# A2 tSDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:. L$ z8 t: ?6 e8 Y  q

2 K' b% k8 H2 c6 ]( Z7 y# V' v4 c4 M: f
  1. #define SD_TypeDef          SDMMC_TypeDef
    " f/ f4 |" \3 c
  2. typedef struct
      l& _! B7 m$ g" _4 E6 T
  3. {
    " c) t. U  O" D! X( S
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    + Z0 O, d* {. {! f5 U# Y
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    + a; j% P2 z- z4 @8 B
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */
    0 h3 x6 ~, \5 k- H# @
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    $ `: o% {: ~" Z  ?$ Z
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    ; }5 B3 a1 P. d& G
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */
      I6 Q  l! B4 A2 K  l, L" e
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */$ g: @6 R" k  t) F% A! F
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    , f: \9 F( Q/ I) K, `0 C* C
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    - u, @1 h  ?- x; ^& V# i% m
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
      @3 o3 s) r1 B
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */, z" }; o; I7 v8 A& |- F9 n
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    7 R+ m) L' [2 k& T5 Q1 C
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  *// b( e7 a1 p& ^( i4 P) G" O/ }
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */
    , @4 h0 ^5 J, I4 J# ~
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */' u) z: Y% \" g0 I+ u5 b, L
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    # {+ K3 |+ N# q0 X, _  y
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */7 @" _8 a* P% c
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */5 A8 w, [# |4 A, L* l' x/ q- P5 K
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    / D7 M  q/ L3 q/ V3 S
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */4 P4 }+ Z; E3 i+ S1 }7 x
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */
    4 e$ n" l7 M4 z8 E
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */
    ' D7 M2 P  r  u) K; m& v" B
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */3 z, N7 e( x! b. s9 J
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    , e, `7 ?7 ]; X1 m! T) `9 q( \3 o2 k: [
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */( V1 |& K  m! D/ x' U1 D
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */( s- G" Z% S, B  p
  30. } SDMMC_TypeDef;
复制代码

9 ]2 W& h) Y; `0 k; ?0 A这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
/ y- F1 i4 K- t# G, Q* K  T0 {* j' t7 \5 [/ P
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
' o2 d2 r9 a8 w' t- r( m6 N% L! n% ?" f5 I* o9 y. a" \  [1 A' W
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    / s1 P1 d/ X# k
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

7 Y" v8 Z; C9 ]下面我们看下SDMMC的定义,在stm32h743xx.h文件。
6 n6 e$ ?" I% k3 u$ Q% t3 J  l
( q0 h/ ?, S/ m5 z% B& F
  1. #define PERIPH_BASE           (0x40000000UL)
    8 U7 v. V# P2 u" x
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    6 k* M3 K$ ?6 k, p5 l/ P$ @5 t
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)& F6 S9 \& i; @1 V& R+ B( t
  4. - M8 I. L: y, b. s) v- ^  ~
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)1 r9 ^6 F' {3 `+ P% t$ m" m+ ]
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)) e+ t) \) {& l# M

  7. & n9 X* n1 L, @$ @
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    3 {# t! ?1 K6 Q( y: ]8 x1 }. n3 q
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

  p+ S( ]' _+ I8 v  G我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。2 m# Q7 {% Y+ c* L* J
/ X" A+ C( j" W" v, ~
87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
5 \! U4 j4 D: H$ k下面是SDMMC总线的初始化结构体:/ n- B& @: s! X5 S5 p. V
, Z' u# `4 y( d$ @$ S  l; I( `
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    # a8 V; P0 F+ N$ T% t2 O1 i
  2. typedef struct- S0 F+ ]4 M; y: U, E. j
  3. {0 t5 F2 q/ V; j1 u5 Z4 }, U
  4.   uint32_t ClockEdge;            $ O: {0 R! d  S# l, Y$ I
  5.   uint32_t ClockPowerSave;      
    7 e' f, }* \: ?+ z$ x
  6.   uint32_t BusWide;             / o+ C6 ^) Y3 A" [/ `" s
  7.   uint32_t HardwareFlowControl;  . {1 i% q5 k7 t* ]$ y4 D
  8.   uint32_t ClockDiv;            
    , k5 \; f3 h8 v' v3 J
  9. #if (USE_SD_TRANSCEIVER != 0U)# ^3 }3 q6 `# W$ ^$ d: u
  10.   uint32_t TranceiverPresent;   
    . S+ n" Z+ e9 S7 n( K5 n
  11. #endif 7 I& C: _1 e% B5 e. P: A+ r6 |
  12. }SDMMC_InitTypeDef;
复制代码

) N( }- D1 h* b  ~下面将结构体成员逐一做个说明:
) U5 i7 g% _% [& t, |  q) _: i/ ]
, n0 @! r* j+ m  ClockEdge
0 c2 F! D& G9 a& U3 a用于设置SDMMC的数据或者命令变化的时钟沿。
7 A$ Z( Z9 z! z% G3 k
4 P: u( c5 f! q
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    4 @0 I, w* S' ~% w" }7 w! y
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码
  J, a, Z' v% U6 M  B! w2 ?" c
  ClockPowerSave  M  j4 K6 |4 c8 S* @: O
用于设置空闲状态,是否输出时钟。! D& m0 F$ O1 G: U: p) n

+ B# u; \3 \3 r; d' e# Z  P
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)0 y2 T! k4 u7 h5 s) t7 Z7 e
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
" l! ^( [2 T+ P9 z: M% {
  BusWide  X8 K" ~5 t6 D- b4 }0 |& K
用于设置SDMMC总线位宽。
5 J4 N; N# _' W  S+ }$ Y- \- t2 }. u) l/ E: G
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)9 U9 e) j. U( v5 A" U/ X' I, g
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0
    3 e0 e4 @( C/ }$ ~; p
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码
7 m4 N1 v+ q6 c0 a; M" \
  HardwareFlowControl
  v4 |- a+ a' B5 c  j用于设置时候使能硬件流控制。
9 Q& W2 D; M" }' g3 Q+ y1 L+ C! M% L  v) [
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U), q& t0 N0 B3 O1 ^) N0 f
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

5 ?: Q# x" G" H; o, {) t3 n/ h  ClockDiv- C9 A6 e# k, _
用于设置SDMMC时钟分频,参数范围0到1023。  @4 R0 K) N# m8 ?
% ~, S7 w/ ?4 A9 }1 n! I' \
  TranceiverPresent
) W8 u7 e$ T. u- q/ S+ l用于设置是否带1.8V收发器。
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U). ]0 G+ v" x" D  Z% h
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)
    8 j4 r( G2 `: A7 L, g7 F$ z- w- |
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
4 s! o. L# a( Q
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
1 Q8 m( W2 [4 U" [7 Q( k
下面是SDMMC总线的卡信息结构体:
5 k+ C7 Z: q3 _% L8 ~1 [- z6 J: h& C3 F# K: w+ c( a: w! ~
  1. typedef struct
    ) \6 o/ M& R% ]% u5 B  Y/ B
  2. {
    ' J/ p& t! b% S- }( v" d
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    3 w5 n$ j5 |# _4 j) P6 i
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
    7 w$ \' d0 l0 |2 M/ u* |
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    7 i! B+ F( b) z
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    + r' X* ^+ a% f, h$ t2 |- _# P! |7 w
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    ' J& D1 J/ r8 a, @( \( ?
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    ' [' L/ ]& j8 q. }; w* R
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    ) ^6 f$ G' j( {: ~% o
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    - |0 K: `1 C9 O0 S" C6 M! Y2 J
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */  o( F, l0 {2 _  e4 _
  12. }HAL_SD_CardInfoTypeDef;
复制代码

% t7 V  Q% ^6 U3 v8 E* V; f; ^下面将结构体成员逐一做个说明:' ?% k, f7 ^5 p- ]
7 _( s! N0 P( U. I- o1 d2 g. w
CardType' e) }& G4 S1 G, \; H
卡类型。* }4 D: F1 o# c$ l$ u! ~3 w2 h7 i

/ S8 r4 W: A& l" M# K
  1. /*!< SD Standard Capacity <2Go                        */
    ) S1 g5 g& A" o6 T: T$ F& p
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) # m! ^- Q8 ~6 ~& Z/ z1 A
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    7 b0 I8 w4 ?& u, B
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  $ c8 b% _* k# [" \# d, M+ U% p7 K
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码
+ C4 C- i. d, A8 N. r5 K9 V6 C
  CardVersion
7 Y: u/ r# \" \1 h9 P; n9 ^9 d/ b4 M

! ^. B- P8 H, [0 D2 r卡版本。; Z/ S  ~; _" }! T! K

$ f& G0 r5 ]$ H. Z5 d+ l3 I
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    + P- ]" q( t2 S
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

* F" H* u9 X5 M, R  Class
" p' d6 ^/ j3 p" x' q  v) D8 x1 l2 A3 R2 L$ }

8 n+ o  W* M2 j! p卡类型。4 R& n3 |0 k0 R9 {

4 j4 l8 R: D4 D  RelCardAdd
% x# f: N! G6 d, A0 w9 m
0 D6 P9 o3 s; n' z: ?- {6 Z, U5 \+ L5 P) t' }  c
卡相对地址。
4 t! p7 m. e6 z+ v  N2 Z; u* K+ i6 L  Q/ |0 D! L. [0 o
  BlockNbr
4 A3 G8 [5 a5 |8 n; H- n8 @整个卡的块数。* z' J; b6 M/ A0 o  c, A# O6 |  l% l+ c9 C

+ c# P% \1 d, p/ g2 ~: Y4 t  BlockSize
" j9 v; s# k8 i) V  R2 e( S% s
& \& C% W! o3 ?4 `" \. [* S" t, \4 S( }; ~
每个块的字节数。! B5 ~5 ~( I" i. |% g( r- x

. m2 {& a# O7 U( K. i5 m( c. f  LogBlockNbr9 R; o( `& i2 j3 V/ b9 f$ ^

! I' H, `, z; m6 m+ M
* T% b0 ?% [+ l整个卡的逻辑块数。
' V* j* r9 b5 H
. B) T: t' J- @' j& p) o  LogBlockSize. u! w! o. ?5 a# a% ^& H0 X# q
4 f! {; n4 u$ {: d
+ ]2 E% ?+ Q4 I4 o5 X8 N% ~
逻辑块大小
1 W4 t+ c6 H% o& {3 E! ~; D, f
4 x1 r' g1 ^# V- }% l
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    2 F, h  F) u" A) `" a. e7 i
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
+ {1 T  E2 K" i% |+ j
CardSpeed2 H. x  X  P" p( i
用于设置是否使能SPI总线的TI模式。& D. V2 n0 S5 z& U3 f1 }1 ^
  O- k0 n3 c  |
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */9 k2 N% Z( E  X" j0 J0 i/ c& p/ [7 _
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  
    / e) @4 p  [3 @  |( }9 v

  3. ' }! _: ]" n1 n3 }, i# Z+ H( q
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */   Z  ^* S) q% g' j
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    / B3 P2 Z7 O) e6 _  P+ f
  6. # G! T8 I$ j0 b. H# f3 s& n
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards  V1 O5 S( L- I- W+ M
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    : A- s/ B: ?' c  B! e0 J
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

8 u7 x/ j$ y% A! B5 P5 L' C; G) n87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
4 \! [8 f3 d% i  x. C下面是SDMMC句柄结构体:% P7 S3 N+ u6 d( A
+ E6 x" v4 k2 t; [7 W
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)) j5 u  Y4 v$ P) ^  X8 U) B# H2 v
  2. typedef struct __SD_HandleTypeDef6 ~/ B  A1 v+ F  b& c: H
  3. #else/ C$ `* B- H0 Y7 j  o+ o! Z4 e
  4. typedef struct
    4 A( p3 {* J, R2 s
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */3 n4 T5 n' U0 Z: e" _
  6. {/ h3 h) `9 Q$ |' J: \4 V
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */8 C5 Q6 X3 _. m4 J  L
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    7 u9 q9 ~/ t0 p' _
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */
    3 k$ F+ e1 W9 d; P* q
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */4 b1 t4 v7 l% V3 M% h* a
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */
    ! h8 y) f) P$ `4 u" X' J
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    ( X3 m" r7 \$ A9 M: F/ v3 o
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    6 {% O& h4 j* |
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    & I8 p+ ]2 C- |, H" T
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    ' E8 V: M- `8 _5 g/ K
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */9 K1 B1 e$ m' M" o" o/ j- F1 l
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */- ]: G0 E( @) w; |. K$ N- d  v8 z
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */
    6 j7 V% v5 b' V6 l* f1 x
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */! u! N- y/ i1 o; w

  20. ; t: n+ p: P6 w2 }. _2 B
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    ( F* q3 ?+ n3 a0 g% ^( V
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);2 n) u, N+ w6 f) S
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);  R# v) Y  p4 s
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);. C" N" Y" Q8 z! Y" E, L% C. B$ a
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);* _8 ]" Y9 _* W9 J4 ^* r
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);  \( z6 F$ S) S& N4 k
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    3 m  ~! m$ a: ?1 `; y1 C
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);/ m: ?" d& ~4 f; p9 p
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);" c7 Z" s8 x; n4 N# [
  30. #if (USE_SD_TRANSCEIVER != 0U)7 G7 `' U( l1 v: K2 ^5 ?9 o* F$ J
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);4 ?( t7 R! [, P! n
  32. #endif /* USE_SD_TRANSCEIVER */) h: ^9 p% |  F" f' n( ?

  33. / X' g+ Y& U" K/ G" J5 F. C; u
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);+ I7 K# d, ?& ]) o- r5 e
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    2 ~, }2 s% A' u. f: W2 ~
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    5 d1 o. A, S9 \6 v/ X- B' p, \
  37. }SD_HandleTypeDef;
复制代码

, R3 q5 M& \  L1 u8 K! N( C! n注意事项:
8 ^. j3 l. z& u! a6 X% z4 n7 |3 M* r6 b) a* f
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:+ ?, Z9 e( |3 U% o4 W) y( u3 e3 d" t
5 F/ K) O9 C  F* y9 X* t" V
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
4 g" r* U; r* U* [/ z! M
& ^* V6 Y* ~/ b/ P& \. x, o4 t通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。; p/ m2 @0 Z0 M) W0 x5 V% U

- ]9 ^; i) B# S( i% M& O; m% @这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
" r* t- ^9 L" }* a1 I7 n! O1 J
" d% p# T' H0 m( b  SD_TypeDef   *Instance; D- ]& g. P+ |' ~, i; l7 y6 P8 F
这个参数是寄存器的例化,方便操作寄存器。, v" t% B- E/ {. {' ]  r
7 E$ E/ B8 |) M$ |+ `
  SD_InitTypeDef  Init) U2 s: Q: E- B# s2 n+ H5 v% c
这个参数在本章节3.2小节已经进行了详细说明。- d- Y- P" G/ P5 f, `
9 U, a4 M2 R1 v( W7 _/ U
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c
; E7 S9 Q& g$ f9 F9 J此文件涉及到的函数较多,这里把几个常用的函数做个说明:
2 G8 D- M. z  L' s1 H* \; e7 s
4 I8 N. k. E7 K4 p2 J6 J  HAL_SD_Init5 S& B% ^0 z3 v* T5 h% D7 H% ~( G
  HAL_SD_DeInit- v! f, I" i2 q4 C
  HAL_SD_ReadBlocks3 c( I7 ~* A6 F4 r" e
  HAL_SD_WriteBlocks6 Q6 D1 a8 i+ M4 g' Z4 a
  HAL_SD_ReadBlocks_DMA; l$ p4 o* A4 o
  HAL_SD_WriteBlocks_DMA7 q' l+ T* E; S7 X  x/ [
  HAL_SD_Erase
& W$ ~6 S/ t* z7 v8 ~3 j7 c/ [
87.4.1 函数HAL_SD_Init2 H+ T6 Y: N0 }
函数原型:& Y! l/ v  U0 Z; l' {8 [% N
2 G% q! E9 v6 J" M( M' c4 q- P
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    1 S+ o- H9 T( q' X
  2. {7 `- O/ E; \- Z6 F+ j
  3.   HAL_SD_CardStatusTypeDef CardStatus;! O0 h# J2 O6 [* t, i* W% P
  4.   uint32_t speedgrade, unitsize;
    0 n3 o+ L/ V# _2 Z
  5.   uint32_t tickstart;
      o3 o8 P" D& o+ H4 o2 x
  6. ; I9 ?/ Q6 ]2 ]1 I2 t
  7.   /* 检查句柄是否有效 */
    : {* g& u; k5 }1 i- w
  8.   if(hsd == NULL)5 P1 o% l% I& U  z! r9 y* [
  9.   {; S- H, d. _0 C5 d' j/ E) x
  10.     return HAL_ERROR;( t7 _( `# b5 B4 k( _
  11.   }
    # g* [, h8 J9 K. x" D( Z

  12. 4 t- Z$ J6 b8 I" }5 U
  13.   /* 检查参数 */
      H6 n4 u4 _& d. m. R% f0 U' I$ H6 X
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));) n% x! K* i+ @  \6 l( o% \# i& N2 N
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    : @: G4 B+ n* s  f& h/ |" l2 \& ^
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
    ' P- i4 F* i( M8 h/ D
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    % B5 p! {! ]) K& i" M- }2 K* }
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));1 u* s; j8 x' W& C# F3 G& \" ?
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    ( c$ F" p* d  T1 H) N3 Q1 x, o: e2 |3 b
  20. 6 M; z& d6 u& ^  I- _* v6 M$ s
  21.   if(hsd->State == HAL_SD_STATE_RESET): y+ B9 z! R7 S3 N' ~
  22.   {
    / B3 f4 {( I9 T) k* x8 p( c  o% |
  23.     /* 开锁 */
      m) |: K) V0 D
  24.     hsd->Lock = HAL_UNLOCKED;! w7 p3 v* O, \$ V
  25. % ?" V7 x8 q( X5 A0 t- V
  26. #if (USE_SD_TRANSCEIVER != 0U)8 S! Z& O; X7 L( u' F0 F
  27.     /* 兼容 */
    * P* ?2 O- L6 W" S7 r
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
    $ @% \0 y+ A: B6 o
  29.     {, R8 T  M& I. @: g1 g! V
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;# c/ y  a4 w* c! l/ W. ^" L, C$ {
  31.     }
    4 {* U$ w" j) B
  32. #endif
    3 l! x/ ~1 H1 S6 e
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)$ y4 Z1 S# V7 {6 a1 R& z
  34.     /* 复位回调 */
    + P  {& l+ r9 m$ E
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    5 J4 M* x  @( Y: g% Y
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    # y; H- S5 m# P9 @* [
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;' P! u2 |' n- V6 T  u3 w; K! u) d+ @
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;! ?. H' w1 S; E" ^' H$ {7 O
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;; Z7 y" P* W. V" H" W% ~
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;: W2 s( z* x, u0 {7 C: h: \
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;- N1 p0 ?; [2 t4 z/ A$ j/ u( i
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    ! z/ `( G) H$ N+ ^, ?6 f& u
  43. #if (USE_SD_TRANSCEIVER != 0U)6 S- U3 e4 O; C
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    2 y2 B, _, K4 T. R, h
  45.     {+ P4 t- Y- b, d4 j
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    : o7 x3 q+ ^. J5 A8 L( ~+ i9 W
  47.     }% Z" ]1 P' f, ~1 _9 v/ R5 X% a
  48. #endif / t0 W; q  N  X! m: S7 k! a' J

  49. / X0 ^7 V' v5 a# p
  50.     if(hsd->MspInitCallback == NULL): h( S7 u$ [; K& V! N* _
  51.     {
    6 \- V8 Q6 |6 a, ^# H- m- h! U
  52.       hsd->MspInitCallback = HAL_SD_MspInit;* y$ E7 w! n  i& L
  53.     }. e% Q3 H7 n7 J5 f6 s
  54. 8 l. w& l! g9 l) T( j8 L
  55.     /* 初始化底层 */
    . M5 ^$ N2 N. J' R& b
  56.     hsd->MspInitCallback(hsd);5 c" o% \. Z/ ~& e& J0 O/ ^: z
  57. #else6 m. C. `1 u, g7 X. h5 j8 y+ U9 J
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    9 C3 }6 B! S) u3 }  L
  59.     HAL_SD_MspInit(hsd);# [) x( L: \5 ?$ |
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    9 [3 {' I1 s& t. V$ ^8 B
  61.   }
    + v+ p* D9 s' g" {% I- v
  62. 0 {" V1 U' f! h4 V0 N/ p
  63.   hsd->State = HAL_SD_STATE_BUSY;
    6 e/ ]4 T  j1 c: \, }

  64. 5 [$ f3 R$ V( s7 w. l0 D! J
  65.   /* 初始化卡参数 */& X& H6 ]- r. ?. i( W: c. ?
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    0 N, w) I- t  S, \' v
  67.   {
    ' W. m0 }4 r% O0 U8 d: |& P
  68.     return HAL_ERROR;
    5 d9 ]4 z6 i9 j) j2 @
  69.   }3 y4 F3 f0 E7 g# Z# E8 I

  70. / V3 A. W! z$ o! g
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
    5 E' V% I; G: K- E/ V) [/ A
  72.   {
    # O* I, u9 O! f* |3 K0 w' O5 h3 g
  73.     return HAL_ERROR;
    ; }' J# Y  c  M6 I
  74.   }
    . d+ i" M- B0 u" [% j4 q+ Z3 Y+ g
  75.   /* 获取卡速度等信息 *// m; W5 U8 S' x4 I7 W
  76.   speedgrade = CardStatus.UhsSpeedGrade;, G; h, [( {' N- h2 T6 L" e
  77.   unitsize = CardStatus.UhsAllocationUnitSize;5 }! V' b, F5 B3 k7 v
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    , Z3 A' \9 X, @- w
  79.   {
    . Y; E$ D  ~8 X! L  d8 p
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    # N. C. d, r' F0 Z' h
  81.   }
    : ]! n6 E7 g! w. P7 j8 M8 q
  82.   else
    7 V3 T1 B, W4 e  H: ~9 ^
  83.   {
    ! G9 `" G$ d' b" ~, |! Y$ l& c
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)8 D$ U# B/ W8 u, Z
  85.     {
    : _& O2 H$ K, y& c. t
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    1 Z8 o5 g* k5 K, d6 C
  87.     }
    0 U+ k7 }% Z  ~) }4 H0 X
  88.     else5 J# I# c1 m' V) J. P  p
  89.     {* h  a5 |: a, ?6 Z
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;* @+ ]2 k- X; C$ x
  91.     }
    * ?& z) K! z- P) A" _

  92. 6 O2 f+ I4 w8 y, y% n
  93.   }, W" _9 f  `! r: {
  94.   /* 配置总线位宽 */0 U9 V3 ~$ e- N$ y4 V: h
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)5 u  W/ r" K* a9 u
  96.   {9 D8 x$ N: B% r! r3 S+ p
  97.     return HAL_ERROR;
    4 t* a* v' Y- j6 N* q7 r* R
  98.   }
    3 b, _# S; y; `/ w6 R) ?

  99. # M9 U  {$ y8 Y; \
  100.   /* 验证卡初始化后是否就绪 */; D% P0 ^9 {4 U' M3 s% C% n7 H
  101.   tickstart = HAL_GetTick();
    - s3 R$ _; O; g- A) D8 o+ L
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    # F0 ^% f1 [+ R2 t' _5 |0 A2 b/ q+ R
  103.   {. X  D  t4 a5 D0 B
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)! W0 a+ X- U5 t; i
  105.     {! ]5 d) h& b$ s
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;" [  {& w8 a% N7 Z
  107.       hsd->State= HAL_SD_STATE_READY;
    ( h$ H. a2 a6 h: z
  108.       return HAL_TIMEOUT;) R4 c7 J" q) a- J1 ^# L
  109.     }: K- G0 ]+ G3 `1 F9 L3 p, U& D' Y
  110.   }5 o5 g4 s% L& `: M# E

  111. 9 F* U- f$ A& a& b% T2 @) F+ I
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;2 r+ i$ j; i0 T' Z. i

  113. 1 @: z/ E8 z5 K* ]
  114.   hsd->Context = SD_CONTEXT_NONE;
    * Z* U/ W) x' _

  115. ' ?+ |, a$ `% k8 P. G( k- H" B
  116.   hsd->State = HAL_SD_STATE_READY;& L7 M; v5 o& R) k

  117. * F2 j; d0 v) Y0 W3 w" S2 M8 m
  118.   return HAL_OK;8 p: C: k5 ~' ~+ o1 r+ E
  119. }
复制代码

- q) u& V# r& X3 n0 @函数描述:
% \% y( N) Q9 x2 o" e/ ?6 `/ j- w& p7 e) H2 `/ o
此函数用于初始化SD卡。  |! c1 x6 {& F+ p! f/ u4 `
7 }, N3 J6 x0 p  A
函数参数:- D& X! F# I8 Y6 f

% ]) b8 |; n2 z  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
) u6 A" F% e7 S1 T0 {0 D  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
% K1 F; t9 k- m8 T# F1 t' y
6 e# }" h: h- Z4 Z) s; H
  f) @3 Z( V; N$ ?0 |. L' ^注意事项:5 P: m1 V1 ?( [9 `- c. J% _
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。* y3 W" K) W, p( G  F/ Z6 c4 S
如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。' M7 q* ^) Q. c7 V  d8 o' n0 k' ]9 E4 `
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
8 t' m6 Z- ^# k* M! [* x4 _
& z" o  l- V  |; {解决办法有三6 T6 x  |- j4 D( j

7 }% `9 w7 O/ s3 T- N( u) ]方法1:用户自己初始化SD和涉及到的GPIO等。9 w9 \5 r& |. C
/ o+ ^/ e0 J6 ?! g+ E6 C6 @
方法2:定义SD_HandleTypeDef SdHandle为全局变量。8 l8 v! @6 ]. a, H

* O7 p" O. R' F7 V方法3:下面的方法, W. K  Z! }+ D! w0 J* R8 ?

5 @3 P6 I. p; ]% v- t
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)2 e. x. j; \5 b6 u' Y. g
  2. {9 |9 H. P- m5 ~0 S& E% g3 K; C
  3.     Error_Handler();" Z1 J8 L( \: G3 [
  4. }  
    ) @+ S7 f, P$ u! X, ^
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)5 J6 a2 a7 N! z
  6. {
    8 I: E+ y! n3 Z' j
  7.     Error_Handler();7 s! w& a7 o$ n# P: n* x& c$ S
  8. }
复制代码

; d- _: v! e+ `使用举例:$ L- n5 d' T* o+ f

5 _3 e( J; ^) b, F# P
  1. SD_HandleTypeDef uSdHandle;
    + Q& l+ c% V2 l2 I1 \

  2. & p% h+ n7 x9 s( J9 h. H) v4 u6 Q
  3. uSdHandle.Instance = SDMMC1;5 _5 l! P; G6 j* F4 }; N
  4. * Q2 \* P! V2 {5 T
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock, B% ^" @% m7 `9 P6 M  n- h
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV]., Q/ o) h1 u$ g2 ?
  7.      200MHz / (2*2) = 50MHz: |; L, e  `- I3 Q* x8 c! K7 F& D0 k* J
  8. */! P  R7 Y# q3 {. w) D! W
  9. uSdHandle.Init.ClockDiv            = 2; , b1 P; a8 `; h, e1 @
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    1 S! S$ C, k' o6 ?. _) u
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
      L& R' {# h% N3 E
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;; q& ^) Q6 M$ |& q+ v
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;
    0 v/ E* s0 q+ N  O  T
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    - F7 C8 t8 X; b5 B8 L; j
  15. {
    ' f% F& o8 A0 J, K6 _3 }
  16.    sd_state = MSD_ERROR;" C- g' o8 @+ M0 _: c+ G
  17. }
复制代码

1 w. \' a1 F1 P9 e, G; R' ]6 K87.4.2 函数HAL_SD_DeInit
5 ]: x1 S; R. Y( \9 a4 k7 j% u
函数原型:7 A- ~8 s' D! @" M3 H. I% E! z
& K, \6 j4 ?# w% T8 o( V. G+ t2 ~
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    ! K& T2 F& _0 A3 `$ l3 k
  2. {  v- q  K6 v/ d6 k6 {1 |' f# h
  3.   /* 检查SD卡句柄是否有效 */! t7 e5 F6 M; G: r/ o: Q# ]
  4.   if(hsd == NULL), G7 W# c4 E  }; Z
  5.   {/ G$ h' O6 g0 D" c. x
  6.     return HAL_ERROR;1 M2 `2 T9 r/ ^
  7.   }& z# _, A1 `8 E2 p  G: ~
  8. ) S* j9 b/ A* ?- K! x+ D' ~1 M
  9.   /* 检查参数 */. C1 i2 W9 z# J# j, L* D8 ?
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));; V4 G. Q# }/ b5 {( `

  11. 7 x& s3 @1 H* q2 _% M
  12.   hsd->State = HAL_SD_STATE_BUSY;9 ^# G6 V5 n9 ^, r' G0 x
  13. + V2 M# ^/ T7 Z8 ?. G& v- m
  14. #if (USE_SD_TRANSCEIVER != 0U)
    3 A- W/ X5 Q- N' t
  15.   /* 关闭1.8V模式 */' i' c  u& m; ~2 F5 b
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)2 b0 Z- z; K$ c6 U- K
  17.   {
    . _& ]$ ?# H) T
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    ) h( s+ x2 P- r" Z- h8 R% X
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)# u- t$ |+ a: h' m  @
  20.     {- F3 E) D* r+ q7 G/ O8 v
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;- f6 `( i' O, ?: h9 f5 b# a3 F- Q7 w$ K
  22.     }
    9 X' m- I5 ^& j4 y: l% B+ h1 ~$ ?! k
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);
    6 q7 Q* o: k' N+ v6 J* q7 b, l
  24. #else
    * F7 w/ F: ^$ Z1 [8 _
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
    4 U/ P5 [! f4 J1 K8 t: w4 [
  26. #endif
    9 V1 z! F* P, o$ y& I* |
  27.   }                                                                         5 j( j3 Y8 c# f6 m! a/ f
  28. #endif6 Q. z: i* o, C; j% Q

  29. . j0 ]2 ^4 F8 @% O8 w& [
  30.   /* 关闭SD卡电源 */
    # }! H9 d( b" M2 ]$ J3 u- `
  31.   SD_PowerOFF(hsd);
    2 u. A; r. P( G* r5 Q2 b2 F8 w
  32. ( q& o1 o1 X! U" H1 N% O: `2 n
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)4 O$ R7 i" M) K) C) @/ R9 K# P1 ]
  34.   if(hsd->MspDeInitCallback == NULL)7 }# O% t3 H; o
  35.   {
    3 e& d' b% s: Y) d# d- A
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;! D5 j. J. N- @
  37.   }
    % y9 T, ]& i! {/ v' P) t% Z+ ~( |

  38. 5 Z. U. y2 f4 r" A( \
  39.   /* 复位底层硬件 */
      ]0 I# T, K. [1 q# |# A
  40.   hsd->MspDeInitCallback(hsd);6 C( C3 X* ]* S: m9 T  y
  41. #else' S. f8 g1 R2 M; r0 W1 g
  42.   /* 复位底层硬件 */7 Z3 Y7 u$ m0 t6 X3 Z; r' H" a
  43.   HAL_SD_MspDeInit(hsd);( d$ p( B- g# V1 q! l! u4 D
  44. #endif / L+ x' T4 f- I$ H, E% }3 h+ Q

  45. 7 S7 g5 c& \% |1 i6 H2 u$ @0 x
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    # @3 ~: ~2 S+ r  N( B
  47.   hsd->State = HAL_SD_STATE_RESET;
    * Z8 x6 B6 e7 [2 ^5 M
  48. 0 d" c8 e4 O6 N1 e
  49.   return HAL_OK;/ T: J5 L& j7 R. e1 Y& i
  50. }
复制代码

( G) y3 {, Z* K1 t函数描述:4 s2 L- u. \; a5 U' u5 y# \

- B2 c9 L; k4 T用于复位SD总线初始化。
5 D, U+ j# Z8 c* O$ c) y, s/ K! e0 H: T6 T2 l+ Q3 t- g
函数参数:
+ G2 m& F5 M  G; r1 G2 A+ P
7 o2 R. t" D8 \0 s7 F 第1个参数是SD_HandleTypeDef类型结构体指针变量。* a1 O9 ~; c7 Z# `
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。" ~4 |: A5 o8 M( c9 g0 _

9 J8 \+ R3 Q+ S# e3 z87.4.3 函数HAL_SD_ReadBlocks  t0 h: o$ ^" ]# k9 T8 X7 u
函数原型:
! a& {4 i; m) c8 x3 L! K9 t
1 ^* ]! n' y, Q. w
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)+ F/ Z2 u- P# D/ h  ^/ m9 p7 |
  2. {; @7 l* x3 A7 o+ [) }, i
  3.   SDMMC_DataInitTypeDef config;
    & B3 b8 p/ |9 e% m  S
  4.   uint32_t errorstate;
    9 c3 S4 ]# x( s; h3 S, [  M0 _
  5.   uint32_t tickstart = HAL_GetTick();. m& Z# m! \4 |; q, d7 e
  6.   uint32_t count, data, dataremaining;
    ; c: W% Z% w4 N1 e& T& ]
  7.   uint32_t add = BlockAdd;
    % N; r& o2 c, f, Z7 m) ?+ E! p" X
  8.   uint8_t *tempbuff = pData;
    5 D, W/ z4 K! r1 h
  9. ; H0 k4 O' h, g1 R, Y0 i
  10.   if(NULL == pData)
    / |  L' m% r& E) ^3 z
  11.   {
    3 j* m& j, X  d7 n
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    8 j8 o7 z! J. C; o
  13.     return HAL_ERROR;$ w. n; g( J" _' i9 Q
  14.   }7 b& P# ]- J- ~2 X. |
  15. 3 i2 S3 Y2 Q1 P/ G/ S$ ^: w
  16.   if(hsd->State == HAL_SD_STATE_READY)% D6 a; A/ ^+ H  Z
  17.   {# l2 T+ T" P" p4 h' p9 I; |9 B3 {! A
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    3 g9 G0 M% T& V7 t- Y( }( _

  19. ! c  U; f7 G4 o2 x  J: X$ Y
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    # `% h% m0 t2 T" {1 K
  21.     {" x5 N6 A( s4 k/ o' U2 Z
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;$ S1 B( z, |; K& m$ g3 V* L
  23.       return HAL_ERROR;7 m3 v6 N! Q8 D9 |
  24.     }
    # L" C$ i% q8 ?! u( q! W

  25. 4 |# Z# Y+ T. k& w4 O8 q# l7 z
  26.     hsd->State = HAL_SD_STATE_BUSY;
    # `. M2 w8 ~' `

  27. 0 K" [9 }! \( {- u* ~0 X: s
  28.     /* 初始化数据控制寄存器 */
    " U1 |; Z! k3 i3 v! P2 J* i
  29.     hsd->Instance->DCTRL = 0U;& A' E: `6 K0 h0 K2 Q
  30. ' F8 M! I" K2 A9 g" V
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    7 r. J: C$ m( A3 A4 e% l
  32.     {
      w* x* W9 A, F9 r: r0 W! R
  33.       add *= 512U;
      g. G7 \2 K3 B; w& W
  34.     }4 `3 l1 x) C  R6 F3 I8 h  F

  35. 6 U0 Q9 C% D  |& J! o. G0 ^" p
  36.     /* 配置SD DPSM (Data Path State Machine) */
    ) c4 T2 P; v6 e4 I8 G# `
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;" J  U, D3 a1 {. n* ~
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    0 M* r+ ]! B3 _1 _, s. o2 C
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;$ ?5 D3 j: M  Z, M: t/ \7 ]/ L- E0 D) u
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;8 H9 Z: U! C% O5 O7 @2 _/ j
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    $ ~1 S  e/ w/ k4 w+ @! {
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;. \0 `- b7 S1 c5 l! |! s
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);3 D$ Y; P# }( \; X2 _0 L; {
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    6 R1 x! K! w8 D. k8 ~5 E$ d/ ^8 Z
  45. 9 d' R  F  H8 a+ ]) e& X2 v: _/ O' b
  46.     /* 查询方式块读取 */
    & N: y# h& P. ?, \; k2 V6 f5 Y- t
  47.     if(NumberOfBlocks > 1U)% B" X- R- f' e7 b) i# L; D
  48.     {
      a. [( q1 c8 L( v9 g3 h: X2 k5 Q
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
    5 P. @/ K6 t/ q% o: S# t4 F7 O

  50. ( O* U( Y$ _. s; h4 x8 j9 j  \# _
  51.       /* 多块读取命令 */
    ; w+ j, Y9 X* h/ J; e! {4 V
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    5 A- H% ~- A1 l5 F) @5 }2 Z0 B
  53.     }. O# l8 m. _: {! A1 @
  54.     else
    , A1 r& r' \; T  P
  55.     {' I# v( N6 p* I
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;! h& m, \9 D% j- s# T
  57. - d4 Q" i0 K7 I  E
  58.       /* 单块读取命令 */
    1 g3 f8 q1 |. h( o4 K9 P6 ^
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    1 l" {0 t& {- _9 _
  60.     }
    / J, t- f; v4 D; K  K* R1 J- }6 C" J, s3 d
  61.     if(errorstate != HAL_SD_ERROR_NONE)! r: D& f9 V$ e6 l- e% n
  62.     {
    . l8 o4 V, P7 m$ z; x8 ^0 J
  63.       /* 清除所有静态标志 */" s& b4 C/ M: N
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ' ^8 p& N9 W: ~; {
  65.       hsd->ErrorCode |= errorstate;
    ) y/ |3 ]! w/ V% s, ^
  66.       hsd->State = HAL_SD_STATE_READY;
    . a% o6 K5 \% a* `, D* S  j  I9 Z- F
  67.       hsd->Context = SD_CONTEXT_NONE;, \( |1 Y" q# ^% o
  68.       return HAL_ERROR;
    : y4 M- Z4 e! A( ?, l3 o
  69.     }
    ) F; q% _+ {+ G

  70. ; m- `9 g0 K# P" w1 f% k
  71.     /* 查询SDMMC标志 */$ t* D# f6 E9 X7 x% j
  72.     dataremaining = config.DataLength;. h2 z+ @1 d9 K' ?
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    5 [5 V8 J) Q" j9 n0 j
  74.     {8 f# N) L7 E; }% a. L
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    4 ]( u; u$ R8 Q  D8 u* J
  76.       {( h4 }" _4 u1 ?$ c6 r% V8 \
  77.         /* 从SDMMC Rx FIFO读取数据 */6 N% n$ E: a9 X8 X! C+ a6 Q
  78.         for(count = 0U; count < 8U; count++)7 S- q+ \- x6 l& n3 z
  79.         {
    4 j4 ?. {3 I* Y; R& \& G
  80.           data = SDMMC_ReadFIFO(hsd->Instance);
    ; G$ w! J" I4 P( |7 ]; N
  81.           *tempbuff = (uint8_t)(data & 0xFFU);
    7 e1 l0 Q) n! W" J
  82.           tempbuff++;
    6 J4 y3 @! x- [2 ]5 O) ?
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
    : m% N) m9 n: ?( [: W
  84.           tempbuff++;5 |( v  A) H4 \* z6 o
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    4 s: v" M6 A8 K% s. E0 x
  86.           tempbuff++;) F4 }7 k) _/ q8 x/ o: ]& j
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
    2 Z  E* V+ k* `$ ~: u4 o# E
  88.           tempbuff++;9 m5 c7 p9 m9 a/ G" x
  89.         }
    ; _; m1 ]9 M+ p
  90.         dataremaining -= 32U;+ ?# y4 O: c  j" {- p7 W0 Z4 s  Y8 e
  91.       }7 e: m& `) f" s& @2 N

  92. 3 x/ i  \5 }1 z: g& N2 [$ t
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    " A2 Q  z: L& W' w
  94.       {! r& E1 K5 [: y. N6 G
  95.         /* 清除所有静态标志 */
    2 N1 a' H0 P! a) W6 u
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);- |& T" ^. G, }7 q9 }5 @1 k
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;2 U6 d' V6 G$ A
  98.         hsd->State= HAL_SD_STATE_READY;8 }2 ], _; J6 @- z/ N# F
  99.         hsd->Context = SD_CONTEXT_NONE;
    - ?# d, L  q6 c
  100.         return HAL_TIMEOUT;( B; _! p6 O9 G. R( M4 E
  101.       }3 I& q6 x  p9 u7 d
  102.     }% U, G( N. ~: k4 N' V# B' w( w7 `
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);' D3 O; f: y& \4 F

  104.   Z; [! f+ y7 A- y) @; W$ F. x
  105.     /* 多块读取发送停止传输命令 */6 u% `6 U) C' Q1 S; U! P3 J8 [
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))0 E4 y; b3 W5 L& h
  107.     {
    ! _4 s+ D$ q3 ]  s' Y6 w, G1 [9 ~
  108.       if(hsd->SdCard.CardType != CARD_SECURED)
    5 z) q- H$ u- l4 L7 _( ]
  109.       {
    8 u9 g* l' }) O
  110.         /* 发送停止传输命令 */
    : M- ?% M& B" I7 K. K" X! B& O- ?$ {
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    1 B6 e: f5 J$ R) @1 v# u
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    9 {& M: c! J$ W* L# c; E6 K
  113.         {( ^# w) G, d* G& f: v% O& D6 }
  114.           /* 清除所有静态标志 */
    $ d, _: r- R% X
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);# r- e& l/ E5 _7 N) A2 Z
  116.           hsd->ErrorCode |= errorstate;
    4 Z; b/ ]. X' E& x+ R( V8 z8 Y4 a
  117.           hsd->State = HAL_SD_STATE_READY;) A( _# }# U  o, p( Q& ]
  118.           hsd->Context = SD_CONTEXT_NONE;
    / O0 `2 n9 Y2 L# G
  119.           return HAL_ERROR;/ v8 P* ?9 }" R2 [1 D
  120.         }+ H; _4 x( E4 J( Q+ ^0 p
  121.       }
    ; V3 s6 V! u1 k( c) M7 i$ S
  122.     }
    * h0 M7 @2 f8 t

  123. , R* x0 s- S$ ~* F" d
  124.     /* 获取错误状态 *// V! S- F9 i" ]  \9 Q" D
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))9 V2 `/ c3 _* X$ ^2 D8 g9 e0 {+ B
  126.     {: w2 Y2 J. l/ V1 S+ o
  127.       /* 清除所有静态标志 */% Q  [: ^5 K* v  L: G$ o' Z9 s! ~
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    * x% ^1 d+ V; ^9 F
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;- U5 v) Y7 K4 R" |
  130.       hsd->State = HAL_SD_STATE_READY;
    / C2 s, z# q) ~: s, r( g. E
  131.       hsd->Context = SD_CONTEXT_NONE;
    * X0 `* N$ }# j
  132.       return HAL_ERROR;
    / C; n* T6 d  T' z) h+ E5 M, ?
  133.     }
    3 k. a6 g% l" z% K$ C' H
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    - S5 `! x1 X) N) C
  135.     {& R5 {* C- @) z8 B
  136.       /* 清除所有静态标志 */7 R2 F/ c5 n8 o; q' V3 V& T
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    + M/ D9 T+ o. U( E3 b; s8 @) q
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    5 B7 e& B9 h- h: {2 {& N: C! @
  139.       hsd->State = HAL_SD_STATE_READY;
    8 ?! _: D3 Q) V! u
  140.       hsd->Context = SD_CONTEXT_NONE;9 M) D/ _) P; g, e
  141.       return HAL_ERROR;& o  c( L4 A# X" Q/ z) v& S- C
  142.     }" R/ Q* O0 N- _! p/ Q; j6 _
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    ) L" j6 i. b* Z) M; r" x8 I, x
  144.     {
    % g! M, r' d. R4 B/ S
  145.       /* 清除所有静态标志 */
    & \+ F( W3 W5 e
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ A) x; h7 W8 o4 K
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;9 e$ w9 }/ _- z. E
  148.       hsd->State = HAL_SD_STATE_READY;- r  f. \& d# q3 ~: Y/ k
  149.       hsd->Context = SD_CONTEXT_NONE;
    - \! z7 \2 U# _1 ~1 h. k$ g; l- @0 N
  150.       return HAL_ERROR;
    / C: @8 X& H/ _' i$ h  p
  151.     }
    & u& ^$ r; |) V/ n
  152.     else3 M( u* y% U, o/ ~
  153.     {
    % w+ ~# T# f( @; p7 e) x" `, z
  154.       /* 什么都不做 */5 q# h% h$ v( H. T9 Q
  155.     }
      P. q: n& n, u1 A
  156. ) V% C- \% h* j! j# k: E; m
  157.     /* 清除所有静态标志 */
    # k4 T2 Q  G- ~) \% O& Z$ U
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    ) b: J2 Q. Y- X$ }. P, @
  159. % D; O- n! h# @  u1 D
  160.     hsd->State = HAL_SD_STATE_READY;( Q$ B' g7 [1 B3 B2 n4 ~
  161. 5 h1 e0 r% q* R
  162.     return HAL_OK;9 j! x6 }9 v% v
  163.   }) u6 ?" q& [6 C. o2 h4 ~' e
  164.   else
    * V8 D* F. N( g# d! p& P6 d
  165.   {
      R+ K0 w0 k, `; l
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;, w3 ?: [* L1 M& Z7 \4 n3 N* N
  167.     return HAL_ERROR;
    4 I9 j  m- E4 z/ W( c- U/ @4 n
  168.   }
    # Q2 F9 q4 ?9 P4 m( R: G0 ]
  169. }
复制代码

3 g" @+ m8 A+ x6 _4 Q函数描述:5 d! S- a! X: j( n: P
: Y- f: Q! T' j$ [+ i$ f, H
此函数主要用于SD卡数据读取。& p: K$ L# }1 O5 o3 @' E; v

) R. k- g4 u3 e* D) v- i函数参数:
1 u8 d4 @3 p6 a: t" R! ^! l8 f' U1 V& b9 @. V" u
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
: [5 z; ]+ m! m6 p: W# e: e  第2个参数是接收数据的缓冲地址。* K; S) E3 x/ B$ y+ G) e
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。# H( h% a. G" v; v
  第4个参数是读取的扇区数。
; X( T2 a1 Y* M! n  ]/ v) X  第5个参数是传输过程的溢出时间,单位ms。: s! k/ u0 ^8 t& J! ^
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
3 y- J  S0 S1 n9 j7 _/ r! E( S2 C6 x
; [  g: n( U% w
使用举例:2 c. x: E7 b) J+ ]3 s" z$ a# V2 o

  y6 ~, v' C$ p0 C8 x
  1. /**9 }* `; S9 t/ m6 v- p
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.8 O8 J" b$ e- q7 P0 R
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit( @; x3 h3 S# p5 |. U& w
  4.   * @param  ReadAddr: Address from where data is to be read+ z& d) u' b, `9 P1 W  o
  5.   * @param  NumOfBlocks: Number of SD blocks to read# d/ y- n9 a' N+ x) [! P: B
  6.   * @param  Timeout: Timeout for read operation, k6 Z& i3 z7 A2 Q- X& i. W
  7.   * @retval SD status
    4 Y7 A+ h/ h9 L" Q) q& Z
  8.   */
    5 j- \% ^- v$ S, Q: T
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    , [0 L4 t- }$ Q' w8 r: I0 o4 \3 ~1 q2 J
  10. {
    / o4 l$ p1 `. ?$ E
  11. * ?& y; K, V2 u; x
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK); p4 v4 p* }7 Z) \8 B  i1 @) x
  13.   {6 E' A' q# @, V/ E9 H8 p
  14.     return MSD_OK;
    . N( b  N% O; v4 t0 X& f2 ]0 H
  15.   }" P0 [" O2 i- s: w  x6 K0 v
  16.   else8 S# T6 B) ^2 I! M9 Z/ c. s6 @" k
  17.   {
    8 e9 l; {8 S+ b, x6 e. U; C& D6 d
  18.     return MSD_ERROR;
    : B) {) @; x1 N3 h
  19.   }! ?" R1 n& T- w1 M

  20. , W6 s, P+ ]& p- d1 \4 W5 M
  21. }
复制代码

' i2 u  b4 v" g3 X87.4.4 函数HAL_SD_WriteBlocks/ {$ t8 q2 l7 ^. j$ h
函数原型:
" p' P; |# A. E3 p9 ^" w0 S5 s
0 X' \: s6 q8 d, J) q
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)% A& v" I1 O- O, I9 Q
  2. {, Z* k) x' o) c
  3.   SDMMC_DataInitTypeDef config;
    6 l5 i- \2 B& e4 q1 i& z; O# _' h
  4.   uint32_t errorstate;$ _$ F1 b0 P$ {3 C  X5 g( L
  5.   uint32_t tickstart = HAL_GetTick();
    ! R' e9 i# q+ ]+ ~! j! B5 H6 w* @
  6.   uint32_t count, data, dataremaining;
    . D8 T' t. Q8 N6 n% P" }9 d
  7.   uint32_t add = BlockAdd;" w% A% Q/ n, y0 F( v
  8.   uint8_t *tempbuff = pData;
    6 M, p' f( V. k( A5 D
  9. 2 o6 n5 [0 m2 B* R4 D
  10.   if(NULL == pData)
    , F/ i- c: v( }
  11.   {* Y3 z2 P- A" B8 f0 C
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;4 R/ i* I! f1 W6 @! P+ W- A
  13.     return HAL_ERROR;
    8 h* t$ ^% c6 N7 C
  14.   }; ~) i8 q" H: s; j' ^
  15. 0 C! d! A  I4 f; g  L
  16.   if(hsd->State == HAL_SD_STATE_READY)* `8 z: T6 H9 W: F5 i. t
  17.   {" r5 S( v& r9 y+ r; ^/ X: N
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;3 q1 E  j3 K/ U% f

  19. & \: N% s+ ^8 W9 j3 G& k
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))/ `' U% n" ~7 `4 H
  21.     {6 r) m, N2 i  N! l
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;4 y9 Y' j3 J& Z8 v9 M' Y3 n% r  M) R6 x) N
  23.       return HAL_ERROR;
    ) }( H- A, l0 I: s$ h
  24.     }( I& \0 E3 ^' J) i+ r/ A7 W$ U
  25. ) R9 U) G5 v4 `. {8 B0 L
  26.     hsd->State = HAL_SD_STATE_BUSY;; P2 w5 b9 `2 n3 M+ |: X4 G
  27. & |) s$ A; H9 N9 Q  x3 A- Y+ t
  28.     /* 初始化数据控制寄存器 *// t4 u4 l8 s) ~. i; k
  29.     hsd->Instance->DCTRL = 0U;
    & D$ d: q. b# L5 C5 w+ J" L8 |
  30. ' C) t4 ]6 A6 N/ M  B9 p5 {0 b
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)1 a# B, E( B+ V0 r, P: {
  32.     {% B8 ^0 p' w0 ~7 N
  33.       add *= 512U;5 H, b) J$ E" d: M
  34.     }; c0 M9 h& Z% i5 |$ g' k6 ?5 L
  35. + o, Z6 ~5 V5 r8 B
  36.     /* 配置SD DPSM */; J& X4 B# r5 Q
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    2 ?/ s. l; c. e# m, O7 n$ O
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;# ^8 F+ R- p, m/ W3 D
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;4 z; V7 X$ y! |
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    7 Q4 s" j  X, H% {$ y% d5 ]: N
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;$ q' z5 Q2 M0 A; k; t+ I
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    + ^7 B/ @" v; @+ K' z9 [( b
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    * e9 w/ f0 S; o$ y6 P7 G
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
      l" k6 ~' t4 B, K+ x5 |
  45. - ]! _  f) L# b; C& g' ?( v
  46.     /* 查询方式块写操作 */- G: ?* M6 T: k/ B
  47.     if(NumberOfBlocks > 1U); w# u0 s* s! i
  48.     {& `- t! S: m$ P3 i; i
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;6 b1 F- p" ~( t: ?$ `2 G$ j
  50. 5 E/ t1 s/ x' M% \& a
  51.       /* 写多块命令 */
    0 |0 P3 ?8 W( R, z; F$ d" t  N
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    ' [6 {( @# e7 p: h* T: `
  53.     }, r3 v1 l! @  X) D7 S7 F) U$ x
  54.     else8 a" u: l' C) Q" i1 x
  55.     {# s' B3 p2 Q, p4 Q% z3 M
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    - ?9 d' |' j) c* K2 H; G! r

  57. 4 O2 x3 \) ^) R6 D
  58.       /* 写单块命令 */" `# h- x- s# b* T
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);$ K% B* k. B# z& y
  60.     }
    , K1 p0 D. z3 H' H
  61.     if(errorstate != HAL_SD_ERROR_NONE)6 p9 Y2 p" |) H, T8 R. q
  62.     {# w4 D4 U6 t+ u. x) t
  63.       /* 清除所有静态命令 */
    7 s8 O9 T- y) K! L
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; V" }4 b1 F  R8 D! G0 M+ `
  65.       hsd->ErrorCode |= errorstate;
      z8 S3 ~# @! P) d% y; K
  66.       hsd->State = HAL_SD_STATE_READY;$ k: ^4 w8 E# @* ]$ r
  67.       hsd->Context = SD_CONTEXT_NONE;3 |. E( g; F( u" X9 d
  68.       return HAL_ERROR;
    0 a+ ^5 @% H; ^. p  [
  69.     }1 L4 ?, n7 P8 d+ ]/ b

  70. + {4 z, T$ V5 ]1 l6 y' y
  71.     /* 查询方式块写操作 */
    3 e7 q) B$ j' s% n3 C
  72.     dataremaining = config.DataLength;
    ! S! w+ o% L8 C: _6 E" s
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))0 n: M% c9 {1 A3 a) u" H) @6 }
  74.     {; R' |; H& m, D- Q0 N9 |- q- f; ~
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U)); }6 K4 x. t0 U1 ]. ]) O
  76.       {
    ; @9 X. d  G1 Z* j2 D" w- D8 q
  77.         /* 写数据到SDMMC Tx FIFO */
    3 F# M0 n( `  x5 a
  78.         for(count = 0U; count < 8U; count++)
    ) F& q9 W% @8 Q) M  J4 ?
  79.         {
    9 h, ^% H) O  Q+ E+ k* X
  80.           data = (uint32_t)(*tempbuff);2 `) d) G7 h; t$ u
  81.           tempbuff++;
    3 `- N; c3 N5 r5 n4 S/ T4 A/ \
  82.           data |= ((uint32_t)(*tempbuff) << 8U);
    $ W% X  ~. |- W5 f
  83.           tempbuff++;3 B0 ]# H# b: r& J' ^
  84.           data |= ((uint32_t)(*tempbuff) << 16U);  `7 A' u$ x- j  f* G
  85.           tempbuff++;3 }: ~( o1 Z4 U# y% N
  86.           data |= ((uint32_t)(*tempbuff) << 24U);7 d! l2 z; a- X0 _# Y9 _
  87.           tempbuff++;
    + Y7 j7 f4 A- g6 x
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);; ^" w. R# e2 U+ P% m
  89.         }
    9 g- x! A+ s3 v
  90.         dataremaining -= 32U;
    $ b1 N  O$ f. T+ d
  91.       }
    9 X: p$ y9 v5 e. S, \9 |

  92. / z; I2 W5 ]5 E# Z& o7 ^
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))1 r0 n+ |6 Z, R" g
  94.       {$ s3 U: x$ O) y; }$ O
  95.         /* 清除所有静态标志 */
      [( g& B5 L( P: o
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ' J, H; }+ L! q/ {5 {4 f: U
  97.         hsd->ErrorCode |= errorstate;- l; ~! Y# ~. S5 n
  98.         hsd->State = HAL_SD_STATE_READY;' W5 ]# }$ D3 N7 U9 N' i
  99.         hsd->Context = SD_CONTEXT_NONE;
    6 d. H3 Q3 |! U8 J
  100.         return HAL_TIMEOUT;
    ; q$ b$ t: T4 V" H0 f) B' v
  101.       }; p8 {2 [) l+ Z9 d
  102.     }
    . _) N% m  Q, u' [1 C
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);1 l( A1 m8 ^8 f( o: z* A

  104. 1 T; h4 n$ z2 Z4 {
  105.     /* 多块写操作,发送停止传输命令 */" D* O7 Y6 P1 L) I1 m
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U)); }" y* l0 l% d& B; ~- g) o# n5 K
  107.     {
    & w3 \& L+ ^) o: T, q
  108.       if(hsd->SdCard.CardType != CARD_SECURED)( M, w/ o, a4 e( L& u% @4 k, {
  109.       {9 r% i; b" C% z6 y# h+ b
  110.         /* 发送停止传输命令 */: V0 N, \( ?7 q$ l! U6 \  L0 w" `- E
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);9 W8 L$ ?5 u" l4 h. X
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    . R1 N5 V! ]8 b5 w" Z4 x$ k
  113.         {
    6 L2 c2 w! K5 O, P  e3 C# \2 ^' p
  114.           /* 清除所有静态传输标志 */
    0 h' g' O' s" N, I( a  t: u2 j, y' T
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);+ |. q% E; L, o( D  d
  116.           hsd->ErrorCode |= errorstate;3 s0 T" f4 e0 M, F# L" P
  117.           hsd->State = HAL_SD_STATE_READY;
      A" H/ ]& C. s; e! T; Z4 G
  118.           hsd->Context = SD_CONTEXT_NONE;9 Y. i" u1 P2 Z* U4 @
  119.           return HAL_ERROR;' V! s! m- Y8 k3 ~9 n
  120.         }* e4 s& s  f! y4 R+ F( b4 g4 A, r
  121.       }" _+ w/ }: Z7 _: f3 _
  122.     }0 n3 j3 D3 C5 [

  123. ) F; ]- t% _+ J( }
  124.     /* Get error state */
    9 l; i2 [+ a3 v
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))+ r3 G0 L. P" Y* d6 F0 V
  126.     {" Y8 Q, w% _' L: s0 K
  127.       /* 清除所有静态传输标志 */3 W3 ~6 d2 X- `# g* b
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" V% p0 K- d4 b8 S
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    , w/ u/ B& f& e$ ]4 E! A4 `/ x9 [
  130.       hsd->State = HAL_SD_STATE_READY;
    1 Z6 j, C+ P' \, J8 S( j
  131.       hsd->Context = SD_CONTEXT_NONE;
    % D0 X6 \* z! I! S' a  a. B
  132.       return HAL_ERROR;
    - a- ]9 S+ ]% i9 ^$ H$ U
  133.     }+ |! @* z+ d/ J2 I# ~/ E3 A
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL)), E# I3 T5 w0 D+ U4 V; A3 L9 t, n
  135.     {
    / R. K# }4 y: C3 U! y: A
  136.       /* 清除所有静态传输标志 */& _/ X/ w) M, k5 T6 x
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    + V5 n$ ]! O3 m8 T8 O; A) M
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    * ~6 m6 b- L; b! J- [
  139.       hsd->State = HAL_SD_STATE_READY;
    ; ~1 X3 k0 T, ]9 E4 c/ U) D3 ]. x
  140.       hsd->Context = SD_CONTEXT_NONE;
      p. f: [$ n! m8 K7 E
  141.       return HAL_ERROR;
    # X3 }2 U" g, R. A) u
  142.     }
    ! C' L' q+ P3 a( {5 G0 R
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    $ o7 X1 D7 j3 w+ X" ]
  144.     {! S8 t5 v4 C: ?4 b; l
  145.       /* 清除所有静态传输标志 */8 ]& h$ L( y) I  _6 r
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    2 O2 p7 f2 I5 @, p) D4 p
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;/ ?! f. A" v" c& e8 t
  148.       hsd->State = HAL_SD_STATE_READY;
    1 E9 }% K  N- B( N( y
  149.       hsd->Context = SD_CONTEXT_NONE;; z+ |' V8 E; F( ^
  150.       return HAL_ERROR;
    3 d/ H  k7 ]: b
  151.     }" t9 Z, r6 ?- r( V# C% z+ N" U
  152.     else
    * m  x4 M9 [3 |; {/ E5 N' R" v
  153.     {
    5 j- ]8 u: b, s3 C, O5 B7 h6 L
  154.       /* 什么都不做 */- c+ G2 N1 l" ]4 V0 O/ t- D. B( O, S
  155.     }" ?, s5 d& F# G* P7 e6 D, q" f. @

  156. % l) h, @' T& _; T+ W
  157.       /* 清除所有静态传输标志 */1 E$ P- q, b& ?5 _  K) I
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);/ _0 p/ r. c; l- E0 U
  159. 1 K& _) f  z, N- i
  160.     hsd->State = HAL_SD_STATE_READY;! C( u3 e7 F; V  Z( M+ c
  161. ) T% g( E/ x1 W: A
  162.     return HAL_OK;9 [0 \) }4 h. \4 P4 \
  163.   }
    # W- B  s( k: @0 z% ^' K( M
  164.   else' E4 W8 [; c3 A* P% J* _
  165.   {0 J$ U& E) i: S& T' V) e% Z
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    6 x, V. ^/ e+ f
  167.     return HAL_ERROR;
    3 f; T% B/ G/ w& r, W# z
  168.   }& p5 T# y# d0 V% y! {7 q" v1 o( _
  169. }
复制代码

! f* v* b6 x- ^3 a3 D2 w* K# j' ~函数描述:8 n+ F: E' o1 v$ }, k: B* i% e" L
  P; _7 d4 d. Q( F* W$ x7 y& Y; U
此函数主要用于向SD卡写入数据。; u1 e8 n9 f& q8 J

2 X+ W) P0 z- L  R) c( w6 A( y2 |函数参数:" G7 V1 z, u$ n) Q3 H

$ X( i& t- Z5 H1 x" y# E( A) T  第1个参数是SD_HandleTypeDef类型结构体指针变量。
+ _1 ?! Z5 E+ V$ U  第2个参数是要写入到SD卡的数据缓冲地址。2 g, M- |8 R  p) j  R3 F
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
6 B) D. a$ d6 `1 k  第4个参数是读取的扇区数。& b4 V9 M* s2 e$ `) D% w
  第5个参数是传输过程的溢出时间,单位ms。  I% }, D0 ?9 F$ Y% u
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。& S, E: p/ D! w  x. L0 H! Y

) W; v; n% i) T
. G' Y4 v4 K% z% P使用举例:" T0 Z8 H2 y& P

# m! i. w' z" m1 H
  1. /**
    8 x3 f1 D6 _9 Z
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.
    - |; M4 C- V' L" ?2 i1 d. v
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    2 D7 z" b3 X* @* b  n$ v
  4.   * @param  WriteAddr: Address from where data is to be written
    ( k% a& s" I2 }6 G/ e
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    ' M. X; y! p( ~& P% j% j
  6.   * @param  Timeout: Timeout for write operation
    ; p! ], M+ L# b' e; ?
  7.   * @retval SD status
    1 y4 k9 o* X/ N5 m
  8.   */
    ; q5 u8 p% g3 r5 d0 B  o
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    / n9 _5 P# \+ H* ~" G& o! h
  10. {
    & V- t/ a* y8 e

  11. 2 j( l. p8 |! W- L0 p4 K
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
    $ u9 b, _. q* Q
  13.   {
    1 o7 y; ?7 |7 h' A
  14.     return MSD_OK;
    0 M# A" E6 {- Z, s8 ?6 Q# T2 n" Y
  15.   }/ f- W' z8 x. U9 V/ \% l
  16.   else
    2 K9 T/ Y4 W9 F- O# s" p
  17.   {! L& h& x) H. f5 J1 |
  18.     return MSD_ERROR;
    + z  ]4 W* V, B- f6 x" ~+ e
  19.   }
    % x. k9 Q. K3 _1 Y6 F, o0 m- v
  20. }
复制代码
  r) x$ K; R7 s8 v7 h) g
87.4.5 函数HAL_SD_ReadBlocks_DMA
8 G. o0 G8 M( v
函数原型:0 R( E. L9 C8 k' s3 C

$ D% A  D2 W0 M* Y6 l+ C
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)4 o  T% ?5 m% W  l8 |+ N
  2. {
    : C: G5 B  M  ?$ b! s7 h
  3.   SDMMC_DataInitTypeDef config;
    # a* i4 R) G* J1 o& W7 H3 ~, O( S9 i7 W
  4.   uint32_t errorstate;
    2 G+ ]3 n5 X5 M! J
  5.   uint32_t add = BlockAdd;3 V3 ^2 B. E& j5 M& [! @% r4 F6 Z
  6. 9 {  q' T% J6 ~/ k
  7.   if(NULL == pData)
    ) C0 [2 C. M) ~- Q
  8.   {" L1 E) M+ S2 g; [4 p
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    0 T1 i0 T$ Z: O
  10.     return HAL_ERROR;  F, U) K" V! ^
  11.   }) i  h  B4 Y/ ^8 N# j
  12. % N. ]% P' n1 i. \
  13.   if(hsd->State == HAL_SD_STATE_READY)
      p) P+ i; d* g8 }0 n3 S0 i# f0 d
  14.   {) n7 q8 o% ~, q; x1 Q
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    2 p  m$ I8 A1 w# E
  16. $ q8 J8 i. {4 S- b: ^5 b
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))/ B$ `$ ]. a' ^% n& W
  18.     {
      y1 r  p3 E5 |* b: s" Y3 J
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;6 J# W" u% B" U) [0 r
  20.       return HAL_ERROR;: F1 G9 a1 W# ]3 B6 {" u
  21.     }' Y- t6 P2 w+ J' Q8 M* C* T! b% O& @
  22. 8 y5 X6 f/ u  R, v3 s9 N' U
  23.     hsd->State = HAL_SD_STATE_BUSY;
    $ H+ f2 d7 A; r8 }. A9 f1 H

  24. ( k  h1 U; |) E% a/ Z# A
  25.   /* 初始化数据控制寄存器 */
    ' s! H  b9 g$ b: s
  26.     hsd->Instance->DCTRL = 0U;8 C, ], a% D) e2 X3 h( h
  27. $ x1 v3 V- O1 J; m* {
  28.     hsd->pRxBuffPtr = pData;& }& r3 g. ?/ I3 F/ {$ K1 B
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    5 F9 z: c% T% R$ c) Q2 R8 V7 K9 P

  30. 7 A( {0 \1 f/ O
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
      S2 B! `$ n* c1 |! b" t0 H
  32.     {) A: B9 S& s+ w0 H/ p) Z. e- z
  33.       add *= 512U;
    2 [' u* b7 s- s4 A
  34.     }  u1 Y/ E, p+ q! i

  35. + [* b6 m+ C/ a( g8 k
  36.   /* 配置SD DPSM (Data Path State Machine) */
    4 o' G7 k: x( \* A1 p4 E
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;5 a' u0 h; t1 l
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    + M% U3 D+ s2 v2 T) D) t5 ?
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    - G7 U: X1 w' K/ `( o& N
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;1 M1 n+ ~6 D! t1 I
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    9 v6 r' S4 N# l2 C
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;3 U4 n/ T4 U: [9 U
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);% U1 R6 \9 {( H/ I$ c& z! I8 A
  44. / J$ p9 Y* [: ^
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    5 o' }  H( z( v
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;8 L  N. t4 \/ G  N
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;  @: H4 y& k, h0 N
  48. 4 e  \6 v6 b4 f5 M6 n$ k3 Z$ h0 u) d
  49.   /* DMA方式读取多个块 */; u* g% C3 L( k
  50.     if(NumberOfBlocks > 1U)
    % m: h' q3 N( }
  51.     {
    $ H5 m8 Q) E6 r7 k& x8 L4 w. C9 C
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);( ~8 c* o8 s0 w" B

  53. ; V: p4 L! c$ H- k
  54.    /* DMA方式读取多块命令 */
      i, w! S* c5 w/ p
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);% y. ~, G" z# w9 o
  56.     }
    4 t! D# ]5 n0 M+ U9 k3 `) x; r
  57.     else: s: B) ?7 Y; q8 r+ j
  58.     {. p0 a  k. J6 w0 K) _3 e
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
    : C5 f! ~* y1 t. k. {8 i& h

  60. 6 b( W* m: W7 \! Z
  61.    /* 读取单块命令 */
    ( A( L9 y* q2 l- n) x& z2 s
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);2 |2 ?! }# y4 p! D2 F/ Q: |
  63.     }
    / M& y2 a9 v' V' u
  64.     if(errorstate != HAL_SD_ERROR_NONE)# |8 W' x% k# ?. H+ X+ ^( P2 q. c  U
  65.     {" E9 N  T1 L9 u1 c3 z/ F( K
  66.    /* 清除所有静态标志 */
    + n8 c' S2 w3 w/ `
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    : l1 j  `3 J- \! {. {# e: Z
  68.       hsd->ErrorCode |= errorstate;$ j6 e  i: _5 A* s1 Q
  69.       hsd->State = HAL_SD_STATE_READY;
    ' X+ ]+ y& c- F
  70.       hsd->Context = SD_CONTEXT_NONE;
    ' y, |- f: Y/ O1 Q4 T- F( A+ Z6 M
  71.       return HAL_ERROR;1 K7 K" w% k- r/ z
  72.     }1 U# |& s3 U* G: {" i3 `

  73. * H. e( d9 ?& w4 g6 w8 ^
  74.   /* 使能传输中断 */8 j% B5 l; O$ [* l1 p8 G# J
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    ! g  V1 I+ ^: Y
  76. " E7 Q7 \+ l, y* m- m

  77. 6 J8 D1 K9 K+ w: B1 ?+ o
  78.     return HAL_OK;$ ?3 d, _. _& d& [, K+ V
  79.   }
    5 Z$ E1 h# N: E
  80.   else
    # x5 s% C5 M  ~7 Q6 i- s% {( j
  81.   {$ C2 b7 [# H  Z/ A& ^  L
  82.     return HAL_BUSY;
    9 H& L+ {/ k8 V
  83.   }$ E0 }0 C( r2 A/ E: e7 u% z: Y
  84. }
复制代码

4 ?1 Z  E$ G' `! z7 _+ V函数描述:3 y' d! x0 ^# z! ?! i/ ~5 a

5 N, p# `- F& x* e2 Z4 Y此函数主要用于SD卡数据读取,DMA方式。
/ q. J, J( }$ W. v) O, B4 Z/ |- k0 O+ c- W( s# \
函数参数:8 k! ?2 C# T% u8 a
* [" R  Q4 F7 P# Z) r$ D, d' `
  第1个参数是SD_HandleTypeDef类型结构体指针变量。5 n4 H9 W9 g# ^- K# u, k
  第2个参数是接收数据的缓冲地址。) h0 z3 c$ l1 j$ `$ r8 b& I
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。5 H0 S9 W( S# \8 q* @' `
  第4个参数是读取的扇区数。; ]0 Z0 f- Q5 Q
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
& j& l  k: e# o: b" r1 e( \+ f% P# `8 f
: T3 O! d8 Y) D) F
使用举例:. f0 W6 U8 [( r2 z8 X

* o9 k) `& J' e. a
  1. /**# `2 I7 N9 O# |( d. a7 J
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.+ e) x6 f& p2 e- V6 b6 T8 d
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    3 B5 a: ^6 P5 s9 A+ r8 L
  4. * @param  ReadAddr: Address from where data is to be read6 c% c1 C6 I- d
  5. * @param  NumOfBlocks: Number of SD blocks to read
    * e4 y% {8 O- K2 V
  6. * @retval SD status
    * ?9 K% d# Z% Q3 g1 W' h  m6 A- Z
  7. */% L  J4 ~' c& H
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)+ |+ N9 s  t: H  d# k: |
  9. {
    4 P/ J+ w  w* c. K8 c% q

  10. 9 v/ ^$ G# n" M$ Q) R1 K0 B& ?- t$ @' O
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)3 c  a9 H9 R2 f
  12.   {
    : L4 r- I9 `* P! \5 u
  13.     return MSD_OK;! A+ X' H. G' X/ }2 C
  14.   }
    + ]. ~& l8 o8 a; b" G4 {
  15.   else
    7 T8 N7 h9 E3 I  Q# f
  16.   {+ {* c2 ]3 U6 S& G- p
  17.     return MSD_ERROR;
    6 ?& Y/ V, d* S4 _
  18.   }
    5 Z! ?( Z1 F% ]2 m8 w& r
  19. }
复制代码
3 u: D6 A% i9 H* V7 C% z
87.4.6 函数HAL_SD_WriteBlocks_DMA4 Q+ I/ m. ]- @0 T6 S; A8 k) V, E) x
函数原型:2 Q+ H0 H) X! |) u, S& A
% l$ j" G7 F4 P! U
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    # ~7 o5 q2 A5 x! ?
  2. {
    6 d  z6 \8 N0 i( B: P; ?) U1 u
  3.   SDMMC_DataInitTypeDef config;6 F% D8 u1 l, d- v( ~+ ]
  4.   uint32_t errorstate;
    2 E* y' o9 W: c8 P, m$ n8 A8 {
  5.   uint32_t add = BlockAdd;. _7 I/ U* S& e5 T8 m4 Q% o. g( A1 i
  6. $ v) t& {% u) M! k% K# J, Y3 X+ C
  7.   if(NULL == pData)! w3 L' T1 ^' g" [7 j- b, K
  8.   {" M4 A* @7 W0 B. w
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;' q/ Q1 J2 G7 [3 u- }1 C
  10.     return HAL_ERROR;
    1 P+ q) s) d- ^3 q, Z3 ]
  11.   }
    ! |! r- K0 i% {( g

  12. 8 y; v4 @7 Q# |$ N# ~. h
  13.   if(hsd->State == HAL_SD_STATE_READY)' M. @) n& S8 C; h; V
  14.   {
    9 ^9 T% J  T" {% z# p6 c, w
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    2 i( L: w3 p# r# {  S, z- A
  16. ( ~  j- H# l; _. p6 p7 l
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))/ u8 j) j' Y% N; x0 W
  18.     {. p+ n# D$ d  }* W% N
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    ' B/ {" f: A4 m( \0 I) V1 ^% n0 e
  20.       return HAL_ERROR;0 L' U" _2 h: @+ ]7 I2 b
  21.     }( }" E' V+ g  y' w1 q1 b- W
  22. 9 n3 h: Y3 z9 K1 }
  23.     hsd->State = HAL_SD_STATE_BUSY;% s) R8 c5 h& [5 |
  24. 9 }2 b  S8 g6 V# ?$ B: r
  25.   /* 初始化数据控制寄存器 */
    : y' ?5 q$ J  D8 ?: k3 j9 H9 S" y. e
  26.     hsd->Instance->DCTRL = 0U;3 {* ]9 l$ T1 [. G5 \

  27. 1 Q; P: Q# K) U
  28.     hsd->pTxBuffPtr = pData;
    0 I+ d* ^9 J8 J. E" h9 [7 A( I5 B
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;8 |2 ?( m4 r: G9 S" \/ ]; a0 Z  c
  30. ) ^7 ]7 t. o9 b, s
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)7 e$ \9 i; \/ L
  32.     {
    5 M1 n5 e& X9 I+ C8 s. Y5 J( s1 |
  33.       add *= 512U;7 N- n  C4 @( x# |1 c
  34.     }1 i  u* n1 O* G: h: ^* H

  35. - R% u8 i9 R, i. v7 h7 y: G6 g
  36.   /* 配置SD DPSM (Data Path State Machine) */
    5 Q7 S- l" [3 V& R4 I
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    3 s* T" e# p1 H6 L% Z
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;# Y- r" X( o; i* Q* x8 S: B$ h
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    & G; [6 X* n: u& d3 d3 _% d. P9 m  {
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    ! Q+ M7 O0 s# }% d- \  j$ l
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    ( k1 E: d4 j4 r* T" p1 X( f9 l: T
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    6 f; ?" O2 ?2 j9 ~3 T) y, E
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);! \2 X6 M! P- _, E
  44. $ i' a* J" _  f+ B. f: ^
  45. ( _0 ?( N  w4 ~
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);0 m# X# v5 y9 f9 Q8 d$ d' {2 v

  47. 2 q# z/ N" c0 U) Y+ k6 r3 j
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    1 ?5 N$ d( {2 z/ z( t
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    5 g) r6 ?- m& @4 H( u& {

  50. 4 y# Y9 @0 W- N- W
  51.   /* 查询模式写块 */
    ' L3 |3 A# d( ?
  52.     if(NumberOfBlocks > 1U)  H# @% ?* o; Q9 y: q! |( ?
  53.     {
    ' X% g2 _, Z! O
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    " C. N! X  z0 j4 u
  55. 7 h; X- Z) s5 j) o' c* O
  56.     /* 多块写命令 */
    ' o% F0 z' B, g! ~- ~1 N  \- s
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);  t$ U0 N  y3 o5 V
  58.     }! U% v% ~  z/ o
  59.     else
    1 O7 ^3 _6 r. b8 _- E
  60.     {
    , y- ^) P- s, I* v
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
    ' i  X0 N2 k' L2 ~! Y5 R
  62. 4 y' E9 \& B5 v2 u
  63.     /* 单块写命令 */
    4 |; @! C* k- u' S! g
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    * _" S+ w3 j/ y3 S% E) q
  65.     }
    $ C: X3 _- a" _. d2 j
  66.     if(errorstate != HAL_SD_ERROR_NONE)
    2 R$ K2 h# n9 d7 {+ U7 V
  67.     {
      D: I% I$ u; _# p% A0 j
  68.     /* 清除静态标志 *// @$ V9 F: ?5 k, j
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 }1 Y! m) {; E( g) R6 a
  70.       hsd->ErrorCode |= errorstate;
    7 \. e  v7 t5 Z% D" ~7 b
  71.       hsd->State = HAL_SD_STATE_READY;
    7 D* H. J5 O# _# m
  72.       hsd->Context = SD_CONTEXT_NONE;' B, t/ h% x' i) }% U6 Z: F7 w
  73.       return HAL_ERROR;
    1 k( G" ~& N/ r4 M
  74.     }, r" m7 C- H! A6 f  j
  75. * t( X" C: B- E* }
  76.   /* 使能传输中断 Enable */# h4 O6 D+ F8 W
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));0 \  F! U0 B; v
  78. * a' j- n* \" `! @2 Q
  79.     return HAL_OK;
    ( K- V0 U, A: p( b# d" n
  80.   }8 s* @( P. r. n, j0 O; U
  81.   else& o  f* }; {- |0 [. D
  82.   {
    6 m! c% f' O& x) g4 K. W
  83.     return HAL_BUSY;
    % Q) S7 o) m6 Y( ^9 l" d4 _0 @3 R6 K
  84.   }
    % G/ r+ ~8 X: h
  85. }
复制代码

5 ^/ ~- R6 G" T$ i# i函数描述:$ o5 I4 c3 }6 m5 E$ c4 ]

( w, k* T; @. k, @- ]3 c此函数主要用于向SD卡写入数据,DMA方式。% ^, S! q  |6 g) t  R0 e4 N! f/ C/ _
- [. ]4 n& {/ U
函数参数:
% U6 I/ r4 f# ]0 J0 _  k. p3 F, F% E) P7 _0 _3 l$ ?! C' r
  第1个参数是SD_HandleTypeDef类型结构体指针变量。: \: V; H0 ^) x: X. J: a
  第2个参数是要写入到SD卡的数据缓冲地址。+ X7 w$ h% B( l7 \% u
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
, W, ~6 J! H% }$ F( {  第4个参数是读取的扇区数。
: k# p: Z' d5 B( t  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
+ p5 ]0 I1 f+ T4 ~; C
% [( O) {# w8 ?# j7 V! s7 T1 c) V, A
使用举例:: D9 H9 E1 t* M$ o' @
4 ]' S) ^  g2 ~3 p) h1 k% e
  1. /**
    3 \/ |$ H; Q9 u$ r0 e3 ^
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.& B, L! ?! t0 n+ D7 _5 F5 l' K
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    1 q+ y1 s, l6 M
  4. * @param  WriteAddr: Address from where data is to be written
    ' Q6 H' Y3 j3 L" L5 W
  5. * @param  NumOfBlocks: Number of SD blocks to write9 l! g( @! `1 C2 E5 {( k. U5 ^2 l3 {) o
  6. * @retval SD status
    . I* Q! M/ x+ Y' m+ q3 }3 y
  7. */
    : q; @, A( W! W# e
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
      P0 T8 T3 ?6 y* C% |
  9. {
    4 E, V% U6 M+ |, ]1 z/ [
  10. % ]* h6 s* W+ y. W
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    6 g7 j8 @# \$ u# H& Y# M/ O% X
  12.   {
    # d. D! b7 |# L& R- [
  13.     return MSD_OK;
    0 _+ W; t8 x# y4 e9 ^) d
  14.   }& O  a& p, v& N4 c2 H
  15.   else& n! v# b( O' L; I# x, S
  16.   {# a4 P9 S+ }, K
  17.     return MSD_ERROR;7 c( R7 T0 p( [- k0 i  H/ x3 G6 X
  18.   }
    ( X  \& B( c: `7 k9 Y& [' C
  19. }
复制代码
. @) F1 N8 s" D) Z+ G% x' ]
87.4.7 函数HAL_SD_Erase
* Z+ M2 ^- s: G  p2 F函数原型:
. T. x% B2 ^! n- p  K! k
! t) X4 q+ F/ U
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)2 C% U6 A: L& ]6 f- t+ t1 ^: _# r
  2. {/ H0 j( p/ ~2 X7 M+ B
  3.   uint32_t errorstate;
    & n& g1 K4 \+ r. v' Y7 t
  4.   uint32_t start_add = BlockStartAdd;
      h' I, `' C" f3 b% r
  5.   uint32_t end_add = BlockEndAdd;
    6 ~$ Q# |. e; Y; i

  6. 0 {0 E) Z: O) d, C# h$ e
  7.   if(hsd->State == HAL_SD_STATE_READY)
    " I! e+ Z$ l. d! |& g. _
  8.   {* U  |/ u7 g6 C6 K" ?
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;; F9 Z' |3 r2 s& Y3 J/ d

  10. 2 q! F2 C  u5 Y' W4 I! c( d
  11.     if(end_add < start_add)
    8 Z7 I$ D2 B$ T$ ?8 S& o6 X
  12.     {/ X7 h3 z. [* `/ B
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;5 F& w# {7 R' }5 ^, T* F' _# Y+ ?1 K
  14.       return HAL_ERROR;
      E8 J, W* e, L( |) t9 m# q/ @& ^
  15.     }
    & u0 n! Q& \& Y& g- M
  16. 1 T3 K3 m) Q  A- |4 m
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))
    - V2 r8 W! L/ X( ?, n
  18.     {# Q% r6 Z& Q4 f9 m9 t2 I
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;, q5 ?: y3 _1 S9 e
  20.       return HAL_ERROR;
    / E3 }( Q) s# a4 H' C; r
  21.     }9 `3 x( u6 j; E; A2 z6 v8 Z
  22. . i1 V" o8 p  T8 Q
  23.     hsd->State = HAL_SD_STATE_BUSY;- a3 z& r0 {) v, l  S. r! u8 l5 N, O

  24. 1 W. q" b- g  s0 x" T
  25.   /* 检测是否支持擦除命令 */
    , Y8 v7 u3 B4 @& `- a# {1 c( }2 F
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    * F' Z. b7 p* h  K, Y; g; D
  27.     {
    1 ~9 i) ?1 e' Y! k4 z) \1 M% G& f8 d
  28.       /* 清除所有静态标志 *// i5 Q# Q8 C+ T: T0 n/ b5 V8 @
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    % _) Y3 s4 H2 s# C6 ]
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
    0 @5 |, ]' L* U8 m
  31.       hsd->State = HAL_SD_STATE_READY;
    3 g! @8 M  m& G
  32.       return HAL_ERROR;6 M9 j- j( Q* E4 }- _
  33.     }' H) F% g& H# o8 z1 [( X" d

  34. ! K- b2 U4 A; {
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)4 n0 ^1 F" T7 d/ M* f/ \
  36.     {
    9 O# `. X1 v7 U) ]
  37.     /* 清除所有静态标志 */
    ) D7 X  N3 ?! h% ^
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ) u9 w/ r0 h5 ~0 j. `4 a
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
    9 l6 d3 K  P5 n% Q9 x4 z5 B3 O1 I
  40.       hsd->State = HAL_SD_STATE_READY;
      y& V2 F9 Q3 l$ {: R- t  @4 h0 V
  41.       return HAL_ERROR;
      ]) H$ b; }$ _3 w- X
  42.     }' \5 D$ v1 T3 s4 g' u

  43. % j9 J4 d9 \0 W( h8 y, e
  44.   /* 对于高容量卡,获取起始块和结束块 */* U5 L/ k4 R8 k8 [* S
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)! o& T6 S. d& i, j) y
  46.     {- M. Q; K6 o# M6 b5 v
  47.       start_add *= 512U;
    * Z$ u" s" f5 M# _! x- `6 `, R: _' r# y
  48.       end_add   *= 512U;
    / J9 C2 q. c$ C; o9 \/ ]% A8 E% W3 Q9 K
  49.     }
    7 U7 f: S! d; L5 W# K
  50. ' R! C  l4 @0 ~" @1 Q9 L+ M8 X- `
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */% @( G  p0 i% y9 J# z3 O) v
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    , G1 _1 i/ F7 k
  53.     {
    + [7 H6 }8 s. @7 q# R8 K
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 *// @0 u2 R, a7 @% [  z* ?5 n
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);/ ?/ @! R- C8 F' i$ k
  56.       if(errorstate != HAL_SD_ERROR_NONE)
    ' Z2 E- r6 [/ J- l+ s& b1 j$ l
  57.       {
    # Y1 G8 r% v% j3 @. I
  58.         /* 清除所有静态标志 */
    4 q; O  A4 i7 u5 [+ X
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);1 M' X5 S8 T) h
  60.         hsd->ErrorCode |= errorstate;
    ) ]6 R3 _1 T4 ]2 G! F% }
  61.         hsd->State = HAL_SD_STATE_READY;. B. Z4 l* {! C- p* t
  62.         return HAL_ERROR;
    - s8 E$ a2 W3 l& E2 K- p4 f+ M
  63.       }: A$ e- g& v, W! h! T5 T$ T

  64. ; k. W$ g: [6 a
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    , h! ~. n! Z3 ?8 T* Y) P
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    6 h" H- u1 Q* |' c' a. o+ d
  67.       if(errorstate != HAL_SD_ERROR_NONE)
    1 Y8 e' I! Y6 U" X( A2 r
  68.       {: g2 U* `6 k- \
  69.         /* 清除所有静态标志 */
    , U) n- \' G+ l8 e* Z
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);4 y4 s8 b7 B  i
  71.         hsd->ErrorCode |= errorstate;
    . n- U( t3 o' s* o# I1 @
  72.         hsd->State = HAL_SD_STATE_READY;
    - n+ B4 O  m( U$ r( |+ N# A
  73.         return HAL_ERROR;
    , o) s9 q/ o; Z) A
  74.       }
    4 o# q5 A1 O: s% I1 I' y: [+ B
  75.     }# Q4 r1 W: r, P& Y+ P
  76. # ?8 L% S7 R3 d6 ]& F1 u
  77.     /* 发送CMD38 ERASE命令 */
    * |* L4 r& ~0 f5 q9 H- L% A
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    4 O' E# o4 V% N! G+ k  D
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    ! |) m4 b0 C" }' ?* K; z2 k' y
  80.     {, `) o1 c* q$ n1 S/ w
  81.       /* 清除所有静态标志 */
    ( \! h1 r5 n7 h- e
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
      J' q! T3 I' K5 t$ }: h
  83.       hsd->ErrorCode |= errorstate;+ Z6 s; v" K: f2 r- X: |0 ]
  84.       hsd->State = HAL_SD_STATE_READY;
    4 v" W" C& @0 ~. Z/ Y3 Q+ Q. t
  85.       return HAL_ERROR;
    * U, G; M0 q/ E
  86.     }
    / n4 l+ ^, E2 v0 V( ?

  87. # ]# q6 C3 O( Q# z- S
  88.     hsd->State = HAL_SD_STATE_READY;1 U8 u( Z$ {% I% |

  89. " w/ Y4 k9 [) Y0 N3 D( G$ ~- z
  90.     return HAL_OK;
    0 e1 A% Y+ i3 U' t( \) r
  91.   }8 x: R/ O# \8 x+ U, g, p
  92.   else
    * j. |3 O. L9 J; r: j% }0 J
  93.   {& H2 W$ N; d1 u, g- L
  94.     return HAL_BUSY;
    9 Z. l$ F/ g5 t  r, U  j
  95.   }4 v+ n; I: ?& X' k2 _, R
  96. }
复制代码
8 ^, S6 ~8 F- P% l
函数描述:9 r! m  }0 e) W6 g' W" `

9 e& F; @# c- ?6 @此函数主要用于SD卡擦除。8 E3 I' ?. ~  L& e5 T! r- I1 \( R3 M

6 X! R: F$ U, v0 i函数参数:7 a/ @/ o4 @' }4 V( }9 o
% ]; I% {- O8 j' H
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
! `: ^  M) b6 l  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。& G' T7 Q- b, P- b
  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。2 z- f- \+ j9 v! P# ]
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
5 ~% N* o4 N0 O3 d: }0 U+ B使用举例:  n; ?1 S1 w' w8 |$ m0 v
6 s; j+ u4 p  S/ `" R: m7 J! B  y
  1. /**
    ) X/ ]$ z3 Z4 [) Z- p- v
  2. * @brief  Erases the specified memory area of the given SD card.4 }6 O% e, s3 y* \) ~) L
  3. * @param  StartAddr: Start byte address4 P% b# l+ w$ A
  4. * @param  EndAddr: End byte address
    / ?9 Q6 L% c7 b" r2 c+ b
  5. * @retval SD status
    3 \4 `! {2 {" r( y
  6. */
    ) t9 r7 X  U5 \: \9 V
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)+ H7 V7 M1 Z- D  ?- k$ T
  8. {- r0 e2 s+ A0 G) {/ k3 i
  9. " R7 x+ k* b# _% q6 B  G
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)2 I$ a6 O' d9 d8 q
  11.   {: k- L  ]8 s0 O, h# ]3 O4 G% q* l. J7 d6 m
  12.     return MSD_OK;) ~3 P, h) y; v* Y& W
  13.   }) }$ O- G) B) l* h+ `* T
  14.   else
    ) C, c# I$ v0 `/ U, B# O
  15.   {
    * [% M; d% z; Q; `5 b! }! |
  16.     return MSD_ERROR;
    1 c0 B: {3 q9 T7 ^9 e6 a
  17.   }+ P& `+ I( p9 i8 L  |; W( x
  18. }
复制代码

; q2 ~" z4 ]$ l- v: M, Y87.5 总结
8 s- `% K$ C+ g' z. v# K本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。3 w* p5 F2 W, N  i- V! J
: W6 r+ p3 I! `- A  u

3 C' x% Z* O+ z2 h& z, ^+ z% n  A7 @" Q+ @/ H; V

/ n. \& q9 g: {' z5 W! \1 q0 x6 W
% E7 _* Q. O( h, Y$ K4 [' {" q' @) o) I
收藏 评论0 发布时间:2021-12-26 16:43

举报

0个回答

所属标签

相似分享

官网相关资源

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