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

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

[复制链接]
STMCU小助手 发布时间:2021-12-26 16:43
87.1 初学者重要提示
& {, O$ M& H# G8 k9 x; b3 |  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。; i% g: B- |/ R% X
  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。
( O0 P7 M; c5 O( @9 R" {9 F  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。/ N7 \# M& ^+ [9 l+ n
  SDMMC驱动SD卡支持1线和4线模式。
0 p* I# o, v2 O; F6 H" U$ {) G  STM32H7的SDMMC也支持eMMC:/ J  L3 b6 C8 |8 L

/ t. f, E3 ]0 h3 D) H87.2 SDMMC总线基础知识
2 ]* C3 m* u$ e& N87.2.1 SDMMC总线的硬件框图3 E9 X! W& H1 S7 I5 @! Z8 u% C
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
* Y- r) l; l2 \1 C
1 J6 H. m' j! I& I1 t& b: w# T
6eea62abe623396815a50adc87205b83.png
8 p6 ]4 T0 G2 J! J; d* M
% j: b4 F; ?! ^2 `1 f2 g) T9 P: E
通过这个框图,我们可以得到如下信息:  ; E" O" W+ y1 v& y  ~. j+ }
   sdmmc_ker_ck输入! p. v$ o4 l4 C5 Y4 t
SDMMC内核时钟。  m) X. k7 L0 |# Q- @
2 d) h. V3 E' z1 H. {; e1 F
  sdmmc_hclk输入( J: P2 e5 e  a$ h
# _' i5 O9 V6 o6 P1 v0 V8 ?
AHB时钟。
. g- m( P/ T# T+ X
5 M" \7 v5 d! i  sdmmc_it输出: P4 C: e5 ]: I  U( f
# ?5 F( N9 q+ S% j
SDMMC全局中断。
5 M3 ]8 h/ ^! s+ n2 R2 x
) m  N+ C! t: W( K  sdmmc_dataend_trg输出( D* q' e# L2 h( [5 r
, W( d) N. {/ }7 p7 q. \) y
MDMA的SDMMC数据接收触发信号。
; h" H& b4 f$ P9 W/ \5 }) G5 ]3 g' d5 a2 Q. n( y6 w5 B# {+ P
  SDMMC_CMD+ s+ Q6 C" I8 c

5 x: X' l8 @0 a- y$ n, C/ o7 hSD/SDIO/MMC卡双向/响应信号。: ~  {+ w" Z0 M* Q
& d" O, ~4 _% Y, r1 Z0 N
  SDMMC_D[7:0]. @# Q8 e* h& L7 v; |
6 I( |* j0 L  l. ]7 k
SD/SDIO/MMC卡双向数据线。/ B: ]! Y5 D) b/ P: N/ Y

1 W5 a% S% R* E9 ]/ `" J3 v* h1 |9 w  SDMMC_CKIN
- o, O0 \( c. s6 Z0 f
! u/ j4 X; o# s来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
! ~2 X, S0 ?( D  E/ x( n4 o/ ~$ |3 o! W; K; a% j
  SDMMC_CK. L3 c2 v  W% ?' C# C3 r

' E6 s" C. U0 ~SD/SDIO/MMC卡的时钟。- C+ T2 a" _! b9 h. b5 j
3 ]1 q' c  S/ b! m, @4 D
  SDMMC_CDIR
, L: h0 R+ i/ h( p, w* i0 ?: K' J0 ?7 z
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。
2 j$ f6 S2 y0 Z4 l1 \" B. S- |) p. v7 C& c
  SDMMC_D123DIR5 N$ q- X" _, u

% B- P/ n8 O, m$ A! K" G& XSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
4 p! {; `- t, D. J. g; k- R5 b! T3 o! ]. a. ]7 y* d# C' y2 `1 C
  SDMMC_D0DIR
" @3 y2 g, K& J; [3 p: X5 n$ c
, z. \; k# _, a$ N+ XSDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
8 A* k" w1 |- u# i% u5 f# u( L' k8 X( E" ~: l8 W+ I
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。7 u& S9 {% [* W) c3 W

0 m3 a  u5 q0 y- P  {9 J7 W87.2.2 SDMMC时钟8 V: h: ^$ v4 b& y; J
SDMMC控制器的时钟来源:/ I! N" A; _1 E0 g2 r
! v) o: l2 \9 G
676ec31792fcb80bee640ed979d48084.png
( V: y2 i6 h+ `% u7 c
1 H, B$ l4 m8 }- {
SDMMC1和SDMMC2时钟源是一样的:3 Y# a, U6 O  i! G: L) @5 `
) B" L! P, B. W% N* o
79b1c69986d1ee5bc090bf1676f396fd.png

9 j3 `9 v5 P% R4 r  s# z
2 l: D; I; H: c: A5 q; E9 p87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
$ o% _; D/ T+ n# P注:大家应用时要特别注意这个问题。
* \" W" @5 Y7 f# |5 h& ]
$ T% b3 r8 j% a使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的
6 l$ X/ y: i0 B
" k1 D" e  ^; j
6a5491d2f4a8740d838af58d034b7597.png
5 o9 ]9 w3 k7 h/ L6 d8 `3 m  _
% K$ J8 f+ z0 `4 Y6 ~3 v
87.2.4 SDMMC支持的速度
( B+ {, s% c/ x: ?! z3 Z! W; E
驱动SD卡支持的最大总线速度:
) }: U) U5 a6 q( ?
* U! b7 V1 I8 Z6 p% t* }" v* S8 V
b70ce31107b38ea820dbc28c3caec38e.png

  E( }; ^. V! c7 A* a2 U# n
3 a; V7 R! h7 ~8 u/ L6 A驱动eMMC支持的最大总线速度:$ z$ Q# H" m2 `7 n1 j  a
% V/ F) Q, }% Y& C. C1 L: g* j4 e
843bf7a054944ba7d5d137ca84e1d4ed.png

9 y& Y& h5 ^0 S* S
" c2 c. ~4 K$ H' `; B( G2 o9 N关于这两个数据表,注意以下几点:5 c. L" J5 e  j0 [
% v4 f7 V- f7 j2 @7 C
  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。1 W( J8 S/ n' {6 r& x1 ?
  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。1 y/ }3 N8 C4 }8 w, o! g1 `' m
  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
- u$ q5 |8 @8 F. L. f2 h* y0 O! x5 M- o# x3 w
87.2.5 SDMMC支持UHS-I模式
/ O) B- V3 C, t1 D- w" b2 {8 N/ `
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
2 R; O# v; t# x. \) R9 s) z' o7 K' u' K) @2 ~0 L) f/ z
2b8e4430b8a60dc5a1b342d7c7f75f52.png
( D, d8 d' s8 Y, g% V2 g6 ]

9 s5 l2 v" t* b) b& j
85f975745619c9afc64f8889289dad58.png

! ?% {/ s5 T$ E' k2 m  D; Q/ u9 i5 N
# f% A8 G9 w, `8 l0 L87.2.6 SDMMC自带的DMA控制器IDMA

7 _; n" l  O  T3 `% E6 ZSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
8 g5 e3 U5 K, s9 W
/ D$ |: i  d1 M4 H; M87.3 SDMMC总线的HAL库用法& d0 f4 ]. }' x% z* U2 h
87.3.1 SDMMC总线结构体SD_TypeDef1 f2 h0 E' j5 }1 H- R9 {
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
: i1 ?4 X1 I4 |9 N$ S9 c2 p
1 U! L: l) J# W1 y" v& a
  1. #define SD_TypeDef          SDMMC_TypeDef! }% |' [  T: x, x! T/ x5 ]8 s; O
  2. typedef struct7 I0 I9 [7 W9 K  h/ k7 b1 O
  3. {
      i6 g; R( I6 F9 J; ?- j
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    " K0 @' G" M/ h" t
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    1 n; `+ l( U4 W5 o9 f  c. B
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */
    1 S( L% r1 m2 \# L  E
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    # ~2 m1 V1 V  e# e) R
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */) ?# E: C  F; M3 O& G
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */
    * f( C9 R3 J- t! J; W1 ]* t8 }1 f" B
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */
    ; n' r! B2 a; l' Z
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    , y. l) I# T2 i$ t
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    2 J* [/ }/ h$ A" V  w6 O
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */) k0 @8 s( i7 z( k! f
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */- W- [; \$ v6 M% Z6 m) G: w
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    . E0 V" e  F* I* [8 A1 h
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */6 c  x9 Q1 a" N2 g
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */# w. W5 u  `4 v! ~: `0 k
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    7 k# D: k9 k' |6 ~
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    , Z8 U0 y& }, b$ J
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */; T/ N  x% ^' R+ O! u3 K
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */) h* i- Q  j. m- p0 h5 p
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */1 J0 \* ^* Y/ d. A3 x
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    9 }& _! g  B; H7 g: f0 m+ I
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */8 |, y9 @$ i7 c+ D, f9 Q, \! Y  S
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */. ?$ [( Y. t5 R2 c, X
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */. i' @3 T2 L9 r: T- ?
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */; {. {9 Z' k0 U6 o2 R4 J0 W9 u
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    2 p+ D6 J$ G* {" N+ Y" r0 ^
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */' F6 q8 S: B7 d' v) I
  30. } SDMMC_TypeDef;
复制代码

) n5 U9 L" t6 P4 f这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。7 L4 [, _6 T$ e
% h- l$ c. J  `- A9 @/ P
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:: {$ U8 \( ?& s! \8 s

9 v( u( u; S2 a$ x
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */) K+ j- x' v9 ]0 K- F. h7 }
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
- o4 ]' S. O7 U. o' i9 F. q% |0 J# f
下面我们看下SDMMC的定义,在stm32h743xx.h文件。
; L  v, ~( N' @2 `9 C- n7 D# z  A& i. @. {4 e. d8 K; T
  1. #define PERIPH_BASE           (0x40000000UL)
    6 @" m; p0 k* E
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)% u" e: s8 F. d9 d; ]
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL). R; t% Z2 y; N% |# t
  4. ( Z! h6 g$ g; v8 X3 o4 F# b
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    1 @( L1 }4 e6 b  ^
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    9 ]6 m9 a  A. G) D1 W, k

  7. 4 i( L$ X8 A4 B4 \7 s! W6 [3 N
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    $ A0 ^) ]( j1 r
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

$ X) G* q! ~! _7 d$ r0 U* A6 E% L( B: [我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。9 N* @9 R- Z1 u4 G# I/ M. ?# C7 j

. L+ x1 N& Z& Y6 A, {0 ]1 d( E" ~87.3.2 SDMMC总线初始化结构体SD_InitTypeDef" ?) h5 X4 z0 w. @2 V* `
下面是SDMMC总线的初始化结构体:
, w  [4 L" s/ \- x6 F7 J7 G9 P4 H9 [
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    ( p$ c' P0 g7 R
  2. typedef struct
    ' T: J. i7 l" A( I6 n1 F6 R9 k
  3. {
    : l& {* \7 e1 ]  [& \; d- G
  4.   uint32_t ClockEdge;            
      V  \- u, F2 ^* y, y
  5.   uint32_t ClockPowerSave;      
    5 }  B$ q) w* x# L
  6.   uint32_t BusWide;            
    8 f* d* o, ^& L8 ]
  7.   uint32_t HardwareFlowControl;  $ J1 ^, `- T2 K+ L- O
  8.   uint32_t ClockDiv;             ( c+ A1 _. i  |) f: ?: M- f
  9. #if (USE_SD_TRANSCEIVER != 0U)
    ( B. t) k+ o( s- C% X
  10.   uint32_t TranceiverPresent;   
    ' i* I' v4 M& ]) ?" U
  11. #endif
      ?$ a1 U( D% \
  12. }SDMMC_InitTypeDef;
复制代码

7 s2 Q6 O; z  `6 S5 d8 e8 T* L4 t下面将结构体成员逐一做个说明:
% a. ^/ m( m3 K+ s2 p& G, ^! F; p; }0 \! a& Y
  ClockEdge% \$ S6 Z% B3 i
用于设置SDMMC的数据或者命令变化的时钟沿。
; H, ]+ d6 N# k% k3 T# j6 G
+ Y" [4 C' S% t
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    + n. \# a; {4 N  G7 s
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

5 s3 n/ D$ M, L) J  ClockPowerSave$ v* f1 m( i; K) \6 o+ A* w
用于设置空闲状态,是否输出时钟。. P/ N$ q" I9 n* D) G+ q

+ A4 S, m2 S5 S$ m0 O# q
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)5 T0 @! D9 _) A! h/ ]
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码

. j/ X  H2 D$ J2 \( {# L& g* s  BusWide
$ b) r4 M: o5 u7 E# E9 \: N用于设置SDMMC总线位宽。0 r" |* C2 z8 n

/ Y% n2 Z1 h1 T/ m. Z9 |  Y, w
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U). Y. v! L* Y) t( b( y+ c3 @
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0
    5 p: v7 {/ N! ~: L
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

% v8 g# R- J7 p5 y$ i  HardwareFlowControl0 V5 Q& w$ m& z8 q
用于设置时候使能硬件流控制。
$ n0 V! S1 r9 l6 Z0 x
9 o0 E* l6 |1 k/ V* K6 A* g- [1 ~5 a
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)/ [- j! F( `/ j3 Q% ^
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

4 ?) O1 w8 e0 h/ {3 b  ClockDiv6 |( ~7 @/ B0 E9 E% M! O/ X
用于设置SDMMC时钟分频,参数范围0到1023。. K% L2 i$ w; T0 u

9 c) V$ q/ Z+ n/ m3 c' _8 S  TranceiverPresent
5 l/ U! L2 _; J0 d% i1 e用于设置是否带1.8V收发器。
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    8 X# O. b7 S, a" }; s3 _
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)" J/ i& d4 \  j8 r
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
+ B: |7 W1 _2 L# `) G8 L# v" {% R
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
) {: G* e2 L# ^& L' U
下面是SDMMC总线的卡信息结构体:: k& k5 ?" N; ~8 Z$ h
* t: ^6 B* ^0 g( {( q: |
  1. typedef struct8 X0 j* ~8 Q( s3 a
  2. {0 ^: J' P9 @, Q: }2 m( v2 G
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    - a; I" x+ T4 Y$ e8 Y0 K8 T# E+ D
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */  v1 {9 J! A( G# @7 a# x
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */$ s+ w8 Y" u5 J# V2 u
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    : B5 c+ Q& O; j/ k( }
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */. Z, e4 C9 V( W" T# k( }4 h; A. i0 V
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    ) Y2 w# [- |3 g4 \
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    % T3 m0 O; O& X; E+ {5 T: |" [
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    5 x- B2 Z& d: x+ U! b
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        *// m6 f! u# s. F; X- D
  12. }HAL_SD_CardInfoTypeDef;
复制代码

1 ?  x4 y3 o) V4 p3 y8 R下面将结构体成员逐一做个说明:
0 V6 ?: N' f* _# N! B$ \
) ^3 I% }8 }( f) Y! Z' n* K# V+ s CardType
$ T4 E5 ]5 z. o2 z& k% C卡类型。, g" i; }& z: R2 e2 e

! s& x  H( a6 v4 X" L: Q
  1. /*!< SD Standard Capacity <2Go                        */
    6 H2 W) n; f  t, ^3 L- o
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) 3 s0 Z! F, O! _! L
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
      m& C7 y& m. \: Q  v; S/ |2 h+ I
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  3 g$ F' p3 E. A1 T, J
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

! D9 {! H& f$ J$ f+ g% d6 x  CardVersion; I$ k  ?5 F" m' l
  J. p# K0 w  S  f

3 M1 f: h3 B6 Z! K3 C卡版本。
& r( |! e* S! c- {' E' [& }: i! O
$ M3 @& h9 G6 W  O, ?
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)* g+ E; y2 J8 D/ {
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

! ?/ z0 o/ l5 b3 J  Class
9 o; B! L$ Q) Q, h" [8 a$ ^& I8 x. S( W' R& Y- \' d' E
' p. F. ~( m& p8 V) c3 D5 r8 h. ~
卡类型。
2 F7 i! a7 B/ Y6 F3 ?6 M7 ~& d" W$ p9 w+ @3 q) S4 d
  RelCardAdd
8 @, W% ]- j# K; T8 k4 B, c
" F' R9 I, Q4 B( O: Z8 p; E! e- s
卡相对地址。* `' ?; |, L" Z, {1 A( ~6 {
/ i; ]$ ^5 D( p  R' w
  BlockNbr7 T0 ~3 n8 D2 X2 Z8 i
整个卡的块数。! P* e0 T+ U9 O* ~" A

) U, n/ [" R( C9 W) P2 T  BlockSize9 M' {2 t2 C5 I4 T8 \  i

/ w) l6 k# ^! E! O  D
! ?7 p7 y5 r; q# @$ H; h每个块的字节数。- k  g6 F" @! X2 J

' T1 u" {/ N: [, w+ d  LogBlockNbr
$ ^, G) f! A+ e8 G7 z1 `1 j1 |5 H4 ~2 R2 L& R

) S9 _. I; O& t8 g; A( |% a: \# w整个卡的逻辑块数。* m6 r  e: \* J3 B
4 d5 \% k! ?# g* ]1 I
  LogBlockSize' a9 q, }9 k: _+ @
- |0 v9 }8 _( S" e; J, h
/ w9 o: w) x$ v/ I
逻辑块大小
: `% A/ u9 S& a
" |6 B# ?$ V3 g5 ]5 _
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    9 `4 _+ n0 `+ k0 i* G
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码

, h/ [+ H. b# I- a2 u CardSpeed
: w# d: ^  \! a+ y' }0 k用于设置是否使能SPI总线的TI模式。/ [" D. |, i' N/ S! x& b. V3 ?
$ S7 P# T, X+ g* H$ v) O% Q
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */% Q, X9 s; Y0 k) m' G9 B
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  6 }. V  B$ C/ k4 U6 S
  3. 0 g) x3 |* B+ z, \2 b1 Y
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */ + y% }. G/ L( h
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)   J  t6 M! W9 w, _, U
  6. , j+ H8 f$ K' s+ C: |6 p
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards) j8 E# W8 n5 `3 a, C9 s
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    ! i) {: d7 \6 I; d' W# I
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码
! C; S$ T3 t: h. _
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
! W* J+ r9 {+ R0 u  t8 n! F. Z下面是SDMMC句柄结构体:5 d9 K8 x) f' S4 @- o/ ?/ _! P

# e& A4 ~! d, N0 Y
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    3 {5 |' r2 b2 }4 f# |- R8 P
  2. typedef struct __SD_HandleTypeDef
    4 y5 Y/ Y# J, G$ D& z/ x$ O, Q
  3. #else
    9 K8 y: W& m# o" |/ b6 z
  4. typedef struct
    6 ?+ [  D, ^+ T/ i' w5 L
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    ; l, e& G$ C5 a$ h# Q9 `# F5 X
  6. {1 Q5 @  b+ R) L3 }1 v
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */
    ( U. O3 w8 q& ], E
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */, w) \! X2 c3 _- c: c# _% F
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */" r6 ~3 {7 r* P6 i2 W
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */
    2 {: Y/ T. q# X
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */0 @  L1 K) e+ D" _
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    ; Y. a* D2 O( o! h8 y
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    & C9 Y% w, M  J7 L  K0 T8 q* M
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    $ ^7 m. F' G: t* s3 i  K
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    + [$ P: Y/ L1 M! m& s6 B' x' E) Z7 d
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    : _& P9 t/ t' @' k1 n  C
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */) o8 ~6 S% x" F" X$ p6 G
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */. Q, t% O0 e! n" L- G/ [
  19.   uint32_t                     CID[4];           /*!< SD card identification number table *// ^# B! E; L2 d+ p: X" l
  20. 8 C5 B! ?: i+ X
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    6 `: ]$ ?* }7 I/ Z" J. O
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    3 g* G+ l% `; j- j7 [
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);6 K$ R2 ?% }# L9 r
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);1 K% I3 l9 D7 r! n8 W. B
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);( b9 t# }  g6 L" O" L
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);3 Y2 l2 X9 r# r$ H* u- K; b
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);8 Q# [) |" ?; y/ I& p; v/ w
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);6 [: x5 Z4 [/ A* l
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);6 R; @9 G& T. c7 r
  30. #if (USE_SD_TRANSCEIVER != 0U)
    - r+ i' P% F8 d. s0 C1 ]
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);
    6 X# ?$ w, Z( {6 m
  32. #endif /* USE_SD_TRANSCEIVER */
    6 {9 w; `3 R+ ?$ L1 {

  33. ) c& y1 n+ o  ~# S" K# r. K2 |, {1 F
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);3 A- i% O8 Q/ B! T# _7 W$ @
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    1 p; r" H0 y4 }' t4 n/ x& O
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */8 j$ v# q0 Z) P" @/ a
  37. }SD_HandleTypeDef;
复制代码

  e% v: u! K0 N1 b) T* N注意事项:
' j6 X, v; O9 _/ l, P$ F
) L* F4 H9 Y# N4 c1 l7 \* \5 U条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
# U& `# \  ~0 u$ e# D4 o1 D, j. a+ O  Y, l9 m8 ?5 P
  #define   USE_HAL_SD_REGISTER_CALLBACKS   15 e, Z2 V! W2 f1 S% O/ N- u
. d; p/ b2 b6 q9 T+ d9 \$ G$ l
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
, }! m6 ^! k/ @
4 O2 ?% b$ o( _0 k这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
" R0 `6 M$ j' l# M/ b7 ]0 H& x* c2 X( B" B6 i0 H8 ^# G
  SD_TypeDef   *Instance
0 h5 O9 c7 y; |6 p6 J# D- {* x( R这个参数是寄存器的例化,方便操作寄存器。- b$ R( u- @( w* ~
7 e, u0 w- ~$ n; S% ]7 ~& r  R1 F
  SD_InitTypeDef  Init8 `0 a* w9 c2 }+ g
这个参数在本章节3.2小节已经进行了详细说明。6 ^$ n8 y  }7 t$ B
8 R& f4 x4 N- e6 U5 q
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c/ O- i4 @' H( S
此文件涉及到的函数较多,这里把几个常用的函数做个说明:
4 a. ]3 _2 u8 m; a% e4 f# h- _
: g% A4 D- [1 p3 Z& S  HAL_SD_Init' j3 I. ^5 E: K! {. p* N) Q
  HAL_SD_DeInit
# l7 E* J% S: l6 _  HAL_SD_ReadBlocks
! \" T, V$ n5 B  HAL_SD_WriteBlocks
" ^1 X5 W* x/ c6 w; @- _: x  HAL_SD_ReadBlocks_DMA
* J! c2 z4 ~- o3 e1 j4 {  HAL_SD_WriteBlocks_DMA
% K# Z8 L, h! z. [/ l4 k0 {  HAL_SD_Erase. ~7 a- s! c4 A4 ?- R

; y& @( }/ g$ e( b* X87.4.1 函数HAL_SD_Init! r# t$ [6 {2 V& T  s! q% \
函数原型:" A" o) D+ S7 V3 _

* z  B! A5 b, C" |
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    7 a3 O; s) S9 y2 j$ N7 j$ a
  2. {& M) ^3 \  P; w5 x
  3.   HAL_SD_CardStatusTypeDef CardStatus;
    , s0 |3 t$ U# m
  4.   uint32_t speedgrade, unitsize;
    3 V9 g5 B( f& F
  5.   uint32_t tickstart;. A8 g6 E+ [6 h

  6. & @( y" U4 d( Q  d' b) a
  7.   /* 检查句柄是否有效 */
    6 G, h7 K1 h3 W  t8 ]# f
  8.   if(hsd == NULL)
    / B' E- c* d3 M1 F; @# t' e
  9.   {
    * k3 V  t, l$ p3 Y2 ~& s. k- k; z
  10.     return HAL_ERROR;
    0 i+ x4 Q- B5 J7 c6 u
  11.   }
    $ I; @! L- K: |8 w5 T* k
  12. " E5 C9 ]" ^" w8 L; v5 x, Y5 B, v
  13.   /* 检查参数 */
    5 @# e" p7 T" c4 J5 X
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    # Z' V' ~# f* h" X" r# n. ^
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    ' C2 ?4 ^$ B: M* |' o' A# U( V
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));+ ~0 z* _; @  O* U& ]
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    5 v% N3 d) e2 ]6 @8 C8 o, h( G6 \3 A
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));. I0 _* `9 n+ F
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    2 N& z0 T7 Q# s4 `% `. s6 J; J

  20. * x4 r. a8 v2 ^, y# h( s1 H
  21.   if(hsd->State == HAL_SD_STATE_RESET)
      i, Q$ x/ V5 U) V0 o2 w5 x" r( M
  22.   {
    ( s; t; g# R6 z- H0 r$ `7 ]
  23.     /* 开锁 */) g' O! Y0 x0 J' Q  L7 ~. U
  24.     hsd->Lock = HAL_UNLOCKED;
    : v- O0 _. p" A/ O! l9 R

  25. . P3 ]: I! \; _3 u# q: S( t
  26. #if (USE_SD_TRANSCEIVER != 0U)
    3 [5 }& H$ V& m
  27.     /* 兼容 */
    8 i1 {7 p) J  w4 e: m2 }: w
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)9 G: |: J* _% J/ Q
  29.     {
    - n% w6 ]* ~* d9 g
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
    9 k7 ~: Y/ u* a, p
  31.     }
    9 D0 b  G. o! q3 A6 y9 c
  32. #endif$ x, C4 w3 ]2 P& ?! o# b
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)2 T$ l) z7 }3 j3 v4 m; X! Z, M
  34.     /* 复位回调 */
    % x. _8 \" N- ^# t! _
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;7 }2 j8 x, K, h- }5 h( D2 U8 A! ^
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    " G: j- b9 e  _5 l  p- J
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;
    # ^+ f4 j2 r- C7 d9 O- G
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    ) {* ]1 N' @/ g/ Y, }2 ?
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;; Z+ D; Q$ i, S
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;' p2 u5 j( G$ F9 w4 \' \
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;9 B/ A9 b4 C3 ^' v+ x1 v8 `
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    1 A" K7 O; X3 V' }
  43. #if (USE_SD_TRANSCEIVER != 0U)
    6 r; C/ h8 l* {% p
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)$ U( O3 n" |. v' i4 w- H
  45.     {1 N2 b* W1 I: R* {/ E* I
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;: c  x( P& X. `0 z1 X
  47.     }
    3 [: z1 f/ _) X5 A. |
  48. #endif
    + T2 u! ~& ]8 M: ?% \# D

  49. , f1 N; z5 f6 s
  50.     if(hsd->MspInitCallback == NULL)! q( A7 y6 P  g& L
  51.     {
    # N: }3 ?% V2 }8 ^
  52.       hsd->MspInitCallback = HAL_SD_MspInit;2 _. d; o( t2 q0 c
  53.     }/ L* C5 ^. c) G& g3 A5 O4 ~& c6 J2 ^
  54. 0 E. h( m4 u  F( `! V
  55.     /* 初始化底层 */
    0 m; d+ {: p1 Q" L# w4 V; `
  56.     hsd->MspInitCallback(hsd);
    2 m  G* K5 s6 t+ G/ {: D
  57. #else
    $ C5 ?1 i( H3 C9 p- M* u) F
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */+ z5 ~! ^7 ?  |9 {
  59.     HAL_SD_MspInit(hsd);
    ' n3 \# ?  |+ w4 E+ A
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    # V$ P0 c& J, r& M  ~; @
  61.   }
    ) [) S9 \  o. a
  62. + _9 o7 b3 e& O; c8 K5 I: Z
  63.   hsd->State = HAL_SD_STATE_BUSY;
    ' I0 ]8 b& g% ^
  64. 8 H# C4 y& d1 _1 l
  65.   /* 初始化卡参数 */: @% B& c+ }9 m/ d
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)8 b0 q9 e; }  F" {7 B% [5 o: o
  67.   {
    0 }+ T& w1 w+ K4 ~, w; b
  68.     return HAL_ERROR;
    + X; l' \5 Q4 E' g0 w
  69.   }) s6 F1 ~8 o, z+ s/ [. M

  70. * G  H. I4 F& X4 t) W5 U
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
    6 N& y6 c2 n8 o( q  T8 ^
  72.   {5 C5 Q- I& M3 N3 T1 A
  73.     return HAL_ERROR;/ k- c" c/ v1 h9 X# Q
  74.   }
    - Y, g+ m& V- U+ g
  75.   /* 获取卡速度等信息 */
    6 g( d  R4 Z+ J. t  O
  76.   speedgrade = CardStatus.UhsSpeedGrade;% G, k) k( ?. {0 ?
  77.   unitsize = CardStatus.UhsAllocationUnitSize;
    + ^3 @3 q1 O( t0 `- d; r9 ^: U
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))# k  J3 p+ W1 P6 ]( m- T) k
  79.   {
    - f2 B' o: L. [' g$ ]8 t3 H
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    0 ~% t# U$ p* ^) Z+ d$ ^
  81.   }
    & D* Q: Q3 c; s* M$ t7 O8 l1 z
  82.   else
    $ ?  K+ N3 q% z/ m2 C& V$ U, r$ p
  83.   {
    . J1 B3 X5 I1 m- t/ u2 e6 [3 p& C
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)7 o; a( @# x' K0 o
  85.     {# ?5 r) T0 a- p) i3 W% [1 N0 D
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    8 o) _. [% Z9 W% l- U( B$ K
  87.     }
    ; S) X5 z  [4 O+ b2 z1 S
  88.     else
    2 O& y" |, a% y2 ?: C4 g. s. p
  89.     {# p5 ^" B; M+ v7 f
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;
    " I# N% I) E/ `5 f- ?0 l
  91.     }
    8 G2 D# Y% B0 v8 g1 m  O- S2 z

  92. * v  t1 b: T1 P3 w2 i3 F: g+ Q2 S  v
  93.   }
    7 F0 B7 O- T% p4 a0 g
  94.   /* 配置总线位宽 */
    ; J8 ~0 _/ d/ `
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    4 P6 B& y3 b/ F7 Z$ ~! n5 U2 t( I
  96.   {
      f8 u: j7 i: g' r0 Q, w3 i' Q6 O
  97.     return HAL_ERROR;% @" q# `7 i: c0 T* W5 M: D! V3 w2 l
  98.   }
    , \: M! ?5 V* G- b8 R
  99. 3 ]* V- `6 y+ B
  100.   /* 验证卡初始化后是否就绪 */
    4 y( M6 I; Y6 j  F. h7 p
  101.   tickstart = HAL_GetTick();
    - f' R" @5 {& c# c7 ?
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))" a) R* q3 I  g  \; g
  103.   {8 S3 W& ~$ s" X- \% O$ |! q1 X
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    2 ?, U( I+ i4 t% K  j
  105.     {
    1 K" N( z4 Z+ R3 V* q5 L0 Q
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
    ) U. E, r# H0 Z5 |# @% o
  107.       hsd->State= HAL_SD_STATE_READY;
      u$ A9 s+ N: X
  108.       return HAL_TIMEOUT;' \" x4 Q) j) X; I. ?% w
  109.     }, K; b8 i& k: ]0 `4 n
  110.   }% [5 i- B" |2 b% P7 k  G! p8 K/ e

  111. # @( D# C, I$ p) v
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    4 N5 X. j" k5 k# Z/ X: i
  113. 0 h2 j" Z/ X& z4 h
  114.   hsd->Context = SD_CONTEXT_NONE;
    7 F3 A1 a# f" z$ p8 i

  115. % w$ _+ R$ W: h0 u$ J
  116.   hsd->State = HAL_SD_STATE_READY;; u5 t! D2 m. i! n

  117. " Y3 t3 u. z# y/ R7 C0 d- i* U, k
  118.   return HAL_OK;
    9 q% w- Y& x8 s( D9 ?
  119. }
复制代码

, U0 X4 @' @: D2 }函数描述:* |& t# T7 p* d) K" T

, P' k: n; e5 q2 S: c* y/ F此函数用于初始化SD卡。' B: b% F. s5 `! A/ `+ w1 q

& \4 H) n3 [1 H% H函数参数:
* r4 U  d" `! W
. p3 q" B! C  H; B* L% H  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
  t, e1 ?# G" d; g  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。9 [: ]$ W9 G: T( O$ g

# h$ x( g; d: ~- t; F8 A1 q$ K. }; q4 p/ _& p  J
注意事项:
5 S% V- I3 A, o2 y) _函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
  ?3 W) R/ y" D% X; H  Q( [0 D' I如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
0 v) o& l4 f9 q0 {对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
* I; U" T4 O8 m0 J7 s, O5 c" p: z6 I* n" Z! Y
解决办法有三* D: f. O' n% W
( X& b2 m9 {3 V0 o2 u! @
方法1:用户自己初始化SD和涉及到的GPIO等。. t6 ]3 J% n3 x4 w, G& B

$ Q+ w- ^1 q" V方法2:定义SD_HandleTypeDef SdHandle为全局变量。  P) g+ Z1 }. w0 S. m

0 p/ u4 b$ A/ r- p) {方法3:下面的方法& h0 W1 A0 z% L2 D! J% T

" v' ^9 N9 [. B& A, Y1 w
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    ) {9 j! `( L% \" v
  2. {
    + L" V0 @$ t1 N) V
  3.     Error_Handler();
    8 ^; P" i- k, _& U* A. W
  4. }  * N: l/ z$ G5 e
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    - g- Y0 ^2 J0 S# A& f; m8 l
  6. {
    : q) N7 p: l( c' b0 Z+ L
  7.     Error_Handler();/ M+ B2 v% K6 x, o5 G2 n% [4 T
  8. }
复制代码

* y, N( R3 ^8 t3 o使用举例:2 p7 v0 k0 M. e+ B4 Y' v- n

1 m6 z' v& a4 m' t, h/ w$ i( a
  1. SD_HandleTypeDef uSdHandle;
    % p$ f: M. h) B+ e' I* B6 [

  2. 7 D9 U: }1 e$ W9 J% `
  3. uSdHandle.Instance = SDMMC1;
    5 u  Q. W" o# J" t' b
  4.   N6 [9 |3 l# i7 p6 h
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    $ l& u3 y% L- i9 V3 g' A/ a, b+ C
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].+ `+ _8 J) X* |" e7 P* [' j
  7.      200MHz / (2*2) = 50MHz7 r( G& Z  `7 `2 a+ {3 G
  8. */+ w  m: O+ c# R! B6 Q
  9. uSdHandle.Init.ClockDiv            = 2;
    + C$ [2 P% {& z- c
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    % H9 P' ]/ x' B; f% J6 \
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    ) `3 h4 I* U8 f. a6 V# J
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    . N+ w. p. G2 h1 q1 c) R1 E
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;/ I( X7 X* P) _, M3 t( B5 o
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK): }; m' Y/ {9 O4 ?8 ?) y
  15. {8 B, L4 h! X7 W* H, i$ r. i" u
  16.    sd_state = MSD_ERROR;
    + l3 Y+ i' J6 E, w2 x# q2 l
  17. }
复制代码
# [1 U  n1 A- S4 B
87.4.2 函数HAL_SD_DeInit
/ |; u7 f2 l& P
函数原型:  t# y" b& ]$ V% ]' g& e

7 Q9 H3 F2 B4 d! ^5 x* Y! t
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)4 @6 `1 H) Q' s$ `- l6 R3 q. S
  2. {5 M9 c; P3 s4 u+ R& S4 c. B2 Q
  3.   /* 检查SD卡句柄是否有效 */
    9 e+ M, b3 I7 m; w
  4.   if(hsd == NULL)
    # y% g  E) W- i1 ~' c
  5.   {
    . z7 B# T( x1 C% ^1 p  v* ?
  6.     return HAL_ERROR;
    : m/ q( m* F! y$ `" |. @
  7.   }2 \; B' ^8 q: F9 \! i2 u: R6 S. _

  8. 4 i, G4 `. o' e- L8 P
  9.   /* 检查参数 */5 \4 t8 _' `! L7 G8 @4 X, \; l
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));6 y  A1 Q( S9 B$ Q% z+ j
  11. ( H; Z: o+ x& X' m; W2 y* y0 H
  12.   hsd->State = HAL_SD_STATE_BUSY;
    # g  c$ [& J; J' m( W3 `- J

  13. 3 ^2 q" L9 A4 J: n
  14. #if (USE_SD_TRANSCEIVER != 0U)
    ) o* O. x+ `$ B1 r3 ^- B& a
  15.   /* 关闭1.8V模式 */3 k; H3 b# A* T5 \+ i) |( Y
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    9 @  ^- B. R' c/ {' g
  17.   {8 N; R( }  ]$ S; P
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)8 u, n- @" h$ k4 t
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)0 o5 l% s, j# W0 R
  20.     {$ k- A1 f# A  i* k
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    4 W6 N! {% k* N* j, ?1 x$ x
  22.     }
    : S: x* S$ _- d1 q4 d9 c2 l$ W1 z6 D
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);
    4 O4 J5 C0 J' P0 {" a1 O5 Y
  24. #else0 r4 Z" |+ e) {5 F8 W: H* A7 X
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);% z- z/ X' R) ~
  26. #endif 9 O, O8 ^5 E: j6 m3 h. L
  27.   }                                                                         % e8 f0 M5 a4 r& y1 X" Y
  28. #endif/ T* ]! `. U- U, J: U& F1 A% R! v

  29. 7 @4 Q+ F$ ^& X4 U- W+ F- O2 I
  30.   /* 关闭SD卡电源 */
    6 e* u. ~. `* C4 t6 S2 A: ]
  31.   SD_PowerOFF(hsd);8 z. G" @2 p5 `$ h+ i
  32. ! A  o3 H1 L1 k% W
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)3 l+ N" J- ~0 X- F5 P2 K  w
  34.   if(hsd->MspDeInitCallback == NULL)
    + ~0 m2 @- q# G. v6 ]
  35.   {
    ' x4 C" d$ n, H5 p: Y" Z
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;4 e6 D: r4 E" O) D" s, z
  37.   }
    ! f" ^! ~+ \6 i
  38. 7 o& A  p0 [" [- Y" z! x
  39.   /* 复位底层硬件 */
    : y# T1 `  b4 o; w' A
  40.   hsd->MspDeInitCallback(hsd);
    % M$ q' c: x; w: T% S* w
  41. #else9 x+ @  d4 w& D% ~/ _
  42.   /* 复位底层硬件 *// }% b% A: x; K" t6 C- H+ q8 |3 I( r
  43.   HAL_SD_MspDeInit(hsd);. Z% ?+ V! t6 l( M! Z$ i' p7 a
  44. #endif
    : k% W' R( [- S# j1 w3 L
  45. . [) `) X9 g+ h2 h0 l6 A! S
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;- L. Z* T" I& H/ [: F7 a
  47.   hsd->State = HAL_SD_STATE_RESET;. k1 \/ i! f) L) u0 \9 x

  48. 3 p  |& L% s' L% P% Z
  49.   return HAL_OK;
    1 \- t& P8 @" H$ B
  50. }
复制代码

9 Q& s* r7 y, s* q; }函数描述:9 C8 m+ F$ V$ H! T7 X0 u& {
4 \0 z/ C( L, q. }! O% `
用于复位SD总线初始化。
4 K+ |2 q0 W2 s1 V* T0 Z( F% z$ b
函数参数:
, J5 c* ]8 [, D4 h
3 h+ n+ t/ I' k* y' w 第1个参数是SD_HandleTypeDef类型结构体指针变量。
8 c& D3 L% O+ L 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。; E7 Y% X7 e9 D2 I

( f" R7 p- M. S' X87.4.3 函数HAL_SD_ReadBlocks
; W% X! L# J% q: e, X" ~函数原型:2 ^" s" H" S, Z9 a, H
* y5 h5 ?, b0 d+ x, v- K4 `
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)) h, b$ O6 d! t+ ^' X- U, [
  2. {
    , O# o3 S8 }' x# |4 I8 s) B( o
  3.   SDMMC_DataInitTypeDef config;9 f: f- N% c- }7 S" i6 q9 G' X
  4.   uint32_t errorstate;* z+ x3 ~2 t6 `% P
  5.   uint32_t tickstart = HAL_GetTick();' \# D, s7 H* [" E9 W7 J! h
  6.   uint32_t count, data, dataremaining;, L  M+ {, Q7 s9 L' R2 C  P
  7.   uint32_t add = BlockAdd;6 r& Y, ?7 y% I6 I! Y
  8.   uint8_t *tempbuff = pData;9 D# [$ d1 c* Y) E' `

  9. . s3 i. j' Z5 A/ W. K+ C3 C
  10.   if(NULL == pData)
    % m. p# X# O% J' ^2 E9 ?
  11.   {
    & U' \4 U; T& c# q) I8 K
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;+ Y8 n5 \9 Y' t8 a9 t) `
  13.     return HAL_ERROR;/ |5 b" l, U+ L- T) Z" K9 |+ x
  14.   }
    6 ?% c: o& z& i% Y
  15. : y2 k: R* W; a. _% K
  16.   if(hsd->State == HAL_SD_STATE_READY)5 v3 ?5 f1 o6 S3 U* j0 i+ y# F
  17.   {' W1 H- l5 P' i: u! v; u+ P
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;& n0 \7 Z: E* v3 L' o4 ]

  19. - F! J' N' ?2 z; D7 |* X
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    : N( M: u$ b0 G5 k
  21.     {$ C. l$ [- o9 e+ K3 q0 x% k
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;0 z7 W3 @) _( i# C
  23.       return HAL_ERROR;
    ! R) J8 z% k4 v% @6 B8 x# ]; R
  24.     }
    3 t. T7 K$ t' _# t# s5 I* |  z

  25. 9 b6 ]) \3 P* r) o* n
  26.     hsd->State = HAL_SD_STATE_BUSY;
    5 }7 {; ]: @& f1 R* b

  27. / o" b5 `* F6 C& k7 o/ g" @
  28.     /* 初始化数据控制寄存器 */2 q& a0 h3 V( M* l
  29.     hsd->Instance->DCTRL = 0U;& a3 u  J: _  p6 k% R" J5 ]" T

  30. 0 C# t; B; @; I. h7 N( b
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ! p( P) _/ X$ W  X1 Q
  32.     {
    % {/ a7 |" f( s4 z( G! W
  33.       add *= 512U;
    : ?0 z" p* N4 \6 \( R9 M* a
  34.     }/ R3 y5 P' b6 O% I

  35.   ^. ]: l/ C% ?
  36.     /* 配置SD DPSM (Data Path State Machine) */! Q4 U0 E# t+ W( \& J
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;0 h/ V3 a- V: s# v: z
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    ) k! h+ [& ?5 a0 c3 A# U
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;* ~  R, {1 t$ |
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    5 y5 h. ]% b. A, I/ v
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    ) L( I5 A% S+ C5 _8 D5 a8 r
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    1 `6 d) Z- b" }: V/ P+ x5 N
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    5 h7 V/ z9 f) `' V; F
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    6 c6 R) o( o5 C, F% G

  45. # R' s$ r9 Z; ~' K
  46.     /* 查询方式块读取 */
    1 f! k9 g6 X9 L& ^9 _* |$ d
  47.     if(NumberOfBlocks > 1U)
    " k) H% t% m9 G$ }1 n
  48.     {
    ( }+ z1 Q+ Q3 ?9 l$ t
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;$ C0 z& k. \2 e( C- \! ~; e

  50. ( O; \' \4 T8 r
  51.       /* 多块读取命令 */
    # Z7 p* N3 B' t
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);  c# A$ L7 P) [0 w' R
  53.     }
    4 k9 U4 d6 x# a
  54.     else9 {3 Z& X$ f$ r0 |& G" w
  55.     {
      r+ j. K" a7 t$ U! q
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
    9 V' ~4 P/ x# \, \$ y8 `) Y- l8 ~

  57. ' w2 ~& `* G) O+ Q
  58.       /* 单块读取命令 */
    0 X' Z6 c! I" |' g0 Q
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);3 U* c" b& `: {
  60.     }! V% ^/ \3 Z9 t! M+ V# C1 v: I
  61.     if(errorstate != HAL_SD_ERROR_NONE)9 O5 A9 r; x! Z6 U2 D
  62.     {
    + S: ^  ]2 [" J9 O$ g9 l
  63.       /* 清除所有静态标志 */; ^7 l  b1 `5 I/ j7 U
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    & _+ q2 J. u+ b6 q  q# L
  65.       hsd->ErrorCode |= errorstate;
    + v) \1 k) X4 |6 W
  66.       hsd->State = HAL_SD_STATE_READY;2 z! T4 b, d" D: K2 H! m/ h* j5 \
  67.       hsd->Context = SD_CONTEXT_NONE;
    ) U. H& G9 p% g2 {6 x7 ]$ z
  68.       return HAL_ERROR;
    $ c( N! i# {" o1 x2 o  p: ]6 n! s
  69.     }0 U8 m3 X, F1 ~- i" F
  70. - ?8 [7 O+ u9 Q: z0 h: D9 Q, i
  71.     /* 查询SDMMC标志 */" p4 f4 `9 [$ j: k1 t
  72.     dataremaining = config.DataLength;# R2 K" N' P4 t+ {7 p" k" l+ j
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))5 Q& I1 u9 @; T* K9 U' v
  74.     {; A" [' L7 @- t7 ]3 E/ U  P$ p" }9 K' L
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    : i$ @& d5 Q  @" k, A5 n# k
  76.       {
    ) p1 K, a/ G6 Z5 g' j& b
  77.         /* 从SDMMC Rx FIFO读取数据 */6 V* _. I$ X. L) ~6 n5 [! i7 c
  78.         for(count = 0U; count < 8U; count++)7 M; ?  j: d& G" [  B+ I5 ]5 i
  79.         {# |8 x" ~  |& `2 @! Y4 L9 S  |2 I5 X
  80.           data = SDMMC_ReadFIFO(hsd->Instance);
    * p8 n% ?5 ^* ?& n- A: `1 J9 _
  81.           *tempbuff = (uint8_t)(data & 0xFFU);
    ; A% [4 `& T' x+ ]
  82.           tempbuff++;# @/ Y, r8 K1 L' ~: H( D
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
    . o1 Y9 A% t+ [7 c
  84.           tempbuff++;
    & T6 F9 x  F/ V2 j6 b  S
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);  e2 y" h" z# j
  86.           tempbuff++;
    ( C$ M9 o& p( q! b. ~
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);( a$ q* ?0 v% w* k1 h
  88.           tempbuff++;
    ; |! k. @  h4 Y' G1 \
  89.         }
    1 ]# @5 ?. x' E: D  \0 r4 e# v
  90.         dataremaining -= 32U;, ?9 K* _- Q5 Z  N
  91.       }
    . p9 \* w  N: C- |
  92. % e3 T" ]' H# H+ G1 t: R
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))+ n( E6 n/ T/ S9 j( R& E
  94.       {
    0 E+ z! j& m1 `7 W) k, N8 y
  95.         /* 清除所有静态标志 */
    - a0 _0 Y$ a) ^7 Q5 t; u; \) c
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    " p" Q% X  ~$ i9 Y7 @
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    ) t  T9 L# n' q5 R' s) H
  98.         hsd->State= HAL_SD_STATE_READY;
    ! D2 e' S" I* X
  99.         hsd->Context = SD_CONTEXT_NONE;
    # ?1 x( M" ?, E
  100.         return HAL_TIMEOUT;5 H+ W! T' M  ?( g6 i
  101.       }
    - {" l( I6 h7 F* h7 j$ T# H
  102.     }
    . S/ o* S7 C8 x- n) U  k. E1 X; o4 l
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);+ h$ [+ \% Z# j% w  I+ O' P: A3 c

  104. 1 Q0 \+ g% c* [7 f
  105.     /* 多块读取发送停止传输命令 */! J3 D0 D" k1 O- [" X2 R( X
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    6 c. Y- n- W" P# ~# Z
  107.     {& Z/ M; n) e- H
  108.       if(hsd->SdCard.CardType != CARD_SECURED)" k/ j/ h5 t2 a
  109.       {) ^2 D- K% I0 L% N# t$ \& H! z( X
  110.         /* 发送停止传输命令 */
    " ^$ T( w5 c3 g8 {$ O0 l; W
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    $ _$ y  N# g+ P; C0 U3 H; Q
  112.         if(errorstate != HAL_SD_ERROR_NONE)& c; h$ r% @+ i$ o' ~, B
  113.         {
    # \( {. `. A2 k! E
  114.           /* 清除所有静态标志 */
    ) K+ J9 s; E. M" u/ C, {
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);/ D/ m9 {* d: X( M; H9 X( \
  116.           hsd->ErrorCode |= errorstate;
    4 O1 ~8 L" J$ P- z
  117.           hsd->State = HAL_SD_STATE_READY;
    1 t" S' b# S* \, E0 K8 x# [2 B; y6 q+ |
  118.           hsd->Context = SD_CONTEXT_NONE;
    5 X: H7 e# ]9 m# ]
  119.           return HAL_ERROR;
    0 m5 M! F; Y3 O' ?
  120.         }
    2 _% W1 Z6 f9 O% ~  [' T' q
  121.       }) D) {$ e, G4 H- m
  122.     }
    ) \% k( `5 i1 Q( |. N

  123. / T. l0 {5 T1 m' z2 v7 C+ E
  124.     /* 获取错误状态 */& E9 }4 T4 s* k
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))3 }0 B! C. K2 Q
  126.     {
    9 o  O3 ~& Z) @. ~$ A5 Q2 Z
  127.       /* 清除所有静态标志 */
    6 {6 W, x( r2 L/ j/ U9 v
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    $ ]* v  k& q3 w* ?4 W( k- I
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;3 B: h) j) {5 U( P; u4 n3 {2 i5 A
  130.       hsd->State = HAL_SD_STATE_READY;$ X' y& e" ?8 i0 ?
  131.       hsd->Context = SD_CONTEXT_NONE;) I0 H% J( e8 V, I" r
  132.       return HAL_ERROR;* U  j, x: f( m  e
  133.     }
    ( f% H, Z/ h9 p
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))4 J6 b( Z" x6 V8 {# g( L
  135.     {9 b( z# v& l( C4 u& t, |' A
  136.       /* 清除所有静态标志 */& r  r4 y/ @+ o8 g( M2 A9 I
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    # @/ h6 r4 w3 H% N
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    % ?$ t* Q' a# t3 ]
  139.       hsd->State = HAL_SD_STATE_READY;
    % T3 z5 ?# p0 H! m2 A5 h6 ~
  140.       hsd->Context = SD_CONTEXT_NONE;
    ; M: U0 U; B. I- a" v
  141.       return HAL_ERROR;# b- R6 x! f* s6 |
  142.     }' f: l4 M" @2 h! _
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    ( q1 K7 t: |+ x+ H8 [# g! `  D/ j
  144.     {1 q' K3 G. l- w: z5 s
  145.       /* 清除所有静态标志 *// j) w, p$ y; t0 z
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);6 E  l, {* |) A6 V: n/ b
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
    2 G9 Q7 G+ I% b. n: c) b$ d
  148.       hsd->State = HAL_SD_STATE_READY;
    1 q" F6 U, V" T* D) H
  149.       hsd->Context = SD_CONTEXT_NONE;
    6 V1 s. r- t3 w% D- z5 @
  150.       return HAL_ERROR;
    * d4 G4 _! @7 m# _2 h1 C$ D
  151.     }( i2 H$ J2 C; u
  152.     else! n( \# S7 U! E) B1 P  G& x5 t
  153.     {! E! h2 c* J8 K" c6 A% p
  154.       /* 什么都不做 */: j% L  ^# g. m" z" _. d" b  a
  155.     }
    5 t5 M# ^- t$ r& s4 G6 `

  156.   a8 Q( ~/ ?, @5 V% p  I" a
  157.     /* 清除所有静态标志 */3 {, a' k' J$ e! S
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    8 R% s. I8 T2 R
  159. 4 |3 n6 R: k9 C) ^
  160.     hsd->State = HAL_SD_STATE_READY;+ [/ q' G7 W& T% }" b

  161. 4 H* y7 k5 V" Z. `; k9 b4 k7 p" W
  162.     return HAL_OK;! d8 X/ s7 N) \& x; J
  163.   }
    # k/ E) X- e, }* ]
  164.   else" Y: D5 z: O) ^  m# z
  165.   {
    $ p- _1 v) ^& l! E
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;+ w7 V- u, e- a3 U1 f5 m, C5 W, G& V
  167.     return HAL_ERROR;
    3 x4 A1 J' C( R8 Y* x- s9 _
  168.   }' x0 \" s9 Q4 W# }% A( d/ x: N( S
  169. }
复制代码

( g* Q( U0 \5 Y! G* M- w& k( X函数描述:1 N# m" [; _. B" y' c

8 v/ x& {4 W+ J% a9 ?, i此函数主要用于SD卡数据读取。8 ^. F6 ]4 T) x6 M7 m. N8 s

3 L6 Q3 W( }% F函数参数:/ p2 z) A& X; I8 u  V4 w4 M! l

; t+ S3 p) u" j8 Y( b3 {  第1个参数是SD_HandleTypeDef类型结构体指针变量。; `( t; N0 U; @0 V( j" W
  第2个参数是接收数据的缓冲地址。3 ~. E+ j8 [6 G( K
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
1 ~. b6 j. m& C  第4个参数是读取的扇区数。  s$ s) O1 E5 F5 D# O
  第5个参数是传输过程的溢出时间,单位ms。4 P( S& F7 r" g. z0 Q; x
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
( h- k: B# [% ^8 N% x( O* L
! p* m% {3 x; k& F/ c8 U9 b2 }; y! X; @3 Z8 A  R7 D1 r
使用举例:, B6 d* C, w, w
: a& t/ A% ~% \6 z3 t& K+ L9 `
  1. /**
    & T+ n0 M  l7 d2 H6 ?
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.& s& }, G1 q! H/ ]" f  @
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    ( @, S" S( Q' y+ k# u2 A$ @' a
  4.   * @param  ReadAddr: Address from where data is to be read% P% S: F% p5 ?! v/ Y$ r7 K9 n
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    ' B) L8 r" ~# Z- b0 d4 _' V
  6.   * @param  Timeout: Timeout for read operation. X6 t+ w" k3 I' ~
  7.   * @retval SD status
    / a8 `3 A- K3 Z' \8 M% D5 e9 \
  8.   */8 _* b( L4 O# L
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    " B( s. y' M7 _3 U. d7 j1 Z
  10. {
    8 ^* B9 G0 l& ?8 T6 G2 k% m  J

  11. 4 x6 E9 V4 ]  H. R
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    : t& \: x( ^* S
  13.   {8 j: l  C! p* N) [
  14.     return MSD_OK;
    $ x, p/ B" e3 ^# T+ E: e
  15.   }
    2 a4 Z) p/ ^% ?4 h# v6 G
  16.   else
    6 n3 E# T7 e4 T% h: g! l, s- ^! U% _
  17.   {/ {6 W- o% x. H- R- Z
  18.     return MSD_ERROR;$ [1 {. e7 r3 U% O
  19.   }
    & Q+ [3 _) ^& y0 a3 u
  20. . K; j3 K- i* Y/ R' p. x! |
  21. }
复制代码

$ T+ R5 D6 a* w+ Z8 a87.4.4 函数HAL_SD_WriteBlocks
) M% g' o# D" q. n$ X* n函数原型:
0 j2 z' ^1 J  E: B( C: E  D
4 `( n# r+ g5 h
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    0 r1 O0 q0 P: J8 s. \" v$ O9 y( W8 H5 W
  2. {
    % v2 ~2 i  Z8 [' ]. h
  3.   SDMMC_DataInitTypeDef config;
    5 S/ V" q$ N. F. L
  4.   uint32_t errorstate;5 _3 O) j- f! L
  5.   uint32_t tickstart = HAL_GetTick();; }1 ^3 t/ C' p. b! B7 m
  6.   uint32_t count, data, dataremaining;$ I$ t3 t, e$ v2 a
  7.   uint32_t add = BlockAdd;
    3 ]' k' e9 t7 B. t* y6 ]# m
  8.   uint8_t *tempbuff = pData;
    ( k" i3 v; ~6 A3 x) G$ O0 u
  9. ! q' k- |6 n' ?, F7 Y' s, i% y6 o
  10.   if(NULL == pData)
      T5 t6 c. v1 o( _) R3 K- j7 u
  11.   {: F  p) c$ e5 w5 U4 r
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    5 O8 G& t& f3 L: a
  13.     return HAL_ERROR;( X% U1 B3 T! u( w4 h2 Y
  14.   }
    6 \9 e) Z5 [6 a( U8 O
  15. 3 \3 r# _3 l% t0 B" k$ O6 R
  16.   if(hsd->State == HAL_SD_STATE_READY)0 f7 e  d5 {5 G! b' _
  17.   {
    # t6 K  }# A; r. N) U
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    / F4 v  _1 s- `* J9 V. p, Q
  19. ( B# p0 x4 {7 J
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    ; o8 J4 B6 f6 w; b9 s" v0 ^
  21.     {
    8 \1 ~' K/ }! x& y5 E9 f" o
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;( i! ]8 O; a4 N6 a! R
  23.       return HAL_ERROR;1 S+ T: |2 W8 a; K8 L# q7 F
  24.     }' z  R4 h. `& B" q% u4 l

  25. / b0 O5 t" q+ z
  26.     hsd->State = HAL_SD_STATE_BUSY;
    + _' U+ s3 v0 Q( `/ A

  27. 2 [$ d& Q* D7 P3 c6 T) A3 c
  28.     /* 初始化数据控制寄存器 */( e" e, W) [+ \3 l1 O3 z
  29.     hsd->Instance->DCTRL = 0U;
    5 X. M5 m6 l) U3 B+ ^3 V1 S$ F
  30. ; B5 g, f1 T$ y
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)" _' y8 z& |& N
  32.     {
    2 f9 S2 E- H7 R' w- i. i
  33.       add *= 512U;! |5 k3 f& F* u
  34.     }
    + `: |' @9 n0 g; l( D: ~3 E
  35. 2 e8 t" `. ?6 w6 @+ P6 r& A
  36.     /* 配置SD DPSM */. L( z: g( `7 O  V; K% X
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;2 }- b; W0 d$ v" I1 E. _  q" l
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;4 ]! x6 K% l, L5 p$ ~* }
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    / L/ _. }% S( \
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    # t8 l8 D% F& D
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    2 T0 ?, N: D: L( ~! p9 _. ?
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    2 |( r2 s% f3 X2 _
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    / M- M: s  t* r+ V
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    - d( @" V/ y5 ?: V5 [0 l. l6 v

  45. 9 X! g6 ^" Y5 R2 v7 N  f0 k
  46.     /* 查询方式块写操作 */- k8 O/ R2 w$ V- j7 f# j
  47.     if(NumberOfBlocks > 1U): w2 d$ v  A$ K4 |" l
  48.     {8 X) e1 J) j& L; \+ f
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    1 s, S; N: a8 @, U! n

  50. ) Y( @- G0 H- o$ Q' q' I
  51.       /* 写多块命令 */( B) D+ k' s" A* V
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    2 `) G/ U- b! O# y! }! i+ t
  53.     }) \, x7 m0 i9 i- N! x$ z
  54.     else
    . s+ q, ]8 k) h7 C5 \
  55.     {  M; m+ p; Z6 h0 A3 H
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;' A' O. Z: |$ ^' J7 Q0 A
  57. ( p% N$ ~" B  a3 e4 _
  58.       /* 写单块命令 */
    , `+ A' L* j$ I  ^
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);9 I: E" n9 P( `) r
  60.     }2 @0 x  W7 f9 K  E( w& P7 W
  61.     if(errorstate != HAL_SD_ERROR_NONE). m2 g) ^1 q3 G% }. R- e3 G6 y
  62.     {0 V' F: a7 y0 E4 v) T
  63.       /* 清除所有静态命令 */
    6 `5 E" q. k: \- j/ w
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 ^' J* [0 [1 l5 y6 V
  65.       hsd->ErrorCode |= errorstate;
    9 f' Z6 P1 _2 S8 I: @+ E  W: h! G
  66.       hsd->State = HAL_SD_STATE_READY;
    . @- ?8 f4 E; y2 h% J5 @
  67.       hsd->Context = SD_CONTEXT_NONE;- r+ t8 I' M. K1 k! r2 Z! j' \3 }
  68.       return HAL_ERROR;
    . b) i/ C2 ^% W/ u/ T
  69.     }
    7 V) t4 v- R/ J; B$ }5 r  n6 A
  70. ) i4 L$ F* ~4 J0 N' F4 [
  71.     /* 查询方式块写操作 */
    & J7 [1 e' s9 U0 C' n. e9 V- G
  72.     dataremaining = config.DataLength;
      e' b# a3 U" b8 s
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    5 x" A; v0 }- o3 K# w
  74.     {
    - B& n' S$ r; [3 L
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    ' y1 [3 r1 v" ~! n
  76.       {0 ]. |7 }) z8 H2 j9 s. x$ ?/ m
  77.         /* 写数据到SDMMC Tx FIFO */
    - B* a; y; r3 {; g* k* [% k0 H4 ?3 f
  78.         for(count = 0U; count < 8U; count++)
    0 A+ |+ x2 f8 x1 X' r  V- ?
  79.         {7 l% N% C+ w, A. c5 w/ _: T
  80.           data = (uint32_t)(*tempbuff);
    - _4 B; }0 W9 M- e( c( k
  81.           tempbuff++;5 H9 s8 ]& H# L
  82.           data |= ((uint32_t)(*tempbuff) << 8U);
    ( f: I  b1 d6 z6 D# R2 h( y
  83.           tempbuff++;
    5 [" g+ b  q, x" X5 j$ L& a3 f
  84.           data |= ((uint32_t)(*tempbuff) << 16U);
    $ [2 ^2 g3 s# ~9 m, X8 i, U
  85.           tempbuff++;
    7 i; \& k5 Z2 m4 i6 E. P/ C
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    9 `0 Y- q, ]3 R( R5 `8 c7 Y
  87.           tempbuff++;9 y8 u/ J+ b) Q7 k
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);# G6 S0 F& k- p) K
  89.         }
    ' z% W7 h) s3 F, @8 N) z1 Y9 c6 o
  90.         dataremaining -= 32U;
    : U/ m: u( `( L* t; p' `1 u7 W) e
  91.       }1 j% I- I7 }( Z2 ^9 h4 H5 K

  92. ; s/ I7 H7 E) B8 t/ ~- u+ n. [7 [
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))5 U4 j9 T# \+ C, E5 I% @& n
  94.       {, P$ L5 u+ J& o& k" m/ }+ L$ q: X
  95.         /* 清除所有静态标志 */
    ' K/ d; o4 u$ @$ z4 I: f
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    1 I2 I- F8 n# k- v
  97.         hsd->ErrorCode |= errorstate;
    ! p) v( h% m* z8 f
  98.         hsd->State = HAL_SD_STATE_READY;8 G- R* m2 d. e) H4 M
  99.         hsd->Context = SD_CONTEXT_NONE;
    7 M% W2 e3 Z; Q, U
  100.         return HAL_TIMEOUT;% O) y  z3 r$ v1 a8 A; M1 A
  101.       }
    & g/ F4 d. |" t# m7 O/ j
  102.     }) W) Y: p0 ^; p+ S) m
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);% c) ?/ B$ R" ?4 Y

  104. & _7 X  \8 D/ R+ {
  105.     /* 多块写操作,发送停止传输命令 */( ~1 D' O& |: u: V% W3 B7 d
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    9 F. [1 ]- v; W2 T( p; a% \
  107.     {
    % n8 j. a* W) Q" I9 f! v. [! r( q
  108.       if(hsd->SdCard.CardType != CARD_SECURED)2 p' u1 |/ k5 _3 B9 s
  109.       {4 ]' C- _  o% z
  110.         /* 发送停止传输命令 */
    ' `1 a5 P8 C) h: m
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);+ _/ d; G" t& s* R- v- \
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    ! y0 \! j5 y8 y" `3 J, G; V9 }% C
  113.         {; m; T' D, E& r2 x  z
  114.           /* 清除所有静态传输标志 */
    ; x5 v; }1 c, k* A# s0 h
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 x! D, x8 e1 t( V2 ^: g
  116.           hsd->ErrorCode |= errorstate;
    9 W' `7 V- b* l8 |  p
  117.           hsd->State = HAL_SD_STATE_READY;* U) l  A" i" b2 ?, H: `, [+ V; I8 c
  118.           hsd->Context = SD_CONTEXT_NONE;  F" a* t  i& e$ K
  119.           return HAL_ERROR;; u3 b' t8 X5 U$ @  j" T& w
  120.         }
    ) C# }8 X1 c- c' H$ G4 A' C
  121.       }
    $ u7 m5 `+ F8 M7 v/ S5 k2 |
  122.     }
    ; y! ]4 X$ v! c; u
  123. 8 G, c# {( s$ E/ G8 M( u) \& u
  124.     /* Get error state */
    1 R/ [- _( g2 S2 N/ b2 K
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    & Q1 [5 L5 j' }+ f; E; l
  126.     {, u* x. U2 L! g: l
  127.       /* 清除所有静态传输标志 */3 N: M/ t& J8 ?+ o8 h$ e
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    7 f8 t; x* }4 y6 Y- ?
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    , i' O: {2 J& O: n6 S# Y- B
  130.       hsd->State = HAL_SD_STATE_READY;
    6 ~) o  q$ U7 A3 ?  A3 a
  131.       hsd->Context = SD_CONTEXT_NONE;: D( d, m9 l* M. ~* s7 e4 G
  132.       return HAL_ERROR;
    8 j, w* O  s) V7 ]3 G& |: w
  133.     }
    # Q+ c+ C0 K! p/ e2 e# p6 g
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))2 u6 J  p3 Z" {, \+ W
  135.     {3 ?0 w% K  h( J: x, c5 L
  136.       /* 清除所有静态传输标志 */
    * n. }5 Q" J. C1 j. p* C9 O
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 y& ~  R5 f  E' e, E3 s
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;; {+ p/ R, a" m6 h6 b' B
  139.       hsd->State = HAL_SD_STATE_READY;
    5 {6 d8 b3 k( A7 V5 i* O% |) P
  140.       hsd->Context = SD_CONTEXT_NONE;% ?9 {/ a( A2 T3 _+ m! d8 X% J
  141.       return HAL_ERROR;
    ) f/ ?" s, E+ h8 I. y* k! q5 X' k% n
  142.     }
    - [' {" f, A7 R6 g& r) R: q
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))+ h, u8 c. c( J0 w5 W1 p6 g
  144.     {
    . P% A5 V7 F! m& L6 I
  145.       /* 清除所有静态传输标志 */' u- K: [# i! Q5 }  w3 e
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);, }, _( c9 m  m- F
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;; G# I5 {* R! A9 q9 U% ?
  148.       hsd->State = HAL_SD_STATE_READY;) p# v! T% y' K+ f9 ^; {7 l
  149.       hsd->Context = SD_CONTEXT_NONE;& A2 q8 a% v* l3 d4 i! {( D- D
  150.       return HAL_ERROR;
    ( Q/ T& u2 M9 }6 r
  151.     }4 z  l- A4 N8 J
  152.     else
    8 X2 u' O8 {( X3 T/ H  N7 o
  153.     {  [9 o/ H- m5 \
  154.       /* 什么都不做 */0 z6 _% U# _$ D$ V) a  e" T+ O
  155.     }) J8 t$ ?5 \  C& t8 D& L; ]) O

  156. # R5 `) T& W2 l6 C. O% L! v
  157.       /* 清除所有静态传输标志 */. S. s' x" B4 [$ x
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);6 G* |4 [& I) m

  159. . t" A0 i8 }' M1 L' w
  160.     hsd->State = HAL_SD_STATE_READY;
      K# ]3 _6 x. U) w9 ^- ?

  161. ; |! w+ t, j3 E& n4 n+ @1 L
  162.     return HAL_OK;
    / J7 K7 w6 p$ f* R6 }0 v
  163.   }
    : E" W( a4 l. Q5 {2 V5 _0 f% i
  164.   else; N/ {, O! m( ~% F8 c1 @. {
  165.   {4 M: q( A/ ]$ p
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;; V; S" }) w% g  T
  167.     return HAL_ERROR;
    ) F& p/ S( \" s# ]9 ]! a' e2 j
  168.   }
    ( s+ C; d! U; j. }
  169. }
复制代码
' w% j, y+ E/ C7 l/ _
函数描述:
# b5 W. U$ O" e$ L# t3 U! T- L# r: C& f* `- e7 f" L: P' s7 Q
此函数主要用于向SD卡写入数据。
: D, t" G* o5 Y4 w) t( m4 {3 Q1 W/ C
7 K5 b( S! Y" N1 d3 o- C函数参数:* P; h. S5 W0 z% |( z

. X. |" V9 j" Y! G; t  第1个参数是SD_HandleTypeDef类型结构体指针变量。
( S7 a4 S8 U" V) g% @  第2个参数是要写入到SD卡的数据缓冲地址。- D! y) n3 ?  |% N2 J- q! h; z
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。9 _6 N1 K7 Y/ H# i( n1 j
  第4个参数是读取的扇区数。
! C+ S# a/ _0 N% |8 b3 D2 j5 i7 `7 T  第5个参数是传输过程的溢出时间,单位ms。/ ?3 H+ y; L) t8 D+ {6 k( D+ |* l- B( _
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
, |* r5 Y: R% E" [! M" A
+ V( }3 o% w% T5 G
8 U, }* K7 H3 c/ p& y$ A5 y使用举例:
& `3 y( U% w+ n4 ~: B' @9 R, [9 E% l  q# G8 K& Z1 R
  1. /**
    ' _3 x2 y6 Y8 A8 Y2 L, {* q
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.- x' w" L& K$ r, x! w  U
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    8 g" L* x* G1 x; b# e
  4.   * @param  WriteAddr: Address from where data is to be written
    ) K6 B& B$ G$ w8 ^9 k3 d* T( w: _- N
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    % C- I# m8 A7 {2 Z+ A6 F
  6.   * @param  Timeout: Timeout for write operation$ k  J, l' L0 u( s9 y
  7.   * @retval SD status
    7 z8 m' d, {* r* S
  8.   */; D% K2 h1 p/ ^
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    9 b5 y5 W; a  @* @7 J( G9 D
  10. {
    . V- N6 j, `0 \+ z; o
  11. 9 b# s! `/ E! X. M- {
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
    7 e9 ^6 O/ q1 h* |: O9 g( v2 L! D4 r( n
  13.   {# f  W" p$ l2 e2 q- q# C5 J
  14.     return MSD_OK;
    ' O2 x  u' U8 D7 L" K
  15.   }0 q- q  G+ C- V( X3 m
  16.   else" c3 C2 X3 C$ G5 ]; \/ ^
  17.   {
    ' h0 a- e. x8 i, C
  18.     return MSD_ERROR;
    + i/ a& q+ b# H. Z" M1 p
  19.   }" |" W7 p$ Y% \' r2 b
  20. }
复制代码
* }3 y6 ^% s6 e- p  w  O
87.4.5 函数HAL_SD_ReadBlocks_DMA

' l4 M+ `* W4 `) H- W) q1 }9 B. b函数原型:
, g, f4 _' T9 e' Y, K7 C8 W. e& u, I
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    , \1 F3 r: E" R" X) a: n& p
  2. {
    7 i8 Y2 j  R  E+ ?2 f8 g8 h+ Q6 u
  3.   SDMMC_DataInitTypeDef config;
    ! _+ W* `* X9 D
  4.   uint32_t errorstate;, |6 M* ^2 v, i, Y6 h
  5.   uint32_t add = BlockAdd;( @# B) l; x/ N1 j
  6. ) _6 W5 q2 S3 Z( o7 n, ?# o) {
  7.   if(NULL == pData)/ X% x/ s7 g% `
  8.   {
    ( d( L  M& J0 t! [0 E
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;0 |* B3 }+ y  j7 d, e, a
  10.     return HAL_ERROR;
    % c- N7 g0 m6 }- r2 [+ [
  11.   }
    . i% |$ u' `: M  a# U8 {
  12. 2 [* P# V5 p! ^+ X- i, x
  13.   if(hsd->State == HAL_SD_STATE_READY)
    : v4 z, q8 l7 A1 U
  14.   {0 U0 J2 l7 w3 b' {7 b6 ~
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;: ]0 r: \8 s( i/ e5 ~, ~, \' X' h
  16. ( l# c) H7 E' o) y) _. }4 V
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    2 b' a! d, N" C9 ~6 x0 _) L
  18.     {( I4 D5 p, ?5 i& ]1 I
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    : ?) U/ f8 A7 E8 k% r+ \
  20.       return HAL_ERROR;
    - \- r- u- o! B) L
  21.     }
      Y6 r# R) n6 U7 p( [, h

  22. ( s* t4 n3 G- M2 l! V/ k% |
  23.     hsd->State = HAL_SD_STATE_BUSY;) X( T  O) ?  `- d! ~

  24. ' q" |. K( A& X/ N" y! ?5 O6 c5 x: L4 W
  25.   /* 初始化数据控制寄存器 */
    8 g2 |7 X5 w8 }' [- F' t/ r6 [
  26.     hsd->Instance->DCTRL = 0U;
    & |* C4 \/ s- g. b, O( U0 F9 a

  27. 2 E. H- o3 y0 K5 o
  28.     hsd->pRxBuffPtr = pData;
    5 _1 f7 V) T2 e/ w. f0 b. Z3 x
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    8 H8 M, p: n$ i: i8 C
  30. 2 S) Y0 J; s: Q% z! N/ q6 W, V) b) B/ i
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    : q: }+ T2 k$ p2 ?( `2 u
  32.     {
    , M) X" Y5 e; C. w
  33.       add *= 512U;
      d, I" e9 n8 l! {/ _, l% i
  34.     }4 F8 \6 M5 J  F

  35. , k' a0 P4 O7 q# b& F3 @
  36.   /* 配置SD DPSM (Data Path State Machine) */0 T% N! c3 l* p  W$ B8 B' G
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    2 b1 n8 T, Y9 J: t1 Q! p% _$ K- u
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;! B/ ]3 }6 k+ a7 T0 l1 O9 \' P* S
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;: q6 ]3 W7 }1 w' ^% o6 K. E; D
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;5 G) H9 Q. f9 z5 R+ ]/ d
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    3 L: b4 E2 b- E5 H( m6 U# p) g
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;! g1 r, b7 Z; X. J! A
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    8 X0 z, k! L# F1 M, ^4 J

  44. * E* f# j5 m/ Y
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    / b0 x' V$ L: G2 g
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;( Y* f  y; Q& C6 b, j
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;; E8 d1 k# \+ p4 S1 S- j: B
  48. . W. M8 `2 e7 ~, S+ r5 i3 [
  49.   /* DMA方式读取多个块 */+ Y& k9 K& n  {) W) z3 ~
  50.     if(NumberOfBlocks > 1U)# B/ a: V  K* [( d+ s0 c  Y  |
  51.     {
    . K5 }) f, @. }5 h) }1 f( R+ V
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    + c1 j- ~0 y: N6 q0 u+ C
  53. : U% T/ n9 a5 N% ^4 I' M0 t4 W
  54.    /* DMA方式读取多块命令 */4 f2 S& p* \0 @7 \" r
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    ! a# _  y6 [; `9 C
  56.     }
    5 I4 [( V  `# u3 W# q6 G6 R
  57.     else3 L' v% `, J1 [/ @5 D0 p5 w) U
  58.     {+ W4 p5 J' w- P0 }
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);1 ]. c6 l! \3 A, n$ |9 Q: v- g

  60. " Q0 s5 Q. k- `7 u" [; v
  61.    /* 读取单块命令 */
    0 M6 B9 {2 u5 n
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    , h- h7 Y' J5 i" [" x% h& L
  63.     }
      m3 e: n4 f7 Z7 V
  64.     if(errorstate != HAL_SD_ERROR_NONE)5 a$ L" O. e1 E2 C+ F) z
  65.     {2 Q6 }. m0 G3 [2 h& @
  66.    /* 清除所有静态标志 */7 R8 x+ c5 P, B: H" u
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' ^+ T7 H) l5 l& j$ ^3 G( {) e8 Y" f) ]
  68.       hsd->ErrorCode |= errorstate;! \& e' \/ u7 b, R4 h7 T
  69.       hsd->State = HAL_SD_STATE_READY;9 E, c) U7 r! D
  70.       hsd->Context = SD_CONTEXT_NONE;: K- r7 u8 r) f+ n" R4 R/ M$ r
  71.       return HAL_ERROR;
    # ^: }+ N, |, J' z% X
  72.     }* J/ b4 f9 f0 i
  73. ! _* y* T/ @8 B; J
  74.   /* 使能传输中断 */$ }- M6 d/ g1 F5 g6 }/ Q
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    ! v) v2 D0 b: w9 G( {8 r, ^
  76. ' V" a2 A' D3 O1 F8 M' o, s
  77. 8 g: D; i9 b6 [' x
  78.     return HAL_OK;
    ' H+ F5 b* N8 Q% N4 w
  79.   }
    3 h; h0 O7 }! x* C0 ?; h9 m
  80.   else
    8 X& J! _4 c/ t) a- n3 h
  81.   {7 r! M) N/ n. ~& r" ?
  82.     return HAL_BUSY;0 o$ C! a5 I+ S) c( |
  83.   }4 c3 q& j( I/ a6 F9 q0 z
  84. }
复制代码

9 N9 [5 d0 \- O; w函数描述:
5 J" Q; B6 Q" E) e% m: B( U$ s( ]( a9 u# _6 Z. z
此函数主要用于SD卡数据读取,DMA方式。9 F) }7 ~* w5 I: L  t% Z7 Y
& S( N0 }: `, }( Q
函数参数:
& l+ @: P2 n3 r; S" ]4 Z* ^1 Z% _0 s, Y8 g
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
, {+ Q7 v# y+ ^# M* j% |: L# y  第2个参数是接收数据的缓冲地址。& i2 G5 _9 ^! s6 G' b0 k5 q) a# j
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。* |$ A# g, Y0 u# C# {1 F2 X: X" d9 ?
  第4个参数是读取的扇区数。
1 U, e2 T! _+ y* s& i; E) b  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。5 c7 i, c% h' X0 r( T$ p
" E7 K* ]( f- c* K. \8 W
0 w4 E% P* b, T. H" d8 R
使用举例:
7 Z4 |0 A: r- q
. [( d+ U7 V: {5 B
  1. /**4 k7 }) k- {) K; J
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    * o$ ^$ Z1 T  V: _; E  i
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit" j! B) G2 |7 l5 f
  4. * @param  ReadAddr: Address from where data is to be read% x3 B: c: p5 ~" o: m( \/ x
  5. * @param  NumOfBlocks: Number of SD blocks to read
    2 U/ l6 ^+ X* O+ C& A
  6. * @retval SD status3 I7 [; W7 Q4 K5 e
  7. */
    ! m; _% [: K8 f5 P
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)  u" E7 L* ^: }7 P
  9. {
    0 s4 Q( v& O4 x$ N+ u" @+ e9 t" E
  10. . }% O" e; \7 \/ J  F
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)6 h4 b' c1 F0 B
  12.   {7 O' G0 j- n2 o
  13.     return MSD_OK;- j% w- z6 ~$ V- }# E) c" K
  14.   }
    6 e8 \' J5 I" d5 {" e
  15.   else
    5 O  G" r2 g4 P" B- ?
  16.   {/ ^' q, D; X# y/ C0 C
  17.     return MSD_ERROR;
    + K' U5 O$ F+ Y5 A' |- Q, J
  18.   }& n4 p+ G3 j4 m/ [7 d! L' r  [( H
  19. }
复制代码

  s" x* v: T6 O87.4.6 函数HAL_SD_WriteBlocks_DMA& Y' m) X& e3 U7 R
函数原型:
$ h" ^. O7 Z. v8 D$ U) e, ~  s) s3 f4 O6 {% c7 }) G% b* G
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)0 d* @( _8 M1 c. o' u$ _/ U5 I
  2. {
    7 I- x! f( U1 M: b$ m6 Q
  3.   SDMMC_DataInitTypeDef config;  ~/ N4 R. v% h% B% M& u2 }( H
  4.   uint32_t errorstate;
    ' c$ V0 r! x# N$ K
  5.   uint32_t add = BlockAdd;
    3 r3 j9 `2 ^  @+ s' r

  6. 0 M9 ~" d  t( ?* J4 G
  7.   if(NULL == pData)
    ' K; F8 A* d) ~( c- C' G
  8.   {1 _) i" L: x" n) X+ T) X3 x
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;- I% h  }$ L' |: ^6 m
  10.     return HAL_ERROR;( X: \% w% A6 T. Z# [
  11.   }0 s. V9 W3 ~/ g

  12. ! q$ D4 d. D$ d$ Z
  13.   if(hsd->State == HAL_SD_STATE_READY)! u4 s; Y& I, n! a; v
  14.   {- D* g/ y3 @2 \8 z( q
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    3 v! U7 F4 H, {, E& L% D( W

  16. 3 {: |: B$ d' E) K
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))2 }4 D: H% A0 i" @
  18.     {7 ^9 G# q% S! Y" w! Z, e+ U) c
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    ( y* u1 h# {! Y$ G/ Y2 `
  20.       return HAL_ERROR;2 ~+ M. J5 W8 ]- R: g6 o
  21.     }9 N6 ?4 g# y. G) d' L" E

  22. 0 z" Q0 N9 V2 c) n8 @9 ]! C; c1 o  c, ~
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ; x) P: q" S1 H) X  L" ?/ o
  24. + k4 A4 \  S( ~* a5 O  q
  25.   /* 初始化数据控制寄存器 */2 r% P1 }9 _! W
  26.     hsd->Instance->DCTRL = 0U;
    - H8 u$ s3 R! ?  J5 @
  27. ( I; i# y) i" b3 I) @
  28.     hsd->pTxBuffPtr = pData;( c2 e% e% u9 g# @
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
    7 W* a8 y7 N, ~7 k- G; i; v( a

  30.   _3 d& x: k8 ]. q4 _# I
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    $ D4 v3 [# q- ~
  32.     {
    $ @" I" {( n' n4 y# c/ C
  33.       add *= 512U;* m: O% V: l5 J' v9 \# a* g5 ]
  34.     }+ A0 N* J1 C( K& s( R6 ~0 s: y- c/ l

  35. : n; N$ Y; g6 L5 n( n5 u! j0 ~# T
  36.   /* 配置SD DPSM (Data Path State Machine) */1 }- p- A" l- W' x  l
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    & P( v& y9 A2 A0 h( f  y9 p4 x
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;$ x; b9 P0 U' e. S% u. r0 z$ ~; z) `
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    8 s$ O  E& L1 j6 ?" ^2 T
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    ) j7 J0 x' N8 J1 J
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;' s- \3 }2 j6 C/ O+ q) |3 h' p
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;, `$ z( B7 @# D
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    5 ~5 q; E( f, O, j! [3 F
  44. 0 O: W1 E" v1 d% e8 |$ M# n

  45. * H! d8 D% ]8 ]& r* V0 l
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);5 ^( c9 d; y' C# P; [

  47. , y. Z; v* M9 y) h$ p5 E: A! ^
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    % T+ _. m% {5 m2 B0 k
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;9 n! g5 X' B- j+ Q; j. E$ e
  50. & ?% o! D6 ?4 L/ n
  51.   /* 查询模式写块 */) s, [2 s7 i+ m2 |) g( [
  52.     if(NumberOfBlocks > 1U)$ Q2 f; |6 Y" n' Y8 ]
  53.     {: Q( A" w/ x0 `- U. g
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);3 Z& c; p- K9 A. Q7 A1 G
  55. 8 R5 I# y% Q$ s2 B" T$ S9 _& ~
  56.     /* 多块写命令 */  M) m( v7 Z" E7 m
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    . |) T3 `  v, G3 T  N) L: ~5 h
  58.     }
    $ G- h; S  u: G- V7 D5 ]
  59.     else
    ! B& \( }3 s: Q, N. I$ e8 n7 F
  60.     {
    / ^: e4 H6 N, `3 o2 a# N
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
    5 ?" B& o4 V! y
  62. - ~) H6 s$ M: I# O* J
  63.     /* 单块写命令 */
    5 D5 c# g: K. T/ `( ?( L
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    0 \9 m0 v' o0 I* F! ?& f2 _8 v0 Y, T
  65.     }: H; R5 C; K# ?2 {$ v; r2 K
  66.     if(errorstate != HAL_SD_ERROR_NONE)1 T+ K/ V; O- a5 o3 E
  67.     {
    8 u4 M9 w: _5 H7 ]
  68.     /* 清除静态标志 */
    " a7 e( }) t* y4 b- Y
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; g4 c4 i6 x' N0 {0 ?4 ^, i6 f/ E3 x, v
  70.       hsd->ErrorCode |= errorstate;' O2 y$ [2 G5 i3 ~3 Y. k5 I
  71.       hsd->State = HAL_SD_STATE_READY;* z# @- W! J4 f3 w% n: {# D: m& ]' k
  72.       hsd->Context = SD_CONTEXT_NONE;9 K6 o& W- Z. g4 g
  73.       return HAL_ERROR;
    3 s! ~3 ]" B* M( p( V# u: N% a# n
  74.     }( P. N: I! Y. X3 \$ E
  75. & Y/ Y6 N7 }0 i
  76.   /* 使能传输中断 Enable */" W: u4 q9 p4 q& C
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));) L9 P  d+ I, H* I: x) T* F/ D2 R8 z2 s
  78. , f0 s# G, j) M. ?) k
  79.     return HAL_OK;+ T8 y% W8 ]( M
  80.   }# K# C  n5 M" Q; `& F
  81.   else/ m9 Y% }* \" B
  82.   {! B! h$ o8 Z0 R) g3 w8 O
  83.     return HAL_BUSY;$ a' G6 Q- V5 z  g* }" I+ L
  84.   }
    + U) ]/ L4 d% Y
  85. }
复制代码

1 ?; B2 k6 A# U3 L函数描述:
8 v; J# w% j& W" h% L* P6 z; I, L7 y5 {1 ]4 ]4 D: e+ D
此函数主要用于向SD卡写入数据,DMA方式。
4 ~* _7 [3 n2 Z5 `; E, q( C; p) s7 C- Z# m7 v8 ]. V
函数参数:6 u" }! U( J8 D2 u  \0 L) F
+ q2 J9 [, l* O. ~  D/ v
  第1个参数是SD_HandleTypeDef类型结构体指针变量。/ W9 O, U6 q& e# N; b7 E5 f7 D
  第2个参数是要写入到SD卡的数据缓冲地址。
3 D  c( l7 M: ^7 T  a  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
$ l1 a; F  w+ b9 ]* y+ M3 a: }: @) f  第4个参数是读取的扇区数。
6 o: Z) Z- l2 t  s  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。0 G! f; K8 |! z9 Y( V- U

0 F  X" }" g9 r+ j' [$ n9 \
4 k$ r, ^- j4 E7 t% k使用举例:
. X9 ]+ O( [; G! K2 T" ?3 y% A. j- V) Y" C9 K% N
  1. /**
    * E& ~) H0 D3 F3 l9 W0 x
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.3 y1 [9 W, i7 m5 G9 A8 A
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit. x' u7 I. \- L4 B5 z8 J1 l
  4. * @param  WriteAddr: Address from where data is to be written
    2 O' P+ O9 S# C3 Y& J& ^& k+ f
  5. * @param  NumOfBlocks: Number of SD blocks to write
    6 g* C+ S' d/ t# b$ @$ N" K$ g. O: _
  6. * @retval SD status
    4 X+ c/ X0 B: C6 r* ^8 \7 \& o4 F4 J
  7. */
    ; @2 i8 H: e: p# S7 i% k! }& T
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    0 Z# Q. ]# v  ~- G& M# G  X' E
  9. {
    6 |4 F$ r5 J3 ~* j, W$ L
  10. ( Q% T& O3 U% X! P
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)6 w' F' W+ H$ g4 P
  12.   {
    ' G8 E' x1 b; u! X2 P1 D! i
  13.     return MSD_OK;
    # |" M! @2 f1 ?
  14.   }
    4 u. x2 c. M- l8 m' f1 X7 J
  15.   else/ D6 I1 t. ~' p6 l" y# P2 W8 T3 V
  16.   {
    6 ^. r- O7 @* x) q4 J
  17.     return MSD_ERROR;2 j3 a" m, p3 j* L5 H+ D+ B7 y
  18.   }2 i: t9 k: k* Z
  19. }
复制代码
  p5 L) S8 `* g8 f" l! H
87.4.7 函数HAL_SD_Erase
% p  F; H* B, a: S/ h% a函数原型:5 r) A! F% L7 A$ P& h

9 V$ d( i* K- B3 [5 w9 `
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    1 p# v$ d0 F( [& u
  2. {
    $ e' ]* i9 h  Z  a" N! Z% c
  3.   uint32_t errorstate;3 `0 {9 a1 \: V4 @9 Y7 S
  4.   uint32_t start_add = BlockStartAdd;
    6 F* W$ U: l7 I/ j) \3 @, M3 C
  5.   uint32_t end_add = BlockEndAdd;$ D, Y! k* L- `" D: G5 b

  6. 5 Z' x7 B/ j5 M# ?& S
  7.   if(hsd->State == HAL_SD_STATE_READY)
    # t8 P* r+ v9 X/ V8 Y1 B( j. R! T
  8.   {
    $ N' j6 @/ u6 c/ @
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;- N' K8 k1 q$ F( i+ O: y8 x( J) Z
  10. ; e# V: `5 G* C/ N7 B
  11.     if(end_add < start_add)
    * E1 Y+ e% d2 q
  12.     {+ r! v# z$ j' f: k- _
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;- l, e& |, L: b6 H8 ~$ i
  14.       return HAL_ERROR;0 \' x3 z4 f2 ^+ \% g8 _/ E
  15.     }# t2 ^& N& [* K" B# D

  16. " ?3 {; ~0 ]4 U! ?2 Y: T, _
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))
    - H# [6 G9 B! C
  18.     {
    . m. A, R8 i/ Q% T( a8 r  M6 q7 P+ A
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    / [& b0 Q) g4 A  `$ f+ K
  20.       return HAL_ERROR;- R! R6 C9 y. a0 T' v9 a5 Q
  21.     }
    5 ^- ]7 H* C  p4 s! t9 U3 Q

  22. 6 s  F' K5 a5 i, R: \) D, g
  23.     hsd->State = HAL_SD_STATE_BUSY;
    - \; U& B4 `2 H: L9 q0 _6 N8 D' v

  24. 7 I: H3 L+ s+ o% l9 `* K/ X
  25.   /* 检测是否支持擦除命令 */% K  H( i8 i4 ?' q9 Q3 Y, p
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    - G  ~. k  `, F- ]4 @# t
  27.     {6 T1 A5 L( M9 M2 r5 r! Z4 v; T2 t& e
  28.       /* 清除所有静态标志 */% |2 R8 Y" \, _: N
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);& q$ D$ N: u1 X1 n2 ~& z
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;3 B, d& y# `# T4 Y
  31.       hsd->State = HAL_SD_STATE_READY;
    $ S, v7 o9 F5 F1 o& |
  32.       return HAL_ERROR;5 x4 D7 H! n6 I/ S! M
  33.     }
    0 }9 j  e- {' g& \, r
  34. ) T: Q4 j0 ]: j" g% Y' K$ H# c5 [
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED); C# ^' _! m$ S, J5 |& ]
  36.     {" j8 r- }  ^* }; E$ @6 S3 r; w
  37.     /* 清除所有静态标志 */
    ) i% h+ k0 L0 D
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);3 ?: _6 ~5 l0 y8 r' D/ i' {
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
    . `' p5 F: U+ a3 i9 l; w" X
  40.       hsd->State = HAL_SD_STATE_READY;
    5 w2 I3 U4 M& q4 ^) ]0 j+ Z
  41.       return HAL_ERROR;
    ; p1 @! v" u7 }# M4 X; d
  42.     }
    8 j8 W+ C" W/ x/ ?& ~0 Q9 @
  43. ! C4 D( D3 z" G. Z
  44.   /* 对于高容量卡,获取起始块和结束块 */
    . U! }2 _% x2 i+ I% S* z
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)+ t( n; ^5 V& p1 \- f2 C2 k$ h: ?
  46.     {
    & [: `1 Z7 [- k6 y1 o
  47.       start_add *= 512U;
    . b0 ]6 A) s/ n( W3 k
  48.       end_add   *= 512U;
    2 Q: q9 Z0 \' v9 X6 n
  49.     }
    / T) p) @- o4 @. n" M
  50. * ^4 T  W  h0 O& x
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    : V: _* E7 S) J7 e1 O$ O! ^
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    ; K) G& h# ^5 G2 L% j' t
  53.     {
    / b3 V5 ~8 m3 q" g6 I! I+ I4 m
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */8 `& I" o' b* ]6 H  S; ^6 P' H
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    4 Z0 r" `- L, d: i2 }) @+ e
  56.       if(errorstate != HAL_SD_ERROR_NONE)+ V# H6 Y6 e7 U2 A
  57.       {
    1 t- v" u) E; R9 d! f; K4 I
  58.         /* 清除所有静态标志 */
    : |7 }' g- n* i8 D1 p
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    8 |) B4 P  W- {# o9 \% \
  60.         hsd->ErrorCode |= errorstate;7 E8 O+ F. S9 T* J
  61.         hsd->State = HAL_SD_STATE_READY;
    ; j8 |/ q5 j& b$ g( d7 ~0 I: x" L, A
  62.         return HAL_ERROR;
    , j0 F5 t! l$ x1 o/ T8 Y* m' e
  63.       }& ~7 j: b0 z! j
  64. ' H1 ~% q( H# q- l" ]0 |
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    ) ~3 m0 n2 j" d! R
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    7 ^2 W* F7 S2 Z( O( i
  67.       if(errorstate != HAL_SD_ERROR_NONE)
    + J- y5 N4 M8 N! ?0 @
  68.       {
    3 s2 ~/ C. }& Q& I
  69.         /* 清除所有静态标志 */$ T8 @2 V7 _: d! O# T4 B- q+ \0 o
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);. ]# q4 b1 d; x8 a2 _
  71.         hsd->ErrorCode |= errorstate;
    * `( N0 B+ Y- t! K; i5 ~% _
  72.         hsd->State = HAL_SD_STATE_READY;
    2 f5 w( U) N: q
  73.         return HAL_ERROR;
    & N( q( ?4 X/ s; \0 ?
  74.       }
    , Z6 h  [% @4 E! N' O
  75.     }
    8 H5 ^- p, p# |. X8 t, q

  76. $ X% p6 }4 U  T7 a
  77.     /* 发送CMD38 ERASE命令 */: N' H% D+ _0 Z) \. L) _5 Z0 J
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);9 P" E7 v- e$ d1 k# g5 {9 C
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    8 r: i( E% ~4 M- U8 v5 ]
  80.     {
    5 C( j, z" O5 {8 c2 {# |5 B
  81.       /* 清除所有静态标志 */
      J2 V! Q0 O9 Y8 M
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);* g4 c* Z+ F" A- q
  83.       hsd->ErrorCode |= errorstate;$ c% Q" c, z. ~2 y8 g
  84.       hsd->State = HAL_SD_STATE_READY;
    % D& q' e4 |$ L' g
  85.       return HAL_ERROR;9 c, e1 z& l) m$ @' K! ^% k
  86.     }8 V% @6 ^$ z. M5 D$ o  _  C
  87. 7 F8 K8 [( C" s# r/ y9 R; x+ K
  88.     hsd->State = HAL_SD_STATE_READY;! [$ p  f7 n7 k8 u' y, p2 l  l" y

  89.   \2 v2 L* Q' h" u8 G
  90.     return HAL_OK;
    ' i) P% x9 `# k+ d, E
  91.   }5 ~( C* `7 [0 `6 u0 U- l
  92.   else
    ' Y0 o7 L/ `% I; l" e. z. a$ J; ^
  93.   {
    # A  V5 ]1 H0 y- _
  94.     return HAL_BUSY;& |+ |. w- e8 V3 X# F/ P9 `
  95.   }: K0 l: r; G# N; ~8 c  g
  96. }
复制代码
$ `; T; N1 i( q2 R) ~
函数描述:
: c. ]0 x! e3 j/ h3 ~; o
" M& s9 |. F/ @# J  l; K; x" u# R此函数主要用于SD卡擦除。& R% ]: F  t  |4 X7 P1 J7 n& X" y6 {" c
8 I6 r. O- t# E' j0 F4 g! K1 S0 f
函数参数:7 C( u& C* \, e

4 _$ S* R; ]$ [- G! t  第1个参数是SD_HandleTypeDef类型结构体指针变量。
' d# s. L0 F& p+ n6 M: `) B& |& f4 o  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
  N) o, w/ a& l/ Q- d+ \2 O6 L* m  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。3 [+ ?. l, X3 N7 A3 s4 o$ J
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。- O+ a5 o$ k; K5 Z( ?, W: P
使用举例:. O% @& Y1 N) m+ o4 u% `
7 g1 e, L' |" H2 J
  1. /**
    3 [1 t- O& Q3 Y
  2. * @brief  Erases the specified memory area of the given SD card.
    ; ?) e' [% l& j0 n; \
  3. * @param  StartAddr: Start byte address) O+ i  F5 c! [  s5 H
  4. * @param  EndAddr: End byte address
    4 ?( ^3 ^9 c& L( o( {9 K5 G) [+ S, K  K
  5. * @retval SD status* n! G' F+ x7 F1 i+ G3 J  u" ?
  6. */
    * T  \3 {4 A! P6 ~3 R
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
    2 ~- v$ \! r4 x' O4 m1 f
  8. {
    # `8 Y. v3 p4 \( I5 }

  9. 0 n9 |! F: F% c) n+ e# i+ s: l
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    ; Z) I  b9 ~6 K2 l, r0 z& o) p; K( u
  11.   {
    / _% k! [7 F: C% T
  12.     return MSD_OK;
    ( ?$ Q9 s9 s2 o) `; `
  13.   }
    3 h3 k& H  N* ^8 V
  14.   else
    3 H- M5 Q8 i, y2 B& i' j
  15.   {6 ~% y7 H% G% f6 A$ e- H- N+ R
  16.     return MSD_ERROR;: C& u9 ?& U& y, P, L
  17.   }
    , U+ w: W, B- g) |; R
  18. }
复制代码
7 I9 g# W; c3 q6 ~+ X
87.5 总结) y. H6 r; n9 \/ {$ U8 u5 o- R
本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。
; I' H4 X/ i0 N- Z* ]- j9 I* p( C! s! X, u
8 v( ?4 ]; z5 j8 G

$ P+ d9 ^) J+ Y+ u: v! n! L! L  g: ~( b
$ |; l6 X/ k# {) w9 ?1 O
  l  Q( S/ i% ?
9 e# A% O! f" r, p; C
收藏 评论0 发布时间:2021-12-26 16:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版