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

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

[复制链接]
STMCU小助手 发布时间:2021-12-26 16:43
87.1 初学者重要提示
! D/ P. [8 e4 F8 P6 v9 ^" A  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
6 |* e3 ?( [, D& E  H  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。) {8 s: L. z0 P/ K8 V+ E( q
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。
8 x; N6 c; m; b! B# V  g" j  SDMMC驱动SD卡支持1线和4线模式。2 V( v7 {# c! [; ]
  STM32H7的SDMMC也支持eMMC:& r% |& `. i4 x
/ h, }! a- T" z. o( P" z1 I
87.2 SDMMC总线基础知识+ V0 o- Y; G3 M/ Z
87.2.1 SDMMC总线的硬件框图; W7 a& ^# |* |" O
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
& ~: o& h- J& t( ~9 M' _6 b2 h" ]0 g6 A( G
6eea62abe623396815a50adc87205b83.png
6 f; Q2 i" G. O- p( O0 o1 Y
4 v0 a6 U6 g3 ]% V; i+ I/ H
通过这个框图,我们可以得到如下信息:  - ~3 k5 R/ P- y* j) ~( L% u
   sdmmc_ker_ck输入
; ^0 `) k3 }% @# l2 oSDMMC内核时钟。7 K1 ~# Y6 K& W+ g' Q# E) p8 y

9 q7 h. ]; t4 k5 S/ D- ?) Q  sdmmc_hclk输入" U. v) l' w3 ]/ t
# J+ n: I( m9 Y8 \0 r
AHB时钟。' t; `; O* x, O* |( i( @$ ?  I
, y5 U7 m. o( G. r6 ~- Y! y7 C
  sdmmc_it输出
- w  B3 m& r* s& `9 y( W
: m' ~9 F, [0 `- E/ T& gSDMMC全局中断。: g# z: j7 ]/ E  R( N4 p; B

! T. U+ R* L: ?# W  sdmmc_dataend_trg输出2 L  H7 Y  t! C
# ?- S. ]% u% \6 w" `( u% L7 w
MDMA的SDMMC数据接收触发信号。
! J/ b, l  n7 D/ ~, `1 o! b
; [& V' p3 r2 Y* P: g' N/ N8 \6 M. M  SDMMC_CMD
5 j* x- z/ |* a# d7 W7 ]5 F6 u
8 Z1 n" \5 c- W0 _! ESD/SDIO/MMC卡双向/响应信号。8 k  B- d/ u! n, u

4 E3 d: S4 a8 }6 q  L5 ~1 L0 `$ W  SDMMC_D[7:0]
7 s: T8 }. u: M- ]4 k
; X1 `, D! Z8 d4 @! YSD/SDIO/MMC卡双向数据线。
7 ~% S- {) O: P" o& x5 G7 X. r* A" y+ G& q% a- g+ I5 ^5 h
  SDMMC_CKIN/ f3 Z% g3 x; |3 p1 ?- \
6 Q5 s6 [% a; O! T6 w) l. c( z. i$ ~9 k
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
% {. p" N% u# k8 R! N  w
" f( L" H2 `. R3 Z' l8 j2 W$ L+ T  SDMMC_CK
/ e* R6 a3 q/ F' L' W2 E, R/ R  }5 y- u/ E7 v' @0 G4 T8 [
SD/SDIO/MMC卡的时钟。
/ [2 a$ U6 e" {( M8 T0 H6 t: d: R0 h
' W/ b( y' o. K: t  SDMMC_CDIR% W$ ~" ?9 t- E2 w# g- C1 u2 i

" f- ~# m3 W! H2 y+ qSDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。. Q, G1 k1 b5 `. a& r( i
2 Q7 F7 d7 O" J( q# P. M; J
  SDMMC_D123DIR, b" k: S- G0 D% m& p, O2 i- m

& E' {6 U, D  C/ u0 {) NSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。* Y; \3 M/ K4 c

1 x3 i: s% r5 D2 l; _  X! W  SDMMC_D0DIR5 k6 ]- [5 E! a8 V

1 J" j& a  d1 p6 NSDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。1 M! ]: Z6 H. v, `
0 d  }6 k# H/ G1 P; }
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
. F0 Q& a; s- Q$ z  x; U) h
& d; `- R% E* l2 i87.2.2 SDMMC时钟
% k0 S( D( O; K* ASDMMC控制器的时钟来源:
) d5 @# n, v: X+ f. h: K
  f* f2 R, Y' L4 z2 a: M+ K8 d
676ec31792fcb80bee640ed979d48084.png

7 G: x! D( e8 r, i8 p
# c1 O* D& ?& LSDMMC1和SDMMC2时钟源是一样的:
8 O6 w5 L1 N2 d4 F, B2 [. Y: b' P* [; O
79b1c69986d1ee5bc090bf1676f396fd.png
9 _" Y2 [2 b9 P/ o1 }( J: ?

5 I8 ~; `5 S- z: }5 H' n2 b& ]2 C87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
+ [  ]) h& _3 F5 t" z注:大家应用时要特别注意这个问题。
2 i1 ]( n/ H+ S5 h- \. y' Q+ {8 N. e  |+ q+ |2 V- |
使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的6 c( s# [% |5 t3 C  E

& k2 ?6 o1 _2 {8 @9 y& X9 S
6a5491d2f4a8740d838af58d034b7597.png
( o- S% p8 k+ p: _7 \* N

: j% V2 _; I7 c3 }% j/ b4 x$ E$ \87.2.4 SDMMC支持的速度
" P) k% ^& V  \8 A* y8 N% T# Y
驱动SD卡支持的最大总线速度:
3 `; x4 E  m4 @4 g5 I% e  q& F6 e- z- k
b70ce31107b38ea820dbc28c3caec38e.png
) ~8 A7 K  [2 }( j" W! r4 k
- Y, k( ?% y) v- g: C  K/ P
驱动eMMC支持的最大总线速度:
( S% h5 ^6 `: ^+ Q) t" n1 |9 L! c7 y$ i
843bf7a054944ba7d5d137ca84e1d4ed.png
( J) W; l6 D0 p1 y; x' d' k

0 ^  j& _7 O+ P! f% u关于这两个数据表,注意以下几点:; G# ^6 ]  S, X) P  t2 _. D9 y

. ~; e  w+ h( Y* V9 ~  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
4 U* a3 A% \; X6 i' p  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。5 h% M* L2 n, E" L, |/ ?2 b& N* C) u
  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
! S- E: a3 {9 s7 ^) A
) n5 d! X2 N! |- p0 S, e( Y87.2.5 SDMMC支持UHS-I模式

+ u' [& H% [3 k1 P* u1 a/ B, ZSTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
0 Y& x2 e& F2 B2 [% O0 f9 G0 V& q% |3 m
2b8e4430b8a60dc5a1b342d7c7f75f52.png

; Y' N  B+ J0 ^# |. P- @; t1 ^3 L; N  V" \9 w6 _# v
85f975745619c9afc64f8889289dad58.png
: H6 D9 G/ d( x8 y1 u

- M% z) @) ]% e% N  v87.2.6 SDMMC自带的DMA控制器IDMA

. A0 U$ q& X4 ?7 E, ]+ Z% i+ ]/ ~STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。$ [! R8 j' S6 [) k# O8 m+ N; B5 B" {# X

+ e9 e& x7 }# t) C- P+ B( T& s87.3 SDMMC总线的HAL库用法
9 T, b4 _# f1 H* `+ c5 M" {87.3.1 SDMMC总线结构体SD_TypeDef9 Q; P- ~8 l5 |. ~
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:; w; d' g( s) e& Y! n7 P
; _: a4 H/ k9 F6 W1 t- w& P
  1. #define SD_TypeDef          SDMMC_TypeDef0 E: Z. p$ O2 }! S4 t  B
  2. typedef struct6 {' L# t+ z9 e/ j. J: w
  3. {
    + u7 C) _! ~* G  d7 Z
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */% g) N6 Q8 J3 r$ W2 w
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */* v2 l  m( z5 x, ?$ [  x
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */4 Q" Z& u9 q/ f; T5 B; a# }
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */! B& N" J* l' t5 L% ?  H; g+ b( f
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    9 i) n4 T" |% @) L6 h( h! t7 E
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */
    7 e* |: }. S- Z; X" b
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */
    3 x* M: X& w2 m$ z+ o
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */  ^' [% \% S6 _* V) r' J" U, q* \
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    3 g3 e9 m2 G% K8 P+ Y9 L3 ]
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
    4 _1 n. Y3 F' A* ^& a  X% f& M/ V
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */8 K  O! L: p/ t' s- [, \( j% I
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */  y4 S! H7 H. P/ f2 @  b7 ~7 w8 Y! e
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */. A2 W4 G9 w' y5 I  l* O' X
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */
    8 g# `0 {' `# z
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    5 [3 ^+ V. l$ p  [% E- x/ ~
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    6 o( c* l9 ^- I$ R5 v0 Y& t8 L  m
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */4 ^+ M. r7 s- P$ \& X* f
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */
    : q) ^( U" R' O" S( b: \
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */* \  {! E6 C+ W5 I, ^
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    % ?& W* t8 ~/ t& X) C# _( k0 @
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */% m; ~1 x( }  I1 v2 @
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */% U+ b- D! ^8 o0 }  Y* I& `6 E
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    + E& [, N, _9 k# p2 M" u( g
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    % x8 J  ?3 G2 X9 }
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    ' ?& q1 a' y6 t( K# H/ K
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */
    / N' c, T+ T  u: n' K3 r: T7 j( Q
  30. } SDMMC_TypeDef;
复制代码

- t3 g' F  U% G- v这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。, }' z! ~! I7 S, e6 P# @* D

) Y3 [3 P8 q+ a__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
3 f  d9 i; S- k2 X- d2 p
! w& y7 _2 p7 u% E1 T
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */" {5 u3 u" ?, r5 a. |5 b; a, X
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

7 v3 a2 J; j  v8 k  X下面我们看下SDMMC的定义,在stm32h743xx.h文件。
# D6 y' z& }5 W% _
* J8 t* k& k4 @+ e* p( f: J0 w8 S
  1. #define PERIPH_BASE           (0x40000000UL)
    # X) w+ G, w, H, d
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    ( g7 }0 M& f2 P7 M$ w$ S* N' e5 _
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)
    4 M% y9 z& I8 E7 d+ P5 I

  4. # e) e  d* f, J0 ~7 W/ }2 R8 L
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    ) `  q8 W  Z/ B3 ^7 o4 a6 y8 _
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)3 P" p0 v' S) f  U- ~$ c/ F

  7. ! B7 y: a# ?# j; q, E  O5 V0 M$ i) f9 {
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)! M4 C+ Q2 i, |. _" g0 I$ T& R
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

. P6 @: D0 e1 n$ ?9 j, s我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。
! H4 K! Q: }" T6 Z1 `3 i( M& C9 e" f( w, e# D6 \- O
87.3.2 SDMMC总线初始化结构体SD_InitTypeDef2 _2 x; {4 `; V
下面是SDMMC总线的初始化结构体:
6 R% ^' e6 J, R0 g9 s( }1 W9 U9 O% {$ H7 C8 T
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef* Y# X+ }! q  G4 x) ?' H
  2. typedef struct+ L/ v; A7 {# ?9 f) n
  3. {
    2 d, n0 ?4 t7 T$ q) Y- P
  4.   uint32_t ClockEdge;            
    3 a6 X" a5 T6 v! e5 p' g
  5.   uint32_t ClockPowerSave;      9 i! `, u- \- J8 \% N6 P
  6.   uint32_t BusWide;            
    8 H- C" D7 Y! L9 U
  7.   uint32_t HardwareFlowControl;  5 E% J" {. g! {) R1 C
  8.   uint32_t ClockDiv;            
    + V) y+ C  k( l2 F. W
  9. #if (USE_SD_TRANSCEIVER != 0U)
    - v. D; k" ~1 |+ ?
  10.   uint32_t TranceiverPresent;    / g( [, {8 ^4 z* G1 H9 J
  11. #endif % M& g0 H& h* a+ ?- Y
  12. }SDMMC_InitTypeDef;
复制代码
) c% k$ J! E# o5 k* c4 b. b
下面将结构体成员逐一做个说明:* `% }$ y) v2 R# c7 k
4 ], t. a" v6 Z* W* E' H
  ClockEdge( C( e: p3 ]% \8 N% J( |1 K- l$ e
用于设置SDMMC的数据或者命令变化的时钟沿。
$ ?. T+ D6 m) }$ s: U# z  ]
. ?  j: w2 f9 O9 @1 z* j
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)1 Q" Z/ B& H: A) F; E
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

/ Y; ^, p  `: I  ClockPowerSave2 T: s2 h9 h8 y# u3 m
用于设置空闲状态,是否输出时钟。- x- N) x" ^. A# g# F( p
$ o9 n0 u2 m& ?# O, J2 R0 a
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)( U. t  ^9 F2 l, R) O
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
1 K, e+ @( l% ?, K( [4 H& `
  BusWide
/ p3 a( {/ A1 o* U! A/ x用于设置SDMMC总线位宽。9 z1 R% X4 v5 g* }
- d" K: |5 i6 h
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)4 H3 T9 v  e# f7 O2 J
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0
    + X) g* o: _: w# A
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

: v( s/ n9 l3 }; i& |4 k3 O  HardwareFlowControl, X& ?1 @& X4 h8 S
用于设置时候使能硬件流控制。
4 M6 Q. [' z2 ?$ \' L! d
: t6 d# D$ ?1 P
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)- z0 M" P6 r& O- `* _9 w% B
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码
) q  A% v  y; Z
  ClockDiv
0 h7 ^1 D# H" U. C# s用于设置SDMMC时钟分频,参数范围0到1023。  I) Z) b, d( f) v) I1 @4 V6 ]. w4 N
7 h" {$ t- V/ U# E7 k! w0 e
  TranceiverPresent1 P% h' H/ Y3 [$ L. c) B
用于设置是否带1.8V收发器。
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    / M2 i, O" V7 H* r% I9 \! }+ v. n
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)
    - [; s: G7 X8 F" n+ z+ h
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码

% c9 \# a8 E- g3 P' j87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
8 U$ j: I$ A( G: e
下面是SDMMC总线的卡信息结构体:
, O& q2 j1 k' R2 w) a6 l; A. r: ?$ |0 }- p  J
  1. typedef struct
    + ^! }, C( f# t8 H
  2. {4 w- ~. x3 R7 K3 ~  \, v
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    1 F6 ~3 M) O$ H+ h8 S
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */0 A- p. D! {( R% X. j7 Z% E
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    " P# u4 |. j+ M* n
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */1 D6 z% E1 N6 R4 L2 ?
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */( l2 p+ V7 T) d4 \, c! U. N
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */- R- T. H* @  H+ [; C# F
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */! R1 k: w* a) ]' d5 M* |
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    8 a* K9 J8 n+ H, Y4 k. l, a
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */
      \2 R# l9 |& h6 l1 b
  12. }HAL_SD_CardInfoTypeDef;
复制代码

: H) W7 t& r  j% ]9 _, ^: Q% S下面将结构体成员逐一做个说明:
" z+ }. s0 Q. `6 p2 L( ]: g" A. @  ~1 w, N% c( a
CardType
& c! R' y5 u  o- z  b1 c+ {卡类型。
  G- @2 O0 r. n2 ?$ W; K$ \
8 |! N: s. H* V! v! d
  1. /*!< SD Standard Capacity <2Go                        */2 K4 t; ?% g* o
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U)
    ( S% A" R$ w- R. W
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    $ B4 J- D) u4 Q( @% Y, i: V. r
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
      i* l4 E. A. A  c
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

1 V. Z" K" k) c) ?( |. M1 o2 a- S  CardVersion
6 o% V1 v+ y* K9 B" o  {0 b8 @( m% v" {6 a# @# r$ o! s0 ~- j8 p

+ ]& C3 h6 `. _. l  S0 i/ I: U6 t' V卡版本。$ Z" [: {& r3 I. r. X# }" r& ?

6 e& X. _+ W' x- F! i1 Z. J; t
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    - e" W6 ?0 x4 S* f! @7 T! `+ ~
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码
3 S; \9 j$ J, x5 e, s( N5 r: E
  Class
. D! Z1 I1 F( Q. r3 A: F0 B' d0 y6 {9 l9 `% I4 }' m
/ H6 P. q, G! U' l8 W4 [
卡类型。
, V1 q7 L1 N) o# t' M% S
1 B0 V, Z" R( n  N4 A% `5 z  RelCardAdd4 N- f* v3 T- D4 T

$ [* E9 J/ t0 i. L; k5 z% t9 p' x6 v
卡相对地址。
' i" E5 m! u' B6 `0 W$ S. [2 J- M( q6 }
  BlockNbr
7 R4 E$ P( i5 l& a4 y# o) K整个卡的块数。1 \( J: X+ E0 K
! ~$ T2 h, J  a+ u
  BlockSize
& P4 R* P* G7 g* \! T' C: g- a6 O4 h5 Y& ~6 B" t
6 Z2 |# f2 O6 W; Z: |- s
每个块的字节数。) W: X' G7 C: }
% F2 |& R1 c. l+ [  L
  LogBlockNbr' E- Y# _9 t3 ^2 {7 \$ _6 i. l
- m; h- M8 G5 b4 @# Y; n( g  [) G0 v
. f2 u; a. t# J8 U& n2 R6 [( L
整个卡的逻辑块数。
, f; K" {- G* [  r5 I4 \; b  g) E* E9 G& y4 y& h+ k! S! t* R% Q
  LogBlockSize
1 p& {8 R. \* }, q( X3 {, D& X1 n) O, Y5 S* H* T+ J: j9 W

( Q: f' ^# k) l7 R1 ^, S逻辑块大小) J. i+ K, j# ~9 q0 m' V; R

2 l! r7 h* B1 J' S4 s) m! @
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    0 S  G) v" J4 j( \8 b" I: Q9 M! i
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
6 k: z$ C& i* b
CardSpeed
: ^' X4 P8 M8 c5 _* T8 F用于设置是否使能SPI总线的TI模式。
5 y2 Q2 m+ j) c  E6 s9 O% O' V6 H; ~- z2 A3 Y6 J& ^1 H( b+ I
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */- x* O. D& C! ^! x" _7 \1 l! B# h
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  8 X6 C  d1 i! J0 H1 e3 l
  3. * ]( D" n( b, J  G0 s) |9 \  c1 u
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */ ! Y/ ^1 c, s, O" U' @
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U) 4 k7 W% [3 C. x7 P$ V; y
  6. 5 w1 Q! d6 d/ O
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards
    + B* Y9 X5 t5 M9 }2 Z
  8.      and <104Mo/s for SDR104, Spec version 3.01        */! e7 s1 @, b# Y
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

: e0 |, n; F9 W8 L8 ?" s87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
8 Q2 d" k+ w. C- r* |  ^3 d/ s下面是SDMMC句柄结构体:
3 h  h3 X) N% I# t% L% {( x# ~5 g' {% E' j- x9 K/ O4 k" ^
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)* l, a0 a2 |" T) _1 }9 @% [
  2. typedef struct __SD_HandleTypeDef
    . a9 z; q; B% H2 m; L* s
  3. #else2 Y  B; H6 [* ^) Y: \% u4 P) a
  4. typedef struct
    % Y: ?+ ^! h# K" ]0 l" W3 |- J$ h
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */' ~( ?2 ^! P- Q2 q- U
  6. {2 P% {9 I" ]8 h4 x6 B
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */7 Y; Z  F+ Z/ [$ v) s$ _
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    ! w  d6 |9 o3 ]
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */' y- q/ s5 ~0 c+ p
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */6 ~/ ?- ?) j8 k) e! ~
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */. y" ^7 c6 d/ K- A4 @2 C5 X7 o
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    7 I  F: R: t& S# ^. r( z8 ?. ?0 t
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    ; }/ H8 W- M8 o$ T- N/ l1 t
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */3 m7 N4 B/ q7 W/ N
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    4 q2 ~  M( q2 @) k* C9 X4 s
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    * C( C5 P- a( c. O
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */
    ! Z$ l% }+ B4 {# P0 f6 i
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */; }0 T" {9 j% V9 Y* c5 O
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */$ F7 T* T2 U: x5 p) D  l9 W

  20. $ ]8 A3 a* ~/ B0 a
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)3 b3 Z3 e+ R5 [# b- q& W
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);) I' H1 R2 c1 E2 p( ]% l( v" P
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);" ~9 i" {0 l2 J: s! k
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);
    , ^, c! x( i1 Q% r4 Y
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);% E& g2 b. |! U( ]- k: N
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);0 F' B6 y' U! G2 R
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);, l; ]$ P! H: E
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);+ `1 ?8 ?3 b+ f
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    . a# U! v# f6 b3 T
  30. #if (USE_SD_TRANSCEIVER != 0U)
    % Y( k. V  u; C
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);3 U/ W. [3 s; H8 J. \& `6 E
  32. #endif /* USE_SD_TRANSCEIVER */
    6 I  y) l+ t2 ?+ [
  33. $ N2 ?6 E' ]# o# I  s; i8 X
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    & i, ~1 L) ]6 N0 v- h( V# h; Y
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    " X1 \2 q7 |8 K/ j4 I8 u
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    . o: C/ u. A9 n7 A6 I
  37. }SD_HandleTypeDef;
复制代码

! f  {2 y" ]2 G$ Q5 ]7 P注意事项:
* n3 |) K5 J, t1 L8 ^% J$ Y" H  j
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
9 ^, p4 _' [1 d1 ]; A) k8 K$ |  E) a
# s: F' M- b6 ^: j! I- E7 ^- V  K  #define   USE_HAL_SD_REGISTER_CALLBACKS   10 p" i8 E$ q7 S9 x* b3 M/ ?
8 b& a+ ^, [+ R! o- B( V; j: T
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。  Z- ^- S+ W5 N4 W' _2 H

* E$ X8 _1 d  [, M; T4 v这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。4 e/ Z6 {) N) T! W3 s
2 J) e" M7 A5 C& B6 y
  SD_TypeDef   *Instance2 [4 h  w. h: Z/ z7 E# M
这个参数是寄存器的例化,方便操作寄存器。" D6 W! K  {  G( O

. b/ l8 |# l! V( b  SD_InitTypeDef  Init
6 `" y! s0 H0 {这个参数在本章节3.2小节已经进行了详细说明。% @) u- h4 J2 K! T% l8 g

5 [  g; f' Y: |6 l/ q  r' R2 f87.4 SDMMC总线源文件stm32h7xx_hal_sd.c  x% }+ w0 y  |: V% I
此文件涉及到的函数较多,这里把几个常用的函数做个说明:& o: p4 D7 J3 n' k" Y% g, w

& h6 y- T) ], X, t# e  HAL_SD_Init
9 q2 A$ s+ q! F  HAL_SD_DeInit8 }( Q- _4 ?; X% Y/ D
  HAL_SD_ReadBlocks# w9 F% W5 u( `3 K3 y
  HAL_SD_WriteBlocks
: t' L3 L2 g" }$ K& M6 T  HAL_SD_ReadBlocks_DMA/ @: R4 |$ O. G4 N
  HAL_SD_WriteBlocks_DMA) W# v# F- ?# q/ J
  HAL_SD_Erase
7 W7 b0 ]. B4 K+ R$ O
/ Q# i9 J" }% e+ p87.4.1 函数HAL_SD_Init
+ e/ D5 \; m, [函数原型:
: Z4 r9 d  `% l6 G& B* V2 y  J
1 z9 K6 W* W/ l* E- o: w' a' Z
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    . Y0 `, |* E0 K9 A
  2. {/ H/ e$ A7 E1 \7 A
  3.   HAL_SD_CardStatusTypeDef CardStatus;
    + t7 l4 [- ~  ~; ^$ n
  4.   uint32_t speedgrade, unitsize;* a) v" F* R: k5 a* h5 c) K. G
  5.   uint32_t tickstart;
    1 o% n! W# X. Q3 N4 ?4 c
  6. & Q7 f# ]/ j0 N1 C
  7.   /* 检查句柄是否有效 */
    8 S% i: Z7 A# F8 n  |
  8.   if(hsd == NULL)$ |4 ^. |5 N& [# I( S  A
  9.   {3 @4 x* t# z( Y3 \6 ?' o
  10.     return HAL_ERROR;
    & ^6 f2 g. m9 y8 O. K
  11.   }
    ! ?4 R# I2 ?4 j: Z
  12. : e' z" }0 Y& y. G0 R2 C0 l" x
  13.   /* 检查参数 */
    ( C2 P9 q! g! G6 C
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));% |3 Z& k( }0 t4 q
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));$ d: J/ I% |2 B4 b! [% T: ~% a
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));7 \* a1 c+ Q# o% ~  H6 Q; W/ u
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));) _  l1 A0 d, {: o6 P/ B$ i% v
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
    7 o  I: l: [0 i( E4 K
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));+ |& o0 u! q/ r0 S6 [! ?

  20. 8 h4 ^3 U7 F  r  `
  21.   if(hsd->State == HAL_SD_STATE_RESET)! R& T& `/ Z- _9 L
  22.   {9 Y- e  h9 b! I7 s" H* S$ Y* `7 B
  23.     /* 开锁 */
    , z9 a6 I* H8 J
  24.     hsd->Lock = HAL_UNLOCKED;1 \1 `. W% I; d1 K0 k9 I0 ]
  25. : V) R1 m8 }' i3 s+ {
  26. #if (USE_SD_TRANSCEIVER != 0U)# {) b$ _# a1 u3 d& D
  27.     /* 兼容 */$ X* d* B( V8 N
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)" W* m, X- D/ s' R/ B1 U
  29.     {
    * }# q, O% ?0 @) N! M( _
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;2 V, {- @+ d2 s3 Y
  31.     }
    1 b7 |0 m4 k6 Z. S
  32. #endif
    " k- t7 t  L, |9 W
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)6 `3 l7 y  O4 \( J8 `$ P
  34.     /* 复位回调 */% }" I; \  A, j) e. h, v
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    ! g% \2 ~1 H+ o: l
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    3 @- R# _; b7 V2 ]
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;1 J2 B8 U2 G  E3 N5 L5 l+ ~, E
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    6 }- U2 L* o, v( n1 A1 M" Q' H$ ?
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;, h5 ]) A( p' t
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;9 ^  {1 |7 N: L' ~/ _" i
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    4 M2 \2 A# I5 X8 b
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;7 M( W: m3 c6 ]6 Z: R
  43. #if (USE_SD_TRANSCEIVER != 0U)1 `3 c9 A" X0 M6 C1 S7 d
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    9 k! [" h& ^: Y* h9 y
  45.     {5 ]0 [5 h. H" D4 w4 ~
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;- Y/ B7 d. N; ^- K  ]& ~
  47.     }& r' v5 x  O8 J& h) O5 N. o
  48. #endif ' G$ z  n# q  b2 `
  49. , A- }  m0 }4 Z* ]  M8 X
  50.     if(hsd->MspInitCallback == NULL)
    6 y0 x) V5 g8 v
  51.     {1 i. G9 x- P% F9 t& u
  52.       hsd->MspInitCallback = HAL_SD_MspInit;
    . k5 J! B4 k* h+ N
  53.     }2 f/ g! ~' x8 ~
  54. 6 X0 S! W1 H! C* \7 W7 `
  55.     /* 初始化底层 */( ~/ b1 u# b  f% ?
  56.     hsd->MspInitCallback(hsd);
    , |# Y( M, A# H- A
  57. #else0 R1 v( y, w8 G. M3 Q
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    $ i" b5 l; `9 p, [/ u; i
  59.     HAL_SD_MspInit(hsd);$ O3 N( g& f3 m! G9 a) P
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    0 L$ y* U# a: w
  61.   }
    3 q7 p( u& k4 m# J7 M2 u8 X4 g

  62. 6 y( y. s% Y- e' I2 f$ O8 B6 L5 x
  63.   hsd->State = HAL_SD_STATE_BUSY;
    / E7 h6 F3 n1 z8 d
  64. % W$ S0 z& D; r% B: |' G  F
  65.   /* 初始化卡参数 */5 X+ k( c, B( u) s3 f+ m
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    ' |' D6 Y' K" `- Z9 M8 j
  67.   {
    7 ~$ d! f3 h* q: F+ f
  68.     return HAL_ERROR;) u. a/ P6 l; @; W
  69.   }
    & h" N: s- T# y4 B  k

  70. 7 b% D# O  \5 y$ p: e
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK). G0 t; E) ^) l! {% w* n" z% G
  72.   {
    8 {* i! g; U/ Z6 c
  73.     return HAL_ERROR;) b) M; q8 X( P6 {) a& @/ F
  74.   }. ]5 ^) K8 ~. t# ]
  75.   /* 获取卡速度等信息 */
    9 k. s7 N9 w  o! v9 K1 Q
  76.   speedgrade = CardStatus.UhsSpeedGrade;4 U) M/ `, H; I- [9 O7 c
  77.   unitsize = CardStatus.UhsAllocationUnitSize;
    0 m' Z6 E4 l4 r/ g
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    5 l& R0 w5 Q: R0 v8 w0 ?( p. c/ ^
  79.   {0 T+ x  E# _1 [7 l5 w
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    # t( F8 m/ j8 D
  81.   }
    * x7 m4 R9 X1 d# u
  82.   else
    ! {; b' e, R5 z- n# v, A$ v; C6 @
  83.   {  L& f2 ?: g$ ?$ F$ m, A+ n' v5 a
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)* w5 G/ L/ w, j) n
  85.     {% }+ A1 K! [$ w  T3 v
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;3 J: D; M  N  `; K2 Z8 r( D
  87.     }  K  n* K& a; o* |+ }4 @
  88.     else! R( k& q9 S- w- p7 @
  89.     {
    1 q) R6 j; h, |5 Y
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;! m0 b! o! b) {2 _+ ?8 G. e
  91.     }9 y+ b: c6 u4 B- i- u9 b5 t
  92. 7 o( Q7 g- q; \: A9 d
  93.   }
    + ?( I# ?6 v  a/ Q/ D+ e8 v0 o! X$ l
  94.   /* 配置总线位宽 */% O; \, A6 @. a7 T# U, e
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    3 Q6 d, P' [6 m; v
  96.   {& a4 F1 ~: g7 X
  97.     return HAL_ERROR;
    9 _' d$ `1 x/ s- \/ O
  98.   }
    3 q  y' V5 M) J% A3 c/ \7 D/ q

  99. % P) S, l' O# }" W( N, B6 S
  100.   /* 验证卡初始化后是否就绪 */
    # v* z( M# L8 _" z% _
  101.   tickstart = HAL_GetTick();: ~. C. m2 J' M( Y# M9 H/ Q: O
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    5 O7 A! s! m! L; }1 c4 W# ]$ F4 c
  103.   {
    . P; I! Q' P- K
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    7 L: o5 C1 q* r& z! c( n
  105.     {
    8 z! {  M! r, s$ l2 |
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;4 j5 D& M8 g% S/ Y  |( o
  107.       hsd->State= HAL_SD_STATE_READY;
    + U" r, t& B: j* [9 ^" t3 A0 Y
  108.       return HAL_TIMEOUT;
    ( Y0 C% b1 ]( f/ K9 I
  109.     }
    8 H+ M2 E$ f+ o' `" P/ n: ~2 a1 b
  110.   }' y- N5 u- i' F4 B

  111. 6 g$ D# D' {( s$ `2 H* e7 j2 b
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    & y% W: o0 Q4 V9 A, i1 H& r% k5 j

  113. 2 P# \" B8 |) _( ~) [3 \  B9 E7 I
  114.   hsd->Context = SD_CONTEXT_NONE;
    3 A! R# |: f$ C

  115. 8 e. z3 w7 F+ `4 _; K" ]) r
  116.   hsd->State = HAL_SD_STATE_READY;+ G, [6 Q7 u" \
  117. 0 e1 U- v, z5 ]8 _" G( K  A9 r
  118.   return HAL_OK;
    ' o) r6 `! H6 e. q: \4 a
  119. }
复制代码
$ T9 B% l; c: C% n8 r
函数描述:: W& t, V* R6 ]1 d  `: t* n. C

6 R$ p) p1 L% U1 v- P/ h6 Q: e# X此函数用于初始化SD卡。& k' q7 u+ f6 o2 g
* J1 Y* I  B2 }
函数参数:% b1 k5 a5 b, ^" {

& b3 ?/ S( Y3 U& X- d* d  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
- r/ g. Y4 C" F( Z1 t* A  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。, j6 M+ X1 C4 M/ Q$ V- [, X

" m/ v7 c) j+ u* m0 W/ u  j1 ^) v2 E  J6 z1 W2 k
注意事项:4 C  m" Z" X% J3 a1 U% I
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。% R% |4 ~  ~% p2 a& Y
如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。( W+ U6 d( Q5 S8 v) E
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
3 w0 R/ X: `# v0 h! F4 z
2 s  T- {9 M4 D/ f; Y解决办法有三5 a. B6 J4 s: L3 ]2 o. z0 R" c

4 n* a* j8 [; @- U' T" b方法1:用户自己初始化SD和涉及到的GPIO等。
5 w+ k) F& j) N) a6 ~4 P" |! X
4 b4 `" X+ {' G  I; a7 ]0 I3 {" b' b# s方法2:定义SD_HandleTypeDef SdHandle为全局变量。
  H3 n. f" W. N9 d2 `
9 S( Z/ Y! k6 R0 ?方法3:下面的方法: P% k3 w. i9 Z# I
( v, w; X7 S) J7 L$ J$ k6 o" x
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    6 h8 f- x# N# g/ u9 u/ o
  2. {# Z  f! i9 v4 d% C5 r7 ?
  3.     Error_Handler();
    + l2 V+ o6 n% G; D9 S- r& Q. G3 r
  4. }  
    / t" b, ~* ^/ h, s+ L- k
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)1 [6 Q4 s5 Y0 b& }
  6. {
    , E% d8 R/ g1 p- X& }& J, N
  7.     Error_Handler();1 x9 G$ o, x% L( ?
  8. }
复制代码
( P8 e+ p- l4 p9 }, [
使用举例:
6 U$ D5 S- F) Y" Q/ {
" s& L3 Y- M5 T, w; _3 a3 I
  1. SD_HandleTypeDef uSdHandle;1 _8 Y& o6 [4 b8 Q. R

  2. ' r8 N& h2 Y4 J
  3. uSdHandle.Instance = SDMMC1;% E" D& R- B. `$ r

  4. / h6 M5 |4 [) z0 P% p
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock) @2 E" I& s+ `: Z7 `
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].& ~# a1 }& r5 l  V! W3 `6 H6 q5 U
  7.      200MHz / (2*2) = 50MHz
    3 P# _" [& S; w! g( ]( U) z
  8. */+ r1 C/ {2 G* e, q6 w5 x
  9. uSdHandle.Init.ClockDiv            = 2;
    / ?# Z0 p$ {3 n, H2 P4 H% J! q5 \
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    / ]! M+ s/ L" G# \7 i' G" v5 s
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    2 }* g5 }" |/ Z" I
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;- k- A% D* |1 J; K0 T3 W) i
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;( s* y) S3 T* O. H; q8 z
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    5 p5 J) S& ]- z( C, Q
  15. {) i! t  b& Y6 H3 R& F
  16.    sd_state = MSD_ERROR;
    . _0 V( y. G5 ^1 z: n7 }; K! U* Z" ~
  17. }
复制代码
# q! i; C4 E2 a8 G
87.4.2 函数HAL_SD_DeInit
. N9 S4 V# F$ L5 [$ A2 D& T9 Y4 W
函数原型:& N* ^, B+ a$ H; p, v

  t# S, X9 N% T: j3 Q! M
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    ! ]+ y, z  t9 t! n
  2. {+ d+ D3 V; ^6 t
  3.   /* 检查SD卡句柄是否有效 */
    8 h' y7 Q( @( m" m* k- U
  4.   if(hsd == NULL)
    9 [8 M1 B4 b) q" x0 {( V( C- `) N
  5.   {) w1 Y! z" p4 U% g2 f4 p
  6.     return HAL_ERROR;7 i, F  k6 d3 i5 @. W( D$ W% x& a
  7.   }2 n, T3 E2 `0 \4 T* Y
  8. * y# z  k7 D+ N2 \- B
  9.   /* 检查参数 */3 H( N3 R5 |. t! ~$ J
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));6 b' H" S; A2 v6 @! O7 c

  11.   [( D% O9 N( m5 o
  12.   hsd->State = HAL_SD_STATE_BUSY;
    ! Y+ a8 E9 T! r/ S

  13. . i% D6 {3 D8 c( E
  14. #if (USE_SD_TRANSCEIVER != 0U)
    6 S) z1 Y( M3 F; t/ y
  15.   /* 关闭1.8V模式 */2 j" L' l4 Z! T7 }, e1 h
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    3 c3 s6 z, d# f; o5 ]7 r
  17.   {
    7 X. a- z. k) _' f+ \4 e
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    , {7 T1 x5 B5 E
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)
    ' u8 M: u6 ^! T0 ?4 P
  20.     {
    # r8 B# t9 i  X8 X- a7 ?4 V$ B  `
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;' `) U+ k3 ~. s6 E, u
  22.     }
    4 k/ I/ L" T: H$ P- p7 Y
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);4 N0 K- J8 X8 G! [& I9 T
  24. #else
    ( q$ C5 V3 g% b2 x
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
    # `7 m7 Z0 g8 `3 U
  26. #endif 9 ^/ a: y$ U" F3 h& ~3 k$ m: ]
  27.   }                                                                        
    1 f! D' a, V. U& \; {# C2 e
  28. #endif# L/ L; W. h9 B7 R3 [" ^/ o

  29. " k; c/ j" ~( R5 Y$ z
  30.   /* 关闭SD卡电源 */
    - n, [3 V! A; ^' D! H
  31.   SD_PowerOFF(hsd);
    ) P7 |" ^9 o" C7 e: B+ Y$ ]/ _* e. b

  32. ( F" d: m: }' {9 L: ]
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)0 m! r! Z7 y) z2 E: O
  34.   if(hsd->MspDeInitCallback == NULL)
    + ^, y; T! e( O9 M
  35.   {' c  L7 ~% [3 i3 c4 n  P
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;% g$ B$ V1 T3 Y: W0 B2 s: D
  37.   }
    ! O. U4 G5 ~* |: L) X" P6 l& Q5 g4 l; T' @

  38. 1 |4 S! ]8 `- ~, y9 V8 {7 \" `
  39.   /* 复位底层硬件 */4 F3 I! u% \' }& b; l: L
  40.   hsd->MspDeInitCallback(hsd);7 V  t7 X7 ?) ]2 S  V
  41. #else% g( F0 d$ [: K8 ~" L5 W; j$ h
  42.   /* 复位底层硬件 */
    % q  _) J- U8 j& e, b, c2 Z9 c% B
  43.   HAL_SD_MspDeInit(hsd);
    " K# p" }4 O0 i: q. g3 k% l
  44. #endif
    : I% x# ~  l5 ^: ?0 Z

  45. 8 g) m$ H$ t5 N) z7 o  N
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    : F. D! ]0 h' W! \' `4 v6 e6 T, |
  47.   hsd->State = HAL_SD_STATE_RESET;6 G0 t6 d# g# D( K% @) z8 {9 D  u
  48. ; A& O: g8 ^" t( c
  49.   return HAL_OK;
    1 f- J; r; Q. @* d. b
  50. }
复制代码

7 x' n0 [8 B$ E函数描述:' N2 |  E- r& D$ [2 C% ^  \3 V
2 Y/ U) G' ]  p. J
用于复位SD总线初始化。. P/ S: q7 H, Q. [
7 o+ R$ `2 j$ O# ~) Q* K! W6 ~1 G6 G
函数参数:; u2 _% ], _% F$ d1 J
3 e. T" N" Z5 J% W" Z, r0 z
第1个参数是SD_HandleTypeDef类型结构体指针变量。5 n9 T0 ~! W0 z$ b9 f  r+ f8 L
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
/ M* }  J9 t7 o) x/ J3 O5 K
" S& ~: ]8 ]- Y+ h87.4.3 函数HAL_SD_ReadBlocks7 u9 `8 D* G! }7 C$ [9 U3 @$ b
函数原型:
; y0 j& d3 v& R% V& V) N5 P; r8 B( k
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    ' X1 J  t) Q. H
  2. {! Z* L& a; a9 B
  3.   SDMMC_DataInitTypeDef config;
    2 b& O' H! G" k$ [$ y% o
  4.   uint32_t errorstate;
    , u; O! p0 ?) R
  5.   uint32_t tickstart = HAL_GetTick();) ~+ a+ V0 L  A' T
  6.   uint32_t count, data, dataremaining;
    3 ^# W* n9 j. a/ H% v" z: u
  7.   uint32_t add = BlockAdd;
    " v) o# ]0 I- |% V6 _7 L9 Y3 f, u; h6 a
  8.   uint8_t *tempbuff = pData;3 j1 D/ i  B0 h
  9. 5 L9 u, F& g  Q' f6 E
  10.   if(NULL == pData)
    7 p% V" {& J+ \/ o
  11.   {$ n0 a2 i7 B/ `$ C5 d. r
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;1 L# f2 Y8 f, v" J8 c  t
  13.     return HAL_ERROR;& [6 u. @: A2 i+ M! S# ]) B- c
  14.   }
    % _5 Q" g7 a9 y5 Z0 _

  15. % x$ H$ |9 @- {: s
  16.   if(hsd->State == HAL_SD_STATE_READY)
    , T9 v: p; e3 o8 j5 @
  17.   {" e( {4 a. o+ Y9 U' }* _- p- G
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;- D% L1 R# A3 ]" T

  19. # h$ n6 j1 {; g3 v5 m* t
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))4 l  ]# k) M5 Y7 U! K0 _& @
  21.     {
    ; F; o) @/ g# e$ {; T6 a
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;( U" f: P" q5 `
  23.       return HAL_ERROR;& k# b1 k* _$ i$ b1 h/ `
  24.     }
    3 G8 j1 \: f3 C. x% ]2 B7 K) W' Q
  25. 2 l# {. d8 B7 r4 f% W* F. y& G0 H
  26.     hsd->State = HAL_SD_STATE_BUSY;- Y( u( G) |- U0 q5 }
  27. , b$ q1 @# E* A. M1 N( W6 w
  28.     /* 初始化数据控制寄存器 */
    ( h: e& {- R: D  k; S
  29.     hsd->Instance->DCTRL = 0U;
    + }1 C& F. k/ P8 L1 d+ V
  30. 8 G6 |2 N% Q6 O9 I8 ~; w
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    , ~6 t8 U1 z9 r
  32.     {
    , v) L" P# T- f! Y; U
  33.       add *= 512U;
    . y6 {5 M; U5 g+ k7 Z- ?9 o
  34.     }8 M* `# i6 U9 F' U2 C

  35.   F) q/ g+ M, d2 A
  36.     /* 配置SD DPSM (Data Path State Machine) */
    & E# U9 X" p  ~4 f, [5 u" C: o$ Q
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;" b+ Z' w! ~% }3 \" z2 w
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    . V2 d5 t& H  W
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    8 y/ w- \8 ]6 X8 l( u  p
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    * s% g* m. n# S6 V. Y
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    % {% z$ R9 c# s
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    ( D" M+ w8 \# ^; m( i/ i9 I
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
      S0 {* u' d: s/ X$ r" {' j
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);4 ~6 _5 @8 r" x. P5 F
  45. 5 u% C, L# x4 l' b
  46.     /* 查询方式块读取 */" |% @6 Q( G& d  W( p# |
  47.     if(NumberOfBlocks > 1U)+ E; K9 a9 t6 t: t& _0 Z& V, V
  48.     {
    : l% ]8 M1 G( V# H
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;: [1 A- H5 J- o  k9 t! n
  50. 5 h: R6 s7 i  U  h, y- D7 z- ]
  51.       /* 多块读取命令 */4 w" S2 [. H( ?1 x% W" }
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);; X; [; b# w1 K- J
  53.     }% \% A2 ]( A# o" h* V5 Y
  54.     else
    6 n' G) o- O  Y) r0 `" {
  55.     {
    0 ]3 V' I/ \9 @8 d6 e4 u$ H! N
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
    $ K4 f7 ?9 N( G8 u6 Q

  57.   o! `0 D! B" R6 K* F8 f/ z
  58.       /* 单块读取命令 */; V, ]" H% v- r& N1 w3 m( t
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);2 _, E+ s: \+ y) d
  60.     }
    ; W$ n3 n6 ?2 X4 K
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    " [- M$ a1 l/ C
  62.     {% p" F# K6 t) p9 r) }; v, K$ W
  63.       /* 清除所有静态标志 */
    / ]  E; h+ v3 _( _6 y6 N
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);7 p  h% r* o# \- Y; ]  @
  65.       hsd->ErrorCode |= errorstate;
    % m6 g0 f; N' z( x) [$ x, T
  66.       hsd->State = HAL_SD_STATE_READY;
    " e7 b" r" M) t% r. A! `
  67.       hsd->Context = SD_CONTEXT_NONE;& N4 a0 K- U/ G- M4 a) I1 B
  68.       return HAL_ERROR;
    ! e, r: _$ B3 a% }7 W
  69.     }
    3 ^, ]7 L, G' s) e& j
  70. % T  p5 ?8 X3 L4 v" X/ f) r
  71.     /* 查询SDMMC标志 */( q: ^& N8 }5 Y# O' C8 r
  72.     dataremaining = config.DataLength;
    2 N4 b3 U7 k" d" V, t
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))0 @) H! x) c+ |- C: U9 A3 M
  74.     {' ~" ]9 N" x! @% T6 y, U  d
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    % Y  Y# j, L. J
  76.       {) G7 E& v9 p" M. z0 ~: o  S
  77.         /* 从SDMMC Rx FIFO读取数据 */1 N" E& {( K. C4 r. ~5 I$ p3 I
  78.         for(count = 0U; count < 8U; count++): t' B7 P) R7 P' k0 ]. C! q. v
  79.         {, j, E; g2 Z' R4 R+ Q, M
  80.           data = SDMMC_ReadFIFO(hsd->Instance);3 V: h1 _# @$ x$ o
  81.           *tempbuff = (uint8_t)(data & 0xFFU);6 `/ V7 C8 E# V& o* P: _7 S
  82.           tempbuff++;1 N, ]7 q1 U0 T2 M4 j, F
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);- `) V) v+ U2 U6 Q
  84.           tempbuff++;( w6 }( J" C$ |. i& r
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    / h, ~, i: p9 S2 R7 s/ @, }2 F2 h
  86.           tempbuff++;& X" r  q+ h8 M9 I! P7 [) r) L& K
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);; W- G0 \* Q2 ~" A9 X/ Q( f
  88.           tempbuff++;
    . z6 T- l& o6 T  E' f; g. b* K2 S
  89.         }
    . l/ o0 o* {7 W* S$ Q" D
  90.         dataremaining -= 32U;0 ~5 y+ [% w( B& R
  91.       }
    4 K) _5 O$ B6 R7 d9 B  r
  92. ) l* |, t  ^3 U! K. t
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    . ^+ l0 d1 m) W& @& \- j
  94.       {
    & c# O: }$ E. w, X6 R# Q! A) z6 e
  95.         /* 清除所有静态标志 */: ^8 i  g, @  ~, t+ a
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);7 e/ P! @) \, @, b
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;1 Z  o9 N  u/ |. I. x3 E9 X/ Z! C
  98.         hsd->State= HAL_SD_STATE_READY;5 I4 M$ o5 f% z# [) Z! [" b  o3 E) {6 w
  99.         hsd->Context = SD_CONTEXT_NONE;% @6 S" Q. f, S# s5 U0 K
  100.         return HAL_TIMEOUT;
    ; Y, N( p$ v, c4 [
  101.       }+ z9 `  t$ B! H5 Z
  102.     }
    * \+ \8 d7 O# }, G* W
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
    4 @+ L6 \  V0 w# ^7 }

  104. 7 x3 y+ E# |  ?/ B* S
  105.     /* 多块读取发送停止传输命令 */- ]+ n* n& l4 C: r- ^4 D
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))8 d. |; |5 c* u1 T
  107.     {& w; y( H' O# H- o) o
  108.       if(hsd->SdCard.CardType != CARD_SECURED)$ G2 j* i& t8 U; `  ], b
  109.       {0 h1 j9 K2 }; w( ]& c" J8 s) F- }
  110.         /* 发送停止传输命令 */3 N0 z) q( j2 _
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);$ ]0 L+ V0 u) D$ s  y7 B- z
  112.         if(errorstate != HAL_SD_ERROR_NONE): V; O( o/ a* n
  113.         {
    - q" f* l  v; j* d' ^& o
  114.           /* 清除所有静态标志 */
    $ x2 [4 b! u/ t5 a, {
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 Z3 E2 \9 w% i$ R$ l; r
  116.           hsd->ErrorCode |= errorstate;
    2 @: P- Q" E) o* e3 C( d2 ?1 R0 \
  117.           hsd->State = HAL_SD_STATE_READY;3 P8 y3 r3 H6 q4 Y2 ^  L4 O+ P9 K
  118.           hsd->Context = SD_CONTEXT_NONE;, z% I9 y" @* C
  119.           return HAL_ERROR;
    6 h/ f" [* X9 X7 a% z
  120.         }2 @; D. j$ J% E& W
  121.       }
    ! t* k/ c: I0 ]4 g
  122.     }$ u) M$ x( I+ s$ i

  123. 1 y) L& Y% r1 p" x3 j
  124.     /* 获取错误状态 */6 W8 T  i2 Z- ~
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))0 n. T' O' a. [9 |
  126.     {1 ?8 h  b' a( F" U
  127.       /* 清除所有静态标志 */! m$ }1 M& k. D2 a; l& m4 o; F: ~
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' p7 H7 r, l* ?
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    : ^5 }) _9 H0 p5 G3 X
  130.       hsd->State = HAL_SD_STATE_READY;) R2 j8 Z4 L5 t: r, K! o1 N
  131.       hsd->Context = SD_CONTEXT_NONE;
    0 X6 x+ M% C2 Q
  132.       return HAL_ERROR;+ c8 q# n, ~1 x8 }
  133.     }
    ) S# z6 j# ]7 F. M( o
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))- y8 Z* N6 |0 p; i. g7 i
  135.     {9 {2 N: g( G+ y, \' l* v: b
  136.       /* 清除所有静态标志 */5 r) y# U* F4 k/ t6 h) i  q9 ~# l
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);3 A- M$ H! e# c
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    9 p' ]- B" K+ z* i) I
  139.       hsd->State = HAL_SD_STATE_READY;* `' J1 {1 x" t. n8 a2 J( P9 N
  140.       hsd->Context = SD_CONTEXT_NONE;4 K. N. V% i9 ?4 [2 j
  141.       return HAL_ERROR;' C1 l- d% J% n! z0 b
  142.     }
    0 c4 p5 q: \6 ]. J% [
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))" [/ Z+ v7 h* h
  144.     {8 y1 `$ D  V* \8 j
  145.       /* 清除所有静态标志 */
    4 ]' \3 H. x  x: h) J
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: i5 \2 L% {5 t2 j4 C
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
    : x7 l! T9 T' O' h! u4 @* N, {) |
  148.       hsd->State = HAL_SD_STATE_READY;3 G# P. W  o  R: R+ {/ Q( a
  149.       hsd->Context = SD_CONTEXT_NONE;
    + S7 O/ J. l# c8 o! C& n1 Z2 ^; G( W
  150.       return HAL_ERROR;
    : \2 `# e; @8 E* w* e
  151.     }& Y; e7 F$ d$ p9 {
  152.     else1 @* A8 o3 \4 E
  153.     {
    2 O+ z( V$ n, C! K2 O7 \
  154.       /* 什么都不做 */1 ?6 Q) w' |1 l! g. D  _
  155.     }
    $ }6 J- U8 d. B& ]
  156. . O* g5 O4 u/ E3 T4 g. g  P
  157.     /* 清除所有静态标志 */6 c- e* x- W- U' X- z! `
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    - w8 c! V! i$ m6 N1 ?6 l0 j: B

  159. 7 \3 j) \1 a' A# o
  160.     hsd->State = HAL_SD_STATE_READY;+ U' ~% ]# S4 y$ e% d5 t

  161. ; W6 {0 q% n/ e. z8 L, F
  162.     return HAL_OK;
    5 j3 M5 a, X6 W- ~' t* T4 A
  163.   }
    6 q' ?: |* n3 z: z! j" j
  164.   else
    . W$ A$ O6 u2 y! }8 C
  165.   {
    % ^$ O& |( P' N1 f2 I6 C
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    . l& s* j6 D/ C& e6 G
  167.     return HAL_ERROR;
    3 p2 Y8 Z" F' |7 L4 i
  168.   }
    5 |/ c# T9 D* r( r( F6 \! P' V4 v( Z) R
  169. }
复制代码
# y( ^: ], L" _7 f
函数描述:
/ G; c) t( u; a  O
, \9 l% M/ G7 q此函数主要用于SD卡数据读取。
& R2 j: a8 D8 V/ a1 R' o+ R6 L
' Y1 ^$ T2 y4 |  o函数参数:, j9 f* A$ v* u- A

' e) [& _/ Z. I1 Y$ _" G  第1个参数是SD_HandleTypeDef类型结构体指针变量。! B/ @9 j" T; O5 K5 I7 _9 [6 Q
  第2个参数是接收数据的缓冲地址。
, E7 D/ `, r* U( p  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。, V3 B4 |3 e4 [
  第4个参数是读取的扇区数。& W2 H) b$ c) f8 L
  第5个参数是传输过程的溢出时间,单位ms。
! O5 _- W5 ]" G, r4 h% |; D  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
4 D8 W. b  T# k$ Y, Y2 g8 s& {, m, s$ b* h

7 O" o' S1 ]& K  m! d: n1 y2 M使用举例:
2 N9 m$ \$ Y8 W1 C0 Y
' E: z0 F$ c+ H, H5 v4 k  l
  1. /**
    2 i! @6 s1 l% H  n8 i0 O
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.! T& d+ {5 _& ~& \
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    8 g! e: P$ P' e$ Z! B# d
  4.   * @param  ReadAddr: Address from where data is to be read
    9 ^2 ^( x5 T" S# ^8 Z7 n7 o
  5.   * @param  NumOfBlocks: Number of SD blocks to read8 K7 e! @8 Q% q3 A8 j
  6.   * @param  Timeout: Timeout for read operation
    5 k. P" R, T% E/ o' g
  7.   * @retval SD status" _  v* ~) p5 l3 i+ s/ D9 x; X; k& f
  8.   */& I4 R% q+ h( j0 a4 Z
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)( i4 I# O+ B/ }1 ~; ~
  10. {
    / t) V, x5 k9 r

  11. + o" H, C2 E# S* P, f1 U
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)) ]# V1 D) y3 ]5 W& K; K3 v0 h/ C
  13.   {2 y) i/ q" @& z- q) W8 V& h
  14.     return MSD_OK;: E6 N& r9 {: j" O% f
  15.   }8 w& g2 ]8 d( _  v+ Q0 B: S
  16.   else4 N7 G) Q5 B' ?7 t0 P
  17.   {3 Z6 G& @" W5 \5 E: ]) S/ `4 Q
  18.     return MSD_ERROR;
    3 R. a8 Y; W" c' D, t) v' B4 H
  19.   }: k( K0 a8 h% D3 C. P* k9 `
  20. ) z( a& o9 @' y: z7 h7 f" |
  21. }
复制代码

# K& x4 ^' y9 I& `1 P# u87.4.4 函数HAL_SD_WriteBlocks) x! [- O% Q# v" K8 J
函数原型:
" F* Z5 c9 f* Y# w; y
. q4 V: Z1 R! s2 _
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)6 @+ ^7 {! k. J/ B0 d0 G1 c3 r  Q
  2. {6 y( K) I+ Q) @# N' c
  3.   SDMMC_DataInitTypeDef config;
    ) j7 ~) d- k6 E! G' H+ y+ d, E
  4.   uint32_t errorstate;% [- H4 [2 Q! c. C
  5.   uint32_t tickstart = HAL_GetTick();# f  V+ X' B+ I+ V! }
  6.   uint32_t count, data, dataremaining;
    - S! W# o' Q" \$ \0 K
  7.   uint32_t add = BlockAdd;# i  a# L1 M) ?
  8.   uint8_t *tempbuff = pData;
    * s4 _5 K7 P* W# R

  9. " b  ?% G, Z) }5 v' g3 L
  10.   if(NULL == pData)! Z4 r2 L: M/ s1 N
  11.   {
    ) }5 [" f* d% T0 g$ W$ X2 a
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;# |7 F8 t5 i0 u$ q4 n: Z
  13.     return HAL_ERROR;
    + b) s  h& \. b$ ~
  14.   }
    5 H! E, _0 f+ f4 l1 {/ L

  15. 0 J( s* F4 [, d- J3 Y- b! f
  16.   if(hsd->State == HAL_SD_STATE_READY)
    8 q' a- h& q  h
  17.   {
    ( Z, O- z5 I( J: D+ p* q. G2 u' w
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    " T4 y) h7 b5 n$ M& w- O2 R4 ^

  19. 7 l" ~6 T& ?2 `# K  D- T! H* ~
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)). H; f7 j8 t" o3 E( u  g; D% a
  21.     {
    " W" T1 s0 I" G0 t$ k6 S
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;; {" F4 p: W' F* G4 W5 N/ o$ r5 {
  23.       return HAL_ERROR;
    3 j# D3 L! ?- x! z2 t
  24.     }! p1 `' B# r% M1 B0 p3 h
  25. # a# o% r" X. a& C0 A! w* V, p
  26.     hsd->State = HAL_SD_STATE_BUSY;
    ! i$ L' u/ ^+ n* s% U7 A* Y( T

  27. 3 @$ p% A; K% w5 J: j% O  i
  28.     /* 初始化数据控制寄存器 */
    " w* z  p3 o$ I* ~4 e
  29.     hsd->Instance->DCTRL = 0U;7 Y6 \5 k  @1 A1 M3 _+ b* R  a

  30. & q# S, [5 y# N& g- u. }2 I
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC), \/ b' }! B! p, ~& }
  32.     {
    7 k2 ]. a/ W; e5 ]8 V9 ~
  33.       add *= 512U;( |+ v" C  P* X- U6 F3 U
  34.     }0 w. d& @3 C( `  S0 m4 O% D9 l" m) [

  35. ) P. J4 W8 l' ~0 w3 O
  36.     /* 配置SD DPSM */. P# t+ n& G! k" c* \& L
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
      ]- n( n" v; P% x2 B1 Y5 X& f8 A
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    6 U  Y8 w0 l- o$ n4 O# T7 ]; T' l
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;7 q0 Q6 M; F) B8 o6 f3 V
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    % B1 q' J) }4 J/ _. f6 z+ t
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;8 i3 r! D" V! C5 M
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    * t+ Q7 u/ \9 [# t
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    ( d8 z! n0 e7 Y8 a; Z! l6 |: U
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    9 x/ G9 W! s4 S, j. @# R- Y4 p

  45. ( J/ M4 }& N5 v
  46.     /* 查询方式块写操作 */
    3 c9 x- t5 q' r  k& E
  47.     if(NumberOfBlocks > 1U)
    & j2 `  ^0 e- C+ _, l
  48.     {
    2 Q1 [' k' V) ]0 o; g
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    4 H( e5 p; s6 |( m

  50. 5 M# m) m: q6 v# ~& F
  51.       /* 写多块命令 */
      `# \: z- Y- w5 N
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    3 t& {3 ?/ D7 m6 c
  53.     }' H5 @6 [( d6 `& T
  54.     else
    , G; ]; t! J; a  ~- }; e  @
  55.     {# b# w+ o4 j+ l" [, Z8 r
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;6 F# F/ _6 s5 V% e/ n$ Q) r8 Z
  57. 5 n( ~5 U' h, ^+ E
  58.       /* 写单块命令 */
    ( f) g& |" i1 T( Q; n" E8 q# Z9 j* m
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    ) j2 @5 f2 y4 F% A$ E
  60.     }
    - p/ T& C/ M8 B+ A$ g$ J- Y
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    : S" N/ A) h, J2 m
  62.     {. N+ l1 w4 P6 ~( G; m* X6 X+ H
  63.       /* 清除所有静态命令 */
    ; X, C) `) h$ e& B5 v9 E0 ]; S( d
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);& r  f$ x& t4 [& v. g: ^2 q( O
  65.       hsd->ErrorCode |= errorstate;& ^5 F% v( G. A" T/ M/ c4 F
  66.       hsd->State = HAL_SD_STATE_READY;
    ; u  F) c" H. L: f( ~
  67.       hsd->Context = SD_CONTEXT_NONE;
    ( l' o' ]2 S9 U# r+ I2 J
  68.       return HAL_ERROR;
    % z- N  [& K# Q$ |0 o! @
  69.     }
    ( N& J, I, ?7 f! f
  70. . O: E  G6 a( E; J
  71.     /* 查询方式块写操作 */+ P2 N" I% n' c$ y
  72.     dataremaining = config.DataLength;
    ' d8 Y7 a6 W2 x& @$ T; R* Y
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    5 t! \6 y: P, _2 r% X
  74.     {# I1 p3 V1 u! C, j
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))# V, l% f+ h4 }$ z
  76.       {
    + q& u+ p% F2 [3 [& G$ U
  77.         /* 写数据到SDMMC Tx FIFO *// `$ t1 j8 ?: k, }
  78.         for(count = 0U; count < 8U; count++)# D# y+ m2 y8 w  i, D2 [! e0 f% u; A' z
  79.         {
    : d$ X' d2 z7 s/ ?
  80.           data = (uint32_t)(*tempbuff);
    1 H4 t+ X$ I3 ]. w; h
  81.           tempbuff++;
    ; S# ^8 D) F4 A
  82.           data |= ((uint32_t)(*tempbuff) << 8U);- R) I# m: E) H' S
  83.           tempbuff++;; w5 ^6 O* P+ o6 V0 B: C
  84.           data |= ((uint32_t)(*tempbuff) << 16U);2 T7 G+ N) r& @, n. M, T- Y
  85.           tempbuff++;8 B0 M2 M0 @/ U& c' X: A
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    3 `  \* J7 {9 S
  87.           tempbuff++;/ L* h1 q7 O$ z: C
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);1 ]  k! d+ n4 i7 u% c! z) s$ d2 }
  89.         }
    % N6 P  M  h5 r8 t, s
  90.         dataremaining -= 32U;9 ~: Y, }0 ?& W* I3 D6 O' g
  91.       }. ^. e6 E$ F+ q4 }6 b% O
  92. 1 N% B8 B7 [( Y  }' S# v2 g. L
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))2 U6 g' s, D9 |; w
  94.       {
    / J# [; r) W3 C% P
  95.         /* 清除所有静态标志 */
    $ w3 g/ J( T7 Q
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);% [, P3 M4 h! Z. X+ p* o
  97.         hsd->ErrorCode |= errorstate;
    : l" R: C& _5 C  {
  98.         hsd->State = HAL_SD_STATE_READY;7 \4 H4 |( y" C
  99.         hsd->Context = SD_CONTEXT_NONE;9 {- T% w9 C0 {; U% `
  100.         return HAL_TIMEOUT;
    ( R0 X  A" k* @4 `
  101.       }$ M0 ~1 i1 c* ^9 p; `
  102.     }- M' ], @) _; S; l/ b
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);' u  Y) K" @% \+ W5 v! n$ M0 a
  104. 5 L: L8 N: v# {5 f& f8 m6 v
  105.     /* 多块写操作,发送停止传输命令 */  Y8 ?( }3 r: |9 C1 p
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    3 u, ]+ H2 `" t$ B* a+ }( p8 p
  107.     {# V% ]& V  V9 P
  108.       if(hsd->SdCard.CardType != CARD_SECURED)! W" C$ C* m2 w$ ?3 o
  109.       {* X" P6 o% @/ Y! q' x0 {
  110.         /* 发送停止传输命令 */
    7 E6 ^0 _( v; G: G9 I" I
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    3 T' f! T; o8 S5 S! x
  112.         if(errorstate != HAL_SD_ERROR_NONE)- C6 S, X% i+ @6 V* m. j
  113.         {5 e1 L9 @) a/ n6 R/ B) m/ z* G2 ~- M
  114.           /* 清除所有静态传输标志 */
    * g6 l8 K3 @% j$ p
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    / Z+ ^) V) j& h" {) N
  116.           hsd->ErrorCode |= errorstate;8 Z; s3 u# [$ H7 v+ b/ g& ~+ D! H% |0 \
  117.           hsd->State = HAL_SD_STATE_READY;0 t8 Z# f$ l$ Y  M: ?
  118.           hsd->Context = SD_CONTEXT_NONE;( P  a& H3 R' H% v% j
  119.           return HAL_ERROR;
    * M6 ?$ `5 J4 A4 r# {& I, n8 h; l
  120.         }
    4 T0 |) r, A: B8 D' L) H  |
  121.       }
    & B' [  p; g3 Y' U$ Q  o
  122.     }
    . |/ K6 ~0 q! n2 F, R6 r9 D8 d

  123. 9 u* U3 _! _# }0 X. h% \$ E
  124.     /* Get error state */
    / E; c2 ?0 N: q, G; o) v
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))/ y: o4 g. Q+ A: e8 S2 U( e  H
  126.     {
    7 H: I$ Y7 T9 ^9 `# v; p1 ]" \
  127.       /* 清除所有静态传输标志 */
    - f) ]7 C1 p, Q
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ j3 t/ t$ ~* K
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;$ p% U% ]; t' }
  130.       hsd->State = HAL_SD_STATE_READY;
    4 k# v$ c7 Y: M% M2 L" `4 o
  131.       hsd->Context = SD_CONTEXT_NONE;9 }# m6 n# `0 [1 h  t$ ~9 m* q
  132.       return HAL_ERROR;7 [7 ?& N( |" x% ^
  133.     }1 e& v2 B* a, y& Q# g
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    - I* A& x# V; f" w
  135.     {, j3 A0 A+ g9 x, T" {
  136.       /* 清除所有静态传输标志 */7 e. B/ }  j7 y9 A- M8 l
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);# n3 j1 F2 u- U. a3 `8 F2 V+ Z, f! P9 \
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;) J3 S6 h+ g# ^" {( f3 l1 a2 u
  139.       hsd->State = HAL_SD_STATE_READY;
    ' `) A- v# W. _& N% d2 Z) N" X. I
  140.       hsd->Context = SD_CONTEXT_NONE;; {' V! o, Z) E/ _) k* Q- d
  141.       return HAL_ERROR;
    9 Q1 Z8 ~# V# D& x+ J
  142.     }- z$ S# {+ d/ W7 t- i# P# L
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    + U6 V  ?* o( m8 X  h
  144.     {# M. x& ~9 U6 _5 u4 N( o2 N# @" j
  145.       /* 清除所有静态传输标志 */
    1 f- w, }4 E5 h! n& {5 U: E6 g6 i
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);- H6 Y! B8 u4 D& N3 O: d# U
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;' g1 d# A1 {1 A+ ~/ @6 y5 F
  148.       hsd->State = HAL_SD_STATE_READY;% M* v* W+ `# i
  149.       hsd->Context = SD_CONTEXT_NONE;  B3 z" N2 p7 _9 y% l$ N2 m4 J" J
  150.       return HAL_ERROR;4 g7 p; q/ D2 i; F' R
  151.     }& t2 s- V% y; C& h- \
  152.     else# G, L* J$ h- i$ Q
  153.     {
    ! f! z+ M2 Z( ?" [6 v& C/ Z* J  G
  154.       /* 什么都不做 */
    $ S4 d- i7 h$ L* B5 {$ ?
  155.     }
      q& N2 ~$ t5 Z0 y" h

  156. : G2 v' c; u7 T: e
  157.       /* 清除所有静态传输标志 */
    $ b; h' d- q6 I: [6 `$ ~* Q
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    ; ]- A- G6 w5 m" \& p

  159. ! ^, p0 \, ^0 N+ a
  160.     hsd->State = HAL_SD_STATE_READY;
    ' }/ a# q' r2 [3 w4 @5 |. H

  161. ( j9 D9 u8 v$ H7 h8 S
  162.     return HAL_OK;
    ) S8 r! `+ P" p$ @7 c  S
  163.   }
    $ n2 [; n( x5 Y0 b1 r
  164.   else
    ; d& w$ i0 `5 G8 `
  165.   {
    # i7 e6 b: I) X+ D/ {; Z
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;) X+ G- k2 m0 w4 q7 K2 |$ U
  167.     return HAL_ERROR;
    , C# w0 ]! _. a8 s3 T
  168.   }, ?( M7 g4 X. V& _& |
  169. }
复制代码
% O8 c1 L% @, N
函数描述:
! D$ J$ Q% [) U
' L, b1 X$ f* Y+ {) `此函数主要用于向SD卡写入数据。+ ~* [+ w- }1 o* [* F

, P1 t% A6 {. d' O函数参数:
0 I/ n+ C& Y7 F
6 ?1 u+ T% `9 @& |$ e  第1个参数是SD_HandleTypeDef类型结构体指针变量。, s' |3 C! p$ |' F6 [8 r0 ?
  第2个参数是要写入到SD卡的数据缓冲地址。
0 r( J* A7 G1 R7 T  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
7 q; Z0 G$ T! }9 B/ E$ `, S  第4个参数是读取的扇区数。
9 J- s$ Z+ [9 k  第5个参数是传输过程的溢出时间,单位ms。# j9 f5 C% e6 f
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。+ h7 M# m5 e9 T4 Z2 U

$ S1 q' D- z5 G9 O9 C1 ?, A# S  k: [8 i$ v0 i2 g5 D) d
使用举例:4 u8 n9 y  {, \9 N, I
. U0 Q7 [7 [) x% r) w
  1. /**
    7 B( ?& u; i& ]" {& h: t! W
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode./ W# M' ~+ X- [0 d8 `. Y
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
      Y' A/ X1 z5 P& V$ }9 ]6 Y
  4.   * @param  WriteAddr: Address from where data is to be written
    # c4 Z$ a$ u, T4 I7 n
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    5 f0 Y1 ]. ]& Z
  6.   * @param  Timeout: Timeout for write operation4 I9 X4 ?6 D8 y" t0 i
  7.   * @retval SD status8 g4 _5 F; Z  a& Y2 Y
  8.   */- X* p- \: `# j* l8 a( e
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    $ o) U9 S! I2 E; {  b
  10. {+ I4 x( b3 t+ W4 P, D) O# T7 N2 s% ~  X
  11. 1 f8 u9 N' Z3 u, |% |  D
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
    - U$ z" B. q  i
  13.   {( a, m3 \1 t9 }! D6 h& H
  14.     return MSD_OK;3 {) D' S( x( B  e! p
  15.   }
    - W5 \8 N' U( i7 g) ]
  16.   else# C) u: z% \7 f& }9 t- L
  17.   {
    - f/ I6 F3 z6 P9 Q4 q; P
  18.     return MSD_ERROR;
    " n" L2 E) M/ w( |. y6 a
  19.   }) u( H! Y  ?( Z8 [/ I
  20. }
复制代码
' t0 e' D1 N% S
87.4.5 函数HAL_SD_ReadBlocks_DMA
9 r* E/ }, K% g5 z. q" Z' @2 L
函数原型:
& N3 z: n! U# S- \( \
9 @; D6 p+ c( {2 n1 {9 X* n
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)' e3 L% p* h: f- ]9 R
  2. {. B+ ^9 H" ]) n/ @  c
  3.   SDMMC_DataInitTypeDef config;' Z/ ~3 {6 i* \: ^
  4.   uint32_t errorstate;. S+ ~) {6 y5 e! c
  5.   uint32_t add = BlockAdd;" W8 ?$ v3 U, z3 A

  6. 4 f) s& \/ `% m$ O9 D
  7.   if(NULL == pData)
    ! `- B9 F5 a3 X. Z" A
  8.   {
    ; X& z  X: p' \% l. e' h% {
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;$ H9 O6 S, g/ Y0 q* B$ c4 l; F
  10.     return HAL_ERROR;& g2 u  J5 G2 r7 l% q, G
  11.   }
    . J- S2 @9 V" W6 |0 C

  12. $ ]& _; C! P5 a/ D. s
  13.   if(hsd->State == HAL_SD_STATE_READY)
    - i) ^2 d6 k; s: J! k; N
  14.   {; {: p, ?4 l7 d( s
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    , f* J+ {  U4 ]8 C  d* g. V5 @
  16. , N9 t) c0 a& Z/ d
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))0 t9 h9 `; o1 I9 _* N7 n5 x
  18.     {
    ' C4 t6 j. Z" k" {
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    1 `+ J/ A4 V$ I6 W+ I/ O6 E
  20.       return HAL_ERROR;8 o! l/ ^, D  z5 r. I; q0 n2 `
  21.     }
    . z, w# |  l+ @9 s2 {+ }

  22. 8 Q1 D" ?5 ]) r; Z. G0 ^
  23.     hsd->State = HAL_SD_STATE_BUSY;+ M; H7 i6 z) Z) K& ?* }/ ^6 d0 G  T

  24. 5 v6 L/ b% ^. W* e1 Q5 P/ F
  25.   /* 初始化数据控制寄存器 */
    2 f1 G4 o  ?; c9 Y$ ]
  26.     hsd->Instance->DCTRL = 0U;
    ' f# D( ^: b1 a9 c& }% U

  27.   Z% f+ O9 ?4 i7 {2 U! q$ o+ ]0 v1 q
  28.     hsd->pRxBuffPtr = pData;3 \3 M& I3 E& [# l: L4 N
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;$ I( W! B) ?. y: k- w
  30. # S& d) x5 g4 F1 [# S" }
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)% e* V4 d. X- T; {
  32.     {  x  w! p, \  W/ J; K, E" r
  33.       add *= 512U;: R) Q4 n7 Q1 |  t
  34.     }
    # H1 L6 Q$ T6 s* C. _+ D2 ~
  35.   Q' b- U" ^; k  o' u. i3 L4 X* W
  36.   /* 配置SD DPSM (Data Path State Machine) */8 E/ R( j( b7 g( e" a2 Y! r
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    ( ~; k" N% o" e7 R2 b' O, ^; k. N  ?
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    : i8 e2 H3 |; {) r5 [' A$ q" \
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;. k' }6 G% U( u! q1 E' M1 X
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;; |, H* f+ h; Y/ P$ c8 C8 H1 S
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;) u( [; v0 a8 R
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;- e9 w4 ^" a5 C  h( Q
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    6 r7 u& j; l0 I5 L! ~7 W$ y

  44. 2 M3 Q5 O/ i0 b) M+ j
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    6 X6 i/ N9 k4 V3 s. _
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    $ }6 x) _* \/ g7 W, R
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;  x# b. b% o; Q- V8 A" E; n% |! Z

  48. 5 [# c# j, v. ]3 P
  49.   /* DMA方式读取多个块 */
    ' p- E9 d/ j* _/ J
  50.     if(NumberOfBlocks > 1U)
    , @' k3 W2 C. \, {
  51.     {
    2 a. v/ G7 P$ t9 G1 ^! @
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);. @0 x$ Q% w6 y$ k2 G9 a7 \& R
  53. 8 ?" ~6 Z% O/ ^% ]
  54.    /* DMA方式读取多块命令 */* S! N, C! [- [' r8 }- P
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    " U. E  @. L6 b  e* D% a
  56.     }
    - X) V0 Q: Z$ L, s4 ^" c" [2 i
  57.     else, m* B; `0 M" Q- X
  58.     {& _  T, V1 i$ d+ C; P7 v
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);7 C  m5 `! V. o/ R) E9 u; l
  60. 5 S  {% m2 t7 T1 G* w
  61.    /* 读取单块命令 */
    : g, p& l8 a  o% |8 ]
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    3 |0 Y$ Q. ~: p! k
  63.     }
    7 W( O) A4 U4 d1 d- r3 x- u7 i: Z4 u+ E
  64.     if(errorstate != HAL_SD_ERROR_NONE)' C9 p4 d; M  G; j
  65.     {0 s! L1 K- M. B4 O  o0 O/ Z
  66.    /* 清除所有静态标志 */
    6 y4 V0 l  W  F" l* X7 ^$ M
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    / E4 v8 ?' V# L$ Q4 l* Y4 ]$ D
  68.       hsd->ErrorCode |= errorstate;
    % b8 x: J! D" p& X! {" Z
  69.       hsd->State = HAL_SD_STATE_READY;' s+ H; G; k( S8 y, J, l2 H1 I
  70.       hsd->Context = SD_CONTEXT_NONE;
    ; C7 e. T7 i% V: c3 ^7 I9 Q2 b
  71.       return HAL_ERROR;8 p% w# b3 R* ?4 }3 F
  72.     }
    ( \; u, R( R6 _$ Y0 e; u

  73. , s+ s$ s$ O+ }' |
  74.   /* 使能传输中断 */: P3 S$ B/ E3 k; n$ L% P3 m% h
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    . h# P& z% ~& s6 m

  76. & U* Y" A% C* `6 f! u, x
  77. + F, L0 Q  O4 ?6 K" x1 w
  78.     return HAL_OK;  B$ M% U4 q5 b3 z1 s5 X6 u& l
  79.   }
    % o. F. o* r2 {/ g3 U! O
  80.   else. b. N4 v+ F% }, u
  81.   {
    ) U( s9 l0 ]/ r
  82.     return HAL_BUSY;& K5 Y, F6 p+ }8 t
  83.   }. `+ F2 L4 |0 m0 a' R
  84. }
复制代码

7 G1 _! \% k  h& K  I8 z函数描述:
: E: t8 P: O) y  M6 ~) `
) R: {  r8 T5 k) Q1 r此函数主要用于SD卡数据读取,DMA方式。
/ o) `5 d9 L; S. J8 g* o; N5 j/ u* l1 D1 x# N  @! n, @2 c
函数参数:
! K6 ^" I' V1 Q" N0 x3 m3 D2 C( ~. |, u
  第1个参数是SD_HandleTypeDef类型结构体指针变量。/ n' b6 S% N6 d
  第2个参数是接收数据的缓冲地址。5 K" u$ T, h# Y; q) e0 N
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。: l7 ^( F; Y5 l: `
  第4个参数是读取的扇区数。
- J% B- c8 e! X( h$ S$ E  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
' T7 I* Y$ \3 A0 F) d
2 r- K' Q7 T$ I  }" G9 s
0 {; A+ P4 o, p5 j$ g5 J! G使用举例:/ Q( q4 T) z. F7 ^# T
- i% Q9 \) `- J
  1. /**
    0 r5 d3 Y2 l, F" L( E, p
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.- W( ?; J% d2 n0 h% q
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    ) ^1 w" ?3 i( g+ X. b& ]
  4. * @param  ReadAddr: Address from where data is to be read' o. o* O; V9 q0 M- \& W
  5. * @param  NumOfBlocks: Number of SD blocks to read
    % z% a& v2 Y9 i, A% L: F0 T
  6. * @retval SD status
    & D) S% E' ^. J. J: H' X* P1 u
  7. */# @( j: L# h. \. m
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)! K( C! l! ]' `4 S& R6 \5 H
  9. {
    ! u  h0 I# e, |$ F, i
  10. * |: N2 X" d1 R( n
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
    ' X' b: C; `# F; k4 N7 V$ M
  12.   {( q' N1 P; ^/ f% p4 H
  13.     return MSD_OK;
    9 H. E+ E) ~7 ?1 k
  14.   }+ c. Q. z# ~* R9 I! e& P
  15.   else- T7 @- y3 N* w* X& h& @1 i8 Z
  16.   {6 r3 F7 u& B* T' ~
  17.     return MSD_ERROR;
    , S1 l: V9 N+ b- K( |
  18.   }
    * \! C/ {2 b: f% @
  19. }
复制代码

& a1 R' O- G1 U4 M, `3 F  g87.4.6 函数HAL_SD_WriteBlocks_DMA
0 b, f1 p* K" N4 C6 c, H4 O, l函数原型:
  ]0 y5 z& {- Q' \
$ N  o: u& j3 W+ M4 P# N, F- r. U5 z, ~
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    1 c" y3 T0 F& y3 }
  2. {4 m. P. `2 ^2 x$ b" k. n  V
  3.   SDMMC_DataInitTypeDef config;
    # j! ?* X+ s# L8 K8 E- n& M
  4.   uint32_t errorstate;: b' N. t7 o0 }( O
  5.   uint32_t add = BlockAdd;; P" n! E# _( ]. X' M6 T

  6. ; K% T( W$ `- }# d! ?
  7.   if(NULL == pData)
    , G; S# a* t& D( E/ d, T3 z
  8.   {
    ; E% D- d3 d/ X' o. O' P
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    / d" e1 \, l6 a8 e
  10.     return HAL_ERROR;6 p) p2 s+ Q0 D& X$ u
  11.   }6 Z0 x3 m7 j# Y0 {) P

  12. 1 y" S3 }, }  r& L; ^% d
  13.   if(hsd->State == HAL_SD_STATE_READY)
    7 M+ f" I( @' B: R' N" _
  14.   {
    0 @# Z: |; [8 \  J
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;( e' H/ g' y- y! J: _( r! @
  16. # @0 D# n8 y7 _% O, X: v3 \5 _
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))4 M) w$ |1 x& i7 I  t7 G
  18.     {
    / _3 _* q9 M0 }/ i5 a' _9 i. H. r
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    - |8 N) P4 `% X6 k
  20.       return HAL_ERROR;5 @1 B& _5 I. M" [) T9 ?
  21.     }5 a8 W6 b: h/ n! b; U3 L

  22. 2 [6 J7 G" u/ o6 v3 {! F( m% [7 [
  23.     hsd->State = HAL_SD_STATE_BUSY;
    " T+ ~9 a. S! A/ Z" O

  24. . f) C, x0 c8 f. R
  25.   /* 初始化数据控制寄存器 */* |* e) j) e9 c$ F2 e
  26.     hsd->Instance->DCTRL = 0U;* |* ~# C' h! q

  27. 6 B/ L' Q% C1 z  m" v+ p
  28.     hsd->pTxBuffPtr = pData;
    2 T5 B( p# g6 x! m
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;2 Q8 m5 \, ^0 G; i
  30. - `, ?2 {5 ?! E7 A6 g; ]
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    8 o& U/ `- S& \- k' }8 h. d4 F
  32.     {/ g% o- y  `" `6 z, q/ w
  33.       add *= 512U;
    . p9 ?4 ]( t5 J4 r, j2 w5 V$ C8 o
  34.     }- _. Y2 M, O$ h' _/ k

  35. 3 {5 B+ S: d: b$ p/ N9 Y; U
  36.   /* 配置SD DPSM (Data Path State Machine) */$ Y$ ?3 C! _! {4 I
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;* ~: p" W0 E6 U6 O/ }+ T
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    8 n1 O) ?. S# z% ]% r* G! a
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;7 {) L6 ~, Z( w8 q  ]  |
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    , r& w& `& c3 E
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    " ]9 Y- J; ~0 H7 W
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    ) E0 v2 v9 q& O. g
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);& U( @- u5 b8 u; S/ |. e- f
  44. * [# W% A( D: c7 l2 f
  45. - |  ^- P$ q9 x$ A2 U2 \# s9 r
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    % ~% e+ u" W1 G' W) Z5 O0 g$ d; T
  47. & n6 b+ W: G2 Q0 M
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;, n' v- @3 y: {6 k6 W
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;" Z) g/ H% N6 l7 ~1 T2 W# @, t% L
  50. 9 {+ H  G6 l" v' _; j
  51.   /* 查询模式写块 */
    $ w: `4 V1 D$ U+ ]- b/ C$ m
  52.     if(NumberOfBlocks > 1U)! y$ ^$ I% R& J; [6 M
  53.     {
    / f* X: Z7 z% H
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);: z2 s3 {5 o/ u9 r( H# _% ~" k
  55. $ F0 @+ ~* W+ ?
  56.     /* 多块写命令 */
    6 @, R2 a8 {, b
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    7 V% w8 s+ n- a( k
  58.     }
    3 z0 }: Q! V- K# x6 n  e
  59.     else
    1 P+ b) \, k4 h, @, j
  60.     {" w1 Z7 C8 b9 R" ^2 i! G6 s; d5 O! x
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
    : u; V/ y5 F3 k; B& H- Z( b
  62. & L  G1 [0 T2 p3 ~- F5 R' D
  63.     /* 单块写命令 */% r/ x8 L6 }: x$ u& a2 A0 q
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    ( Q; Z9 n7 b- j, I8 V1 p
  65.     }- m; `8 g1 B+ @% e% j8 Z  S
  66.     if(errorstate != HAL_SD_ERROR_NONE)" W2 _2 Z$ ^. N
  67.     {
    9 O4 a7 J& k9 K6 H" w' @
  68.     /* 清除静态标志 */
    , V9 M; v0 ^; v( c
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
      L, X# L6 ~" N/ C' ~6 b
  70.       hsd->ErrorCode |= errorstate;
      p$ C# x' P4 ]! d& i( f8 V8 x2 Z
  71.       hsd->State = HAL_SD_STATE_READY;
    / D2 L3 o9 j1 k1 X$ {- A8 W
  72.       hsd->Context = SD_CONTEXT_NONE;% l, V( T; d- Y5 q6 }
  73.       return HAL_ERROR;7 H7 [. c' @/ I/ W, F5 N6 y
  74.     }6 d6 Z' J) y5 B, E1 f& B3 Z1 t
  75. # c3 E, R8 w% _% N$ R
  76.   /* 使能传输中断 Enable */& n0 s" w. z2 u! C
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));+ G" C6 K. @3 i# B

  78. , W/ M1 c5 J3 q  H- \. B! C& v
  79.     return HAL_OK;$ V  ~2 g' q6 L* O' ~5 R+ d3 K0 T
  80.   }( s% ^1 h( E+ q; \: h
  81.   else# O+ s! A  x% {1 Q: G
  82.   {
    ; l# u1 [: D3 C/ ^$ m
  83.     return HAL_BUSY;) x, v7 j0 |. w. Q
  84.   }
    - J6 M+ Q" v3 G9 W
  85. }
复制代码
" }# X- |$ n3 `# d0 D
函数描述:
; r- y7 N* J- F) q
; M2 P) Q; h& C7 B此函数主要用于向SD卡写入数据,DMA方式。  P: x6 I1 h+ G9 z/ n: Y% C+ \

% o% x+ |3 o1 J函数参数:' I3 Z1 ]  b, s' {) h* V3 O
! d' J) z% P1 N  M; D
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
! p$ {' _' f+ ?- H  第2个参数是要写入到SD卡的数据缓冲地址。' ~* n' U; Z* t+ Q- R
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。! u6 L3 g0 z; F* N4 u  m
  第4个参数是读取的扇区数。9 d1 L, r/ j' z4 U( M0 f0 B! k% {
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。6 l* A' r$ C: s' s

) `! o( s6 [5 P" Y, ]* W8 J
3 l' z1 c* q6 k$ _  ?+ \使用举例:% t, S% t4 B" w4 V
8 R: @) I2 N2 o7 j9 g( p
  1. /**
    & H1 O$ W" A" o' L; u! V
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.0 A- k3 |, K; f( B7 m8 f9 j2 ]
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    ) i) f. L. c5 G  _- Z
  4. * @param  WriteAddr: Address from where data is to be written
    / P  ^# v/ w% S4 _3 F! c: K
  5. * @param  NumOfBlocks: Number of SD blocks to write3 D3 t, C2 y5 K$ L5 z
  6. * @retval SD status
    : \" }7 ]2 v2 ~  H+ O# x% B
  7. */  s* \$ o3 T7 F0 r
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)# n) a- v$ @+ O  P; p( h
  9. {
    ! |) t8 U, s$ q4 l# b0 h. W8 Y9 ?
  10. ( g# c, a& P* I) L' C
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)5 q5 S/ L, {) @
  12.   {
    2 \; l" A- U7 n" b8 H+ C
  13.     return MSD_OK;* m* f0 g# I; K1 a' F- z
  14.   }  Q$ o8 }5 ^4 j1 j7 t9 C
  15.   else% M4 }# g3 v; d$ ~1 b4 `* b
  16.   {1 M1 o* o5 Z- H
  17.     return MSD_ERROR;7 m. D9 v1 n, T2 C
  18.   }, f& _" v- r' A* Y* f
  19. }
复制代码

8 E9 H( y# d% v' o- ?; G8 B87.4.7 函数HAL_SD_Erase# p" Y& F* _- C% g9 o& i
函数原型:) Y  S) ?, a; }2 \

1 a& {% V  J. b2 c0 K
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    & E& ?# D. c- |; b( h. t
  2. {
    4 y; {' h# z4 Z# E* q6 [
  3.   uint32_t errorstate;
    + j0 K( G1 J0 Q( D# {: Z
  4.   uint32_t start_add = BlockStartAdd;
    ) a* V' y8 p3 S" r4 y( i: `- n& M  Z( B
  5.   uint32_t end_add = BlockEndAdd;" j8 a0 i+ o' t4 T

  6. * ]* [0 ?% j, A# P! B; ~6 W
  7.   if(hsd->State == HAL_SD_STATE_READY)
    $ v8 X' e* r/ ~3 P
  8.   {
    / F9 F2 t, y! |& M8 b
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;: V; _) `% T( \0 Z$ Y$ D

  10. 5 i3 I7 }+ E2 K
  11.     if(end_add < start_add)) n3 D5 O1 W: _2 q5 T3 ?; I
  12.     {
    8 f9 i# y0 _& c# z6 N% k, o
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;/ Q7 n. z  }2 W4 U
  14.       return HAL_ERROR;& R. Z& d& {- ^( o
  15.     }5 |; U) H4 x& P3 \! z
  16. / f" m# r# x, a+ Z, a; y
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))
    1 O; D7 t/ f3 F2 B
  18.     {
    * ~# O2 R' h( v7 t/ _9 H: @
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;7 O; y# W2 I) S9 M4 O( p
  20.       return HAL_ERROR;) S5 M  G. P9 z- v$ I; `
  21.     }+ w- K+ R  O0 h4 `# `6 C# U" w
  22. . ~& ~! o2 I7 ?
  23.     hsd->State = HAL_SD_STATE_BUSY;  n9 p) ~/ d! U. r8 t/ [" ]
  24. : T+ W; d7 h, {; z
  25.   /* 检测是否支持擦除命令 */6 v, i. k5 D0 c' K  A# \  D& z
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    ) V1 W0 w& a- K, @8 Z
  27.     {5 W' x! [! v3 e& |, f" K& G; [
  28.       /* 清除所有静态标志 */
      `. y8 }9 s5 H3 G
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    $ \9 K, Z- M3 d4 \( i# [
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;0 C2 {# }# _1 o& m1 D: c( Z/ o
  31.       hsd->State = HAL_SD_STATE_READY;6 B: V9 D1 x/ A+ y
  32.       return HAL_ERROR;
    " D  c+ T+ b! {9 }' T( s. D
  33.     }4 @0 o! y; W/ N( o* \" W7 |

  34. 4 \" ^, O' r1 h2 `3 i: e% k
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
    * D, Y% k' [& H( K* ^0 D% G  o; T8 k4 l
  36.     {
    " Z# I1 [: s5 C- O' X' u, f
  37.     /* 清除所有静态标志 */
    ; U" c, X2 |2 w0 v0 J- t! M
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    $ j9 M! U/ E3 a- a; v! v& Y. k
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
    ' b6 `4 w! v% S  m6 m
  40.       hsd->State = HAL_SD_STATE_READY;/ P+ k9 [& l8 L
  41.       return HAL_ERROR;; P3 J" g  }- g5 _  E3 y( V  ^
  42.     }
    9 ~; B( f5 a4 u. f; S% S

  43. 9 u7 ~' D- {4 T1 d2 W- n
  44.   /* 对于高容量卡,获取起始块和结束块 */1 E* U0 e/ g6 v! }% Q3 p, C
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    % d5 D' ~' }. A# y) ^2 |+ L6 R# X
  46.     {
    " D; b$ ?/ i) L5 U7 g+ Z4 y
  47.       start_add *= 512U;6 g$ e' s" H3 j1 {! W  z
  48.       end_add   *= 512U;# h4 C8 c/ H6 D7 D
  49.     }
    . q9 V$ ^$ J" L' M, b5 f9 \8 o4 U
  50. & ~0 ?* S5 X# X( r- g1 t# _( D' G0 ^
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */( l: _# r% W" a$ n) L$ P  ]
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    3 B7 M, Z& M6 [5 @! S% _
  53.     {+ {# q7 {4 j/ M) v% v
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
    / J" t" R9 Z& n. r9 H, L
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    ; V, o+ H9 g* F  k
  56.       if(errorstate != HAL_SD_ERROR_NONE)) m6 ]9 m3 h6 p' e* D' n
  57.       {
    + A9 ^% O! f5 r& O
  58.         /* 清除所有静态标志 */
    1 m' N2 E& o0 J
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" z& h* }0 s5 u: p) _+ v$ x) z
  60.         hsd->ErrorCode |= errorstate;
    $ g- w/ M3 d5 J% `9 }4 F  G
  61.         hsd->State = HAL_SD_STATE_READY;
    ) \1 j$ S1 c8 z8 q& P7 J8 [( l* r
  62.         return HAL_ERROR;
    / ]! ^" A! d) |1 R
  63.       }* W7 r% i2 J: ]4 V& R: k+ ~

  64. ! @$ D9 }4 x+ W
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    9 K; f2 v- @/ z# w  e0 C6 R
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    . ]# i# T8 N/ T4 Q
  67.       if(errorstate != HAL_SD_ERROR_NONE)9 b6 i) t+ n& V% Q
  68.       {  I3 O  X0 T4 y: N- Q
  69.         /* 清除所有静态标志 */1 s7 c$ a: W! S# |- f0 Q6 k5 H
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ W6 o! k+ x! ?' s6 L
  71.         hsd->ErrorCode |= errorstate;
    2 p* B) j; d- V4 K& W; U
  72.         hsd->State = HAL_SD_STATE_READY;! F/ J$ V* ~* [; E- h
  73.         return HAL_ERROR;
    ) ~+ s9 `% l3 b# P9 s' a
  74.       }
    6 P6 z: k/ ?" |. Z" J
  75.     }
    8 E* B3 E8 U9 q8 l; B; J9 Q

  76. 2 L" H) Q8 R; a( ?* r
  77.     /* 发送CMD38 ERASE命令 */
    / H7 `" a: Z6 C( ~% Z
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);" f& ^# j0 T! W! g7 A4 ~
  79.     if(errorstate != HAL_SD_ERROR_NONE)  _2 A3 h. L3 ?1 `
  80.     {- e% q" D# f; v$ y( H) ]3 n
  81.       /* 清除所有静态标志 */
    * |8 G/ D% F) j: Z( W4 L2 q
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    8 [. M" [0 K$ U8 N- V/ [) P
  83.       hsd->ErrorCode |= errorstate;) ~- X0 D& V7 ~" `& b
  84.       hsd->State = HAL_SD_STATE_READY;
    5 _; q; I( e* s
  85.       return HAL_ERROR;1 Z, j; a. C1 E; S9 H6 t! \
  86.     }9 l' \5 m1 h9 I& v, c2 ?
  87. & W9 Z& @1 |7 v* K+ W9 ~6 a7 N
  88.     hsd->State = HAL_SD_STATE_READY;; d* e2 |1 `* H  r; J
  89. - k2 E# y) I9 ]5 w9 L
  90.     return HAL_OK;
    & P+ J% S+ M! A
  91.   }, c2 {& S6 e; n2 w, X1 g
  92.   else
    / }: \! p6 Y3 K( F9 X) P% Z
  93.   {- ~& [4 Y$ Q& s- K. Y1 s- o" _+ M% h
  94.     return HAL_BUSY;8 O" n0 y% B$ R6 k
  95.   }* a2 e( t& n0 @7 ]' @  i, T8 S
  96. }
复制代码
5 s0 t; O/ |- U& K4 u6 i$ Z
函数描述:
+ `4 j( ?& g2 Q$ ^) ^. E
6 g* U9 S8 t3 [4 C( d此函数主要用于SD卡擦除。
( j5 P% G+ T! t" X0 e) I% N- u6 [( X. W) X  R; r3 ~7 s6 x
函数参数:
+ I9 F( x: r5 f& w% J4 y+ r/ _/ r& e
1 x& I" |4 `5 N8 X  第1个参数是SD_HandleTypeDef类型结构体指针变量。9 ~$ u( j8 e/ e1 w( B
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
1 W" O; k0 O- B% f% u  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
8 M& O9 u5 \- `  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。* @+ L7 ?% P3 ]( p/ |- X) A* ^
使用举例:
5 g! j* e9 K/ z" n) K# g& x
3 L9 o* U4 v( t
  1. /**2 w6 |# V, U3 |2 i3 L
  2. * @brief  Erases the specified memory area of the given SD card.
    . r, a. P. i' [2 j
  3. * @param  StartAddr: Start byte address
    2 c. L' ?" C  ^( p- m
  4. * @param  EndAddr: End byte address
    / _# w# Q" _5 t; }* D
  5. * @retval SD status! u" v5 v8 H3 V, x) D% {/ T; r
  6. */
    2 i- G  A3 A4 a6 a3 p) f
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)& e- R2 w2 \% F, T
  8. {
    1 \2 n6 T4 u/ H2 D+ B+ g' Q
  9. , a+ \4 n9 }7 r5 B8 g& L
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    ' \/ J! p" ]" q0 O$ H$ t
  11.   {
    $ w  j  b* h4 V
  12.     return MSD_OK;
    7 K9 A1 F- g% z& [% f( D
  13.   }
    : b. Q+ |/ U0 l- J: {) S
  14.   else
    , |2 L7 H7 L  h2 ?
  15.   {+ ]; \2 r6 |6 S6 a6 ?0 ]/ g) ]
  16.     return MSD_ERROR;0 w8 c& A, k" h+ n' G
  17.   }/ ?9 I* F2 x( B5 n4 K  I
  18. }
复制代码

1 F( S. V, Y8 W& U9 W" ]' A' q87.5 总结9 U  J3 V9 V8 b3 m2 d
本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。& n, w7 e# ^0 `: m3 k$ `
9 B7 d, z' r; N8 c- B
0 `$ W, S  N  ~; P

# b8 D  c  I6 ?) k$ m4 v8 `' N/ {  D& M& b9 w6 e" l

$ u  u- q" r7 s; p/ ^+ L, A2 {2 e# n) S" V7 _% E& \
收藏 评论0 发布时间:2021-12-26 16:43

举报

0个回答

所属标签

相似分享

官网相关资源

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