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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示# r2 K- l( U. J. }& {
  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
" F6 [& o3 F8 n  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。8 s4 c5 O" P" Y; B8 Y+ {7 z; U) [
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。8 K5 R- c# D  c0 q/ T
  SDMMC驱动SD卡支持1线和4线模式。  I% R  T0 u/ A) w, H2 b0 Z) J
  STM32H7的SDMMC也支持eMMC:
8 L! \1 S% L8 y; S! K) Q. Q  : j* o2 E( _1 w6 T% Y
87.2 SDMMC总线基础知识# k  j5 J2 X, n* O! I
87.2.1 SDMMC总线的硬件框图
5 q' ^& T. B$ l4 V认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
. ~1 _$ Y6 o& E3 l1 Z: n+ |; Z8 L' u2 I
6eea62abe623396815a50adc87205b83.png

# N7 H( q4 w, J, C2 f& R" I$ C
1 H% S% R) c1 }0 q# a通过这个框图,我们可以得到如下信息:4 b/ R# \* ?' z6 K6 V! y) U6 _
( q3 Q1 H1 x1 Z5 ~- l
sdmmc_ker_ck输入( _' j2 ^- E# R7 q/ z. s$ w2 o3 ^
SDMMC内核时钟。
0 D, B6 T7 q# e, C5 @5 ~
. m9 y8 f* C* N3 J: K# ~  sdmmc_hclk输入
6 d- Q( o# o8 E) IAHB时钟。
+ L7 n/ x0 a0 K; M: h: q" F) M% E$ B+ W3 m7 z" Y1 [
  sdmmc_it输出6 m' W+ T2 h5 c4 a2 J5 A
SDMMC全局中断。
' ]" o4 S- w) B, M' `% K  a# ^1 u( D0 i
$ o/ M0 ?4 a7 M3 a) H+ Z  sdmmc_dataend_trg输出
) y+ E8 e1 J$ w- M7 A& E0 UMDMA的SDMMC数据接收触发信号。
6 a4 e' {% ]% \; g1 m* X' W8 T
" l! \8 T+ b6 ~9 ^  SDMMC_CMD9 m5 z7 h. Y9 F' O3 C
SD/SDIO/MMC卡双向/响应信号。" @3 A3 u. o) X) {6 S9 l

1 W- [5 h9 v$ p8 K  SDMMC_D[7:0]
6 a: u: D0 E, O/ LSD/SDIO/MMC卡双向数据线。
# \5 @8 ~- n% q& Z) Q' d6 X4 @$ ]: S2 I8 N/ C
  SDMMC_CKIN
" V+ @5 A5 t: K' J$ l7 j来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。& V1 V& E( D8 j! ^" |3 P! P+ F$ b

' X) g& o$ a( J  `- c9 ^/ N; V  SDMMC_CK
& K' j+ r- W5 J+ gSD/SDIO/MMC卡的时钟。
# `2 ]. W, _4 ]
2 V1 G+ _3 G# Z) T# `( V/ B8 l! w) L  SDMMC_CDIR& ^& @; H8 b4 Z
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。9 q5 g2 V5 w8 S/ {. l# x, R
& v3 W& D& R2 Z+ V" ^2 X
  SDMMC_D123DIR8 G3 E5 T$ k. q$ e% C6 _+ L9 Y
SDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
8 c/ c; C3 r8 L: z: y3 m
( Y: v0 f# j8 |1 q  SDMMC_D0DIR: ]" y8 e/ d/ d: ?/ L! Z9 S* L
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
! C6 P/ ^7 j$ u( m4 Y5 P2 Z9 U& _* _/ m, X( _
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。; `4 n7 B/ r4 `( Z0 {/ b

0 x1 b+ D* H! w5 c87.2.2 SDMMC时钟
* k( a+ d# _' R8 b  r/ QSDMMC控制器的时钟来源:' h( G' H. x: u4 T1 g# `1 i) @# |

& @& o  u& l1 G8 V  c
676ec31792fcb80bee640ed979d48084.png
, ]+ r! X; o6 J: m4 h
2 k& K8 D) U% y, H; J5 n# f
SDMMC1和SDMMC2时钟源是一样的:, O0 p; W. R! j( K( c

. b2 s: C% B& E5 G
79b1c69986d1ee5bc090bf1676f396fd.png

) y# G; N6 P: H: F/ F  [) n: {% z2 l  b; @# d
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别3 I5 a* F/ x& a' S6 [: M, a" Z
注:大家应用时要特别注意这个问题。% L" ^2 d, I: b# N) V

+ D5 P+ ^# C; m' S; K; X' g& h使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的' P2 h) E0 Z/ e  k7 g

6 I9 ]: c' H5 {! S5 W6 k
6a5491d2f4a8740d838af58d034b7597.png

# E/ K3 q# f6 G1 d' r$ a5 [
) h6 @# D- v/ S0 U87.2.4 SDMMC支持的速度
( z9 c# ~9 D0 g0 ~% l4 ?- |3 f. c驱动SD卡支持的最大总线速度:8 }+ z9 n% v; [" F
. X5 }( \. D1 ^- `. o0 ]
b70ce31107b38ea820dbc28c3caec38e.png
8 C& a0 ?) d, o: t) D2 C5 y
  f" q& p- e& x3 L+ H; m
驱动eMMC支持的最大总线速度:( `; I( ?! n2 Q: i+ o

# ^8 s6 Y3 u+ e. t. |9 P
843bf7a054944ba7d5d137ca84e1d4ed.png

$ v3 {0 L: a, {2 z2 j
1 \0 J$ {5 c$ \. X6 c关于这两个数据表,注意以下几点:
2 }& m' [( y0 `, P4 w# ^) ^
* {6 j% n( G! Y3 _  i3 x3 I& ?8 N  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
# Y  ~* ^# @$ c- o  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。6 B4 G$ `: j3 Q: b# e
  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
  ]4 U- E% v1 u3 ]( M87.2.5 SDMMC支持UHS-I模式
+ P0 @: U& {( m1 e* QSTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:' O) t1 o7 @9 `  D4 ?, @

: `) `/ V9 h  m
2b8e4430b8a60dc5a1b342d7c7f75f52.png
) A4 y* j7 h$ J1 ?; A& P
$ v  V0 Q! }5 i3 f6 k: V& x
85f975745619c9afc64f8889289dad58.png
3 j7 R, D2 a" e' p0 m$ m6 t
0 {0 v% M/ D! Y
87.2.6 SDMMC自带的DMA控制器IDMA% l8 Z$ |0 @$ n# [1 a* e3 Y
STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。; r& V' k' \8 F1 Q, ~+ K; r
& Z& Z( P: c9 a( L5 W
87.3 SDMMC总线的HAL库用法
' m( c- u/ K; N+ e0 b4 X) E2 t' S87.3.1 SDMMC总线结构体SD_TypeDef6 F. H! F8 ]# y
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
8 U. |- T2 G9 [! F5 X, [: u. n" }& P# f# \$ U# r, ?( h7 z
  1. #define SD_TypeDef          SDMMC_TypeDef
    . M% k: L5 K" u2 W* d( X( D- p# y3 \
  2. typedef struct
    / A6 w& E8 o  R  N- E. P! a, N
  3. {
    1 Y4 k1 Y7 d8 s. S
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    , T( r9 f" F  Y0 n4 Y  [8 X% z3 @: ^
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */, g' k6 b% f" s  ?
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */& i! b- f8 O( W% `' [* c9 [
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    ( R& Q, d7 T0 C8 i# {# E
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    * i' o1 h7 n, H* m( e; s
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */
    6 J( K+ X' c; a+ Y; _) e. O
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */3 `0 a2 m: q" I6 Z2 O/ o
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  *// Z1 B* i- h$ L' E* |
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */! B2 k+ [, U5 {# t+ U
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
    1 F2 Y+ Q) |+ k: D4 Y3 Q
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */
    . L% A: `* z) `6 E6 S. N; K; @
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    9 R  k( d0 P6 y
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
      L9 F" `) ^- E5 Z0 [2 z
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */4 K; ?. c% h! u* i
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    ! z' G3 ~; m  F# b5 |3 ~/ T% ~, M% @
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */* o) F( A/ b! m8 o6 h+ Z
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    ) Q# ^1 J* E/ c0 L) [  f# R" U$ d  l3 G
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */
      N+ h+ P% w& H* }3 \& Y) F+ ~& a
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    : I) `" `7 M- X, I& s$ k: e
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */3 W3 Y3 r/ B( R- S# M& N
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */1 i( z* e2 U% U" \6 a$ m
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */* K8 \& c' O* I8 A- W
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    4 X; y" y. ^. {
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */# u1 y+ Y  N' A
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */0 Q1 s- J3 V8 T6 E' R2 a3 C; ]9 a
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */  G. N; S% P" J8 l8 G+ q
  30. } SDMMC_TypeDef;
复制代码
- \9 i5 o' _. A$ v
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。  K0 n' s4 ^; `# U: @
( y- X5 v% x- c3 f% @
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
9 S2 J4 `8 F0 X" h6 N
" g5 N3 A$ ~/ w3 M) ~
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    9 F0 \1 l- i- q! P0 m4 z
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

$ z# ]# b  ?- w下面我们看下SDMMC的定义,在stm32h743xx.h文件。
3 a) ?5 S( S; w. @+ x2 C* T& \- s: |6 P% p
  1. #define PERIPH_BASE           (0x40000000UL)
    & H! Y% w8 T+ O2 ?
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    # |4 J3 T* w( L& ]* b1 L- n
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)
    2 y9 @; k* z7 H# y3 L' T1 A1 P

  4. ) z# K, ^0 k6 I5 w
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)2 h2 b; V% Q; N' [
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    3 M% y) W. A: ]4 f: b+ E
  7.   q" W; H+ X3 x2 F3 u& r
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)2 ~2 F4 n+ J, p5 B# y
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

- e0 t4 u$ O: v9 R1 |) F我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。, P1 x, e# j: c

( s! c0 R0 k" E# j: P7 q87.3.2 SDMMC总线初始化结构体SD_InitTypeDef6 }3 y1 L0 W- d4 h" A) f: h0 O
下面是SDMMC总线的初始化结构体:
9 j/ B& Y5 @  S9 c6 b0 c' y* L/ c9 {3 ?; A$ i
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    # W9 B8 e# P  _" P
  2. typedef struct# f: {" d" _7 B7 \/ {$ X% K$ d
  3. {
    + z5 B  P% @8 q  _2 o
  4.   uint32_t ClockEdge;            " N$ _6 f2 }2 b. P
  5.   uint32_t ClockPowerSave;      $ Z' g( I; e1 k3 Y4 e- A* _5 v
  6.   uint32_t BusWide;             2 Q6 G- W) O, b- s1 }4 Y5 z- K
  7.   uint32_t HardwareFlowControl;  
    + z$ s* h2 b4 b$ v. F
  8.   uint32_t ClockDiv;            
    5 J; C9 x/ |4 X' j! G3 K8 m
  9. #if (USE_SD_TRANSCEIVER != 0U)& [+ a4 E: F$ r+ r. _! v; r. c& V) x
  10.   uint32_t TranceiverPresent;    * \& `  ]# x8 h5 u5 I/ W( ~$ X4 ?
  11. #endif
    * _% B' P/ U( `3 O% m
  12. }SDMMC_InitTypeDef;
复制代码

  a3 Z) q; g9 h2 M下面将结构体成员逐一做个说明:
7 c. R; m& u' X$ k( W& Q
: h5 @) m" C% S, {4 D  ClockEdge
  L/ M! U8 h, ?: D' e% D( A0 u/ @用于设置SDMMC的数据或者命令变化的时钟沿。. S$ M* E' o; _+ V/ p7 _$ x7 j
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    % \' l1 |# |- }5 Y- @- }- o- ?
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

/ |8 N$ s& V) {4 r  ClockPowerSave
" O# N/ p" t3 U0 }6 S& J8 }# n3 l: @用于设置空闲状态,是否输出时钟。
! E$ U5 r  P2 A8 j* D: \4 P$ z
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)3 u8 D6 T! w; d( I( E8 q
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
5 ^+ T! s) C3 B2 V( ~" k
  BusWide
* `1 M1 J9 E: j" Z+ Z用于设置SDMMC总线位宽。4 J, E) ~7 B* r9 K  T) ~+ [: @1 q5 K
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    , c9 [: M0 z  |9 ^
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0$ @' ~: u/ N" Y
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

. t! C) R3 _' B6 ?  U0 n9 R  HardwareFlowControl* S- Z( r: N6 ^7 G3 x; ^$ m/ u% U% I0 N
用于设置时候使能硬件流控制。& t: X3 B" T' p6 P4 T* d1 W' T
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)% E. @6 P4 S$ l) r! O/ i
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码
+ V1 T7 `1 j2 I# z5 e: ~. |3 z7 w
  ClockDiv$ N# s  `9 Q9 r4 R# |8 }
用于设置SDMMC时钟分频,参数范围0到1023。
2 N9 H  N( d" S& a* j& K% R* p* E7 T8 ^: N
  TranceiverPresent
( j0 M- b2 e) h& h& ?1 N5 a$ g用于设置是否带1.8V收发器。/ d7 F4 S' \& M0 u: P" _7 R* u
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    & H2 s* ?( v9 P+ x9 }  z
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)" ]2 x' O9 _$ ~: b
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
: i% p6 Y$ Q6 F. U( j0 A5 h' A
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
6 N% n( a" N- z: N8 X& _* s% K下面是SDMMC总线的卡信息结构体:
7 W4 h2 B9 r4 C
  1. typedef struct
    6 y5 v4 G/ k" d% i0 @
  2. {5 t2 N# w2 K+ g! {+ ^- a6 V
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
      L/ @1 U' v  i
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */6 o8 E8 u) ~/ v6 }7 D# H3 h* f
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    2 a3 H. F" a3 {
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    % F' s' ]) p7 }. I
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */9 {5 ^# q0 A; I5 c
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    ' b9 T' K) V0 j2 h* ?" N
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    $ J1 C) j; b) i- H
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    3 Y; a: s& P+ ^" F( r
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */
    5 F6 c. C- L/ e  Z
  12. }HAL_SD_CardInfoTypeDef;
复制代码
. o( j+ j( E2 C+ q% k
下面将结构体成员逐一做个说明:
8 k; x! m$ M0 E- u* k! V' k% j8 l& P! e. ~% y9 v
CardType6 q& f2 E0 k. H5 {
卡类型。
  U! Z9 a8 l" K2 _
  1. /*!< SD Standard Capacity <2Go                        */+ m) t* |7 E; R5 Z
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U)
    / F3 q! C. c8 |4 }/ c" `+ u
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    $ ]6 p  [1 _" U" }% W( f7 e; Q
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  2 }- l  g' A4 s8 ], {
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码
& j# g# N5 e  p" M% Q& \
  CardVersion2 M& D% G4 e5 D3 b% g3 D) r1 n, g8 P
卡版本。0 h. X) Q% X( d: N5 p. \
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    ! a/ r# D* \1 f/ W) G
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

" S! H1 d* U* F& A  Class/ W3 ^9 a6 L; _9 e% k  K
卡类型。# @6 I* \, Z* h( |5 S
, z/ U' F' S0 {5 c4 g: r0 D! a) Q
  RelCardAdd! {1 [* V3 Y7 }
卡相对地址。
" _7 h. v" O# [5 U
( M  O6 G# t: t  BlockNbr
0 ~9 T  y" |  h  G( ?, L整个卡的块数。' p( F  o; f: j" c- [; C* c" w5 n: V
, J5 J) {) p" k
  BlockSize
/ R0 P9 N. e6 J4 Y0 {3 i) T每个块的字节数。  V5 n. z' h1 i. a" a4 u) w0 u. Z) J

3 e: M- v, u' o3 S/ \* U+ I7 d- O  LogBlockNbr
* C6 t' c0 h5 {, r9 Y" T整个卡的逻辑块数。
: c: _8 ?, I, m. D, ]) W
3 ?4 P  f, s' F4 v0 `  LogBlockSize8 p4 Q0 J. U0 b% Q8 ~* _
逻辑块大小
' v9 B  M" T8 M, M/ c
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)! j) c' S, Y4 _5 J3 a8 a
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码

! F% @0 E5 Y! |0 O6 T- I CardSpeed8 }& n8 S" R1 x( }0 m2 q
用于设置是否使能SPI总线的TI模式。
8 T& r+ q5 r4 p/ i; e; u6 z1 L
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */  E2 f( ~9 j5 n8 X8 M9 b
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  * o; {' q6 @0 D  e5 z" O6 r; P7 l

  3. 6 U- F- V) t' y& F3 b$ i2 ?
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */ 9 P7 X4 V* s4 w/ U& O* E# c
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    7 @/ X  A: `* W+ }$ W
  6. 0 H! R& c3 v: D7 L" k, V# C" A; l
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards
    # m) ~2 {& \& n3 B
  8.      and <104Mo/s for SDR104, Spec version 3.01        */3 [% M9 M8 d# s- `1 w( j% I
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码
0 V! n8 E; y3 L  \! W! v
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef4 P" H1 h. V0 F' Z. x' V" B- E
下面是SDMMC句柄结构体:
7 W" v$ S) w1 Y6 M7 c( t4 g+ z& P7 t
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)8 [, y5 A% Y; f  J
  2. typedef struct __SD_HandleTypeDef; g( u( M! s& j$ @4 `2 i% t+ n% h( N
  3. #else4 c# h5 r" ~. n7 h! i( A
  4. typedef struct
    + x0 W6 O7 Q2 @. v" m
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    9 \6 t, T) `3 `5 Z: d$ @6 |
  6. {. G" r' y( ^$ X' x$ V/ }
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */; N8 }3 j1 Q: M3 F2 w  d
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */1 P9 @3 t6 A- P, \
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */
    6 ]' h5 s7 h+ H0 l5 x1 s8 ?
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */  \3 d( ?- W) H9 ~& [$ g
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */3 c$ K9 F2 k& _% I
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    8 q0 f7 @/ W4 p, h5 I0 v
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    # L5 p8 C' X. j& J
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 *// p  e' {* L4 n6 f
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */1 Q5 f2 c' `( Q: `, u" r
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    8 q9 i1 Q. l/ l' r* G! j# _, ]8 d' p5 \
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */
    7 Y% D$ C1 ~! e  r& L# y
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */  R2 B4 \- P- Z/ p% V
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */( g) m# W, i8 g
  20. ! y3 W* X3 Y& z7 g! }3 [" [
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    - O0 U3 S& z5 D9 K  i) l
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    $ v( r, Q2 L2 Q
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);) a% l% y  @7 ?% ?  Y0 f
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);; L' M, m3 i' @
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);
    $ r& b. T( b( c
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);5 Y. P9 n5 T. J: {5 D4 m5 p
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    3 n0 n% o* m8 p! U5 E
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);+ g  {+ w* W7 \8 f- x
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);/ ^- n5 G) p" G; K. O3 x" r
  30. #if (USE_SD_TRANSCEIVER != 0U)+ c( A; j# }/ T! e3 ]$ ?
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);  P' N1 D2 F9 L6 h: ]
  32. #endif /* USE_SD_TRANSCEIVER */
    : c1 U% h7 f& W

  33. : b( Q/ K4 E, \6 |
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);5 \0 t. i) u$ ~7 N* H) v8 s9 Z
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    + l; P/ O0 p# m
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    1 E" f4 y% y1 ^5 K' z
  37. }SD_HandleTypeDef;
复制代码
( A5 q, I4 v0 O, q; H5 |
注意事项:
) y# V7 G( V5 v9 z. ]  X3 r* h5 \
2 V0 B1 I: p* e/ t条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:0 Y2 J* ^. A/ p  d- T
* @7 h, _* G' ]9 b& ?3 R
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
- `: Q/ R: C: d6 ]: Q% y
" Y1 U0 x) M+ ^0 s6 k通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
1 U/ B" l) Y3 W* X$ k& |- S! A( b8 T! S# ]. p0 ^1 a
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。' s7 N- d7 t' i, E$ W1 P. M  q( C+ w

4 _3 X* [) _! C  SD_TypeDef   *Instance9 C4 s# |, [( o/ P8 [0 B2 j
这个参数是寄存器的例化,方便操作寄存器。7 Z: e; U# h, Q5 U! f
3 P1 T- k' k/ Y' `+ B1 T
  SD_InitTypeDef  Init" \- C: \+ f# v1 F0 G
这个参数在本章节3.2小节已经进行了详细说明。; C2 j/ z9 y$ F' P5 k1 U+ @
/ L9 X( F3 W% d
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c) M  n0 s& o0 o" ?# A+ q$ u- W3 K
此文件涉及到的函数较多,这里把几个常用的函数做个说明:" Z3 {0 b7 |2 j& \

1 |2 s4 w1 A6 U  HAL_SD_Init
+ C% I  y6 ]  r% x4 ]6 t, s+ E7 F. S  HAL_SD_DeInit* T  u# N+ A4 `; x" {1 X) Q4 l
  HAL_SD_ReadBlocks
. [" @, a! ?1 m2 Y2 d  HAL_SD_WriteBlocks
5 a. X5 [# I0 v$ T  HAL_SD_ReadBlocks_DMA
+ d" W4 X6 A: M1 j  HAL_SD_WriteBlocks_DMA6 O% L: _! ?9 z4 C
  HAL_SD_Erase# M- K* R6 D# _
87.4.1 函数HAL_SD_Init, s0 P( i% R& m. }9 p
函数原型:
1 t0 |  }$ _5 {& E, L- s7 {
6 R1 \9 U9 N2 @3 r$ h8 n" K7 l
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    % O0 d- I8 _4 r/ y2 }! ^
  2. {
      |& B! ^' n. `8 k
  3.   HAL_SD_CardStatusTypeDef CardStatus;
    ' L2 [( [4 e) m* v6 ~+ y. }
  4.   uint32_t speedgrade, unitsize;
    8 Y# n( @$ J" j$ J
  5.   uint32_t tickstart;
    . T* d" i' Q7 o2 r) w
  6. ! m8 \( G; a$ M% d7 w% w- K" l
  7.   /* 检查句柄是否有效 */9 C* a$ X! @% j$ R5 t$ ~
  8.   if(hsd == NULL)
    * n% ~. y9 Y: J/ D0 [
  9.   {
    8 g$ h. v# d5 n
  10.     return HAL_ERROR;
    ! Q% W% P0 o0 a9 u( a2 O0 J4 F0 l
  11.   }/ `8 [- T+ W3 c! r+ S8 j: K

  12. $ L3 \( _( r; c) w6 F2 t1 W
  13.   /* 检查参数 */
    4 R$ Z8 K1 N( g. V+ x4 ~
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    $ \$ H( c4 a3 ]( G4 [  k
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));0 B  i; T8 ]% C! C+ \, s. D
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));/ D) K( `* w% i3 t
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    1 G: @. d3 Q  Q9 D# z5 L1 L& K) Q
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
    3 H% q& _7 N8 I- v6 ^; b
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    9 A+ R" P: s0 D# e7 T6 L
  20. / @; G. r2 K: w% y% a
  21.   if(hsd->State == HAL_SD_STATE_RESET)' I! u( o8 Z" j  r$ B
  22.   {7 k7 L- ?' @/ m- A# `
  23.     /* 开锁 */5 K/ d8 n: N7 _6 k. B
  24.     hsd->Lock = HAL_UNLOCKED;, e3 M: u0 b0 f% g

  25. $ u# f" y. }, W: x6 I
  26. #if (USE_SD_TRANSCEIVER != 0U)0 f8 ?' ?  t) {  N% w: i2 N6 I
  27.     /* 兼容 */
    # |& E1 D, S0 }, F
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
    , [1 M6 h: Q. D5 k
  29.     {
    2 I6 Z( b+ Y( ^& A: E# Y
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;% s- r3 S5 [- v" @, f- p# u% [5 M
  31.     }
    : D8 G  W  Q0 x# ?
  32. #endif$ l& z% l; O( w  E0 U
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    : u& S2 F' y+ N, N+ |4 ]
  34.     /* 复位回调 */9 O. ^8 `  w( N% |
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    $ H. U: Y/ ~+ Y; M. Y! F$ `+ L+ `
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;. W- a5 P  N- E) A" e. g  Q( s
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;
    ' j( D9 g/ l7 P0 i
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    5 h! u  {* N) p) X, u/ E; H" o4 Z, E
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    : @; `1 |/ i! ]
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;! W7 ?1 }+ q; m
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    ' B- t$ w9 z+ i, g/ H
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;/ l; p4 q7 `9 `" z& Q
  43. #if (USE_SD_TRANSCEIVER != 0U)+ B; O3 R# Z7 a! Q) h/ g( _
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)# o* @% T' U3 X/ V6 U8 \( P- f; t
  45.     {2 Y. h+ {7 i: z+ A$ S. y
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;: b0 d' G( h0 p2 I% L: v  C' l' }
  47.     }
    ) W+ ?" `0 P' h& c8 D1 Z  G
  48. #endif
    ( b6 X: `3 W1 z1 N0 i$ w
  49. , \5 V$ A, F% o- _  ^' t
  50.     if(hsd->MspInitCallback == NULL)
    # r- K+ ^, r8 C+ ~7 Y" `
  51.     {# \2 R! y: E, j! B: R
  52.       hsd->MspInitCallback = HAL_SD_MspInit;6 D5 Y# r, H- c) `# F
  53.     }
    . \! C% l" F- ]2 v2 |2 K

  54. ) o$ z; Y$ k1 j4 B  J+ h- `) P
  55.     /* 初始化底层 */
    $ j1 |) ?5 z, F; ~7 k5 l; `$ C
  56.     hsd->MspInitCallback(hsd);
    , I3 b4 a  h# O+ A7 V
  57. #else
    % @3 A9 A0 Z+ f9 q$ B
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    * v# X: C% N* |7 |9 W5 Q. `
  59.     HAL_SD_MspInit(hsd);
    # V2 l8 n- ~& W+ _9 ]! K; U
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    4 l' j- Q! |4 h( s$ j7 n
  61.   }
    . X' \9 Y* |* e, c" ~
  62.   @1 w' R+ D4 m; w4 W# i
  63.   hsd->State = HAL_SD_STATE_BUSY;* a4 }/ G* H0 q, m

  64.   O3 Z0 w# W- L2 W8 p) a- \
  65.   /* 初始化卡参数 */
    : V& \) w! @+ y' {# n9 A
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    ' v" ^4 m, @; n# d6 g( Q# b
  67.   {
    1 P( g  h; R2 Y
  68.     return HAL_ERROR;
      b5 v7 R) q1 V7 m* g
  69.   }. ^8 e" ^% ^# \6 g  _
  70.   S& ]+ g" P4 q! R! |! B
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)* Z- r' E$ ]6 t" S
  72.   {
    , m3 @6 k+ B# O( V1 d+ [* S
  73.     return HAL_ERROR;
    ) V6 e' u1 n" `/ O5 c
  74.   }  o( `4 w5 {# z  f" H# ]
  75.   /* 获取卡速度等信息 */
    % D  L) t3 C) s# f, f2 x. p
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    " s3 z$ a3 d; r) t
  77.   unitsize = CardStatus.UhsAllocationUnitSize;  j; h, K# g; N2 d9 t: ]) ~9 z
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    ; z4 ~: C' @, ?
  79.   {' a8 O3 g8 w2 B$ w& T4 w* l
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;. ~8 E# e' @% a( y, T% N
  81.   }# J" I1 M/ K. ?2 `5 P1 O+ V, C7 j
  82.   else* a* @& Q7 o* o) U3 S
  83.   {
    + R5 p3 [) s7 A
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
    4 q- @. \' Q2 Y/ D  B& o, |
  85.     {( j8 \& s7 K5 w5 H( d( i
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;; ~; @0 h! L  L) I/ m4 g
  87.     }
    ( q# r/ _/ i5 m) j; J6 g, l
  88.     else2 M. T& A, Q& K: z
  89.     {* Q" M' {& H8 H* {3 W7 k: e
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;
    ' o7 u3 \5 U/ r; q
  91.     }
    6 W0 M: `8 J1 k, e& C

  92. / v' R! Y* X4 R" T! r' |1 C  A" Q
  93.   }, g' H6 O/ N- ^: [0 X0 O% N, D' M4 C
  94.   /* 配置总线位宽 */1 y* O& H* ]" z  |, p7 o: C
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    % k+ F1 S) J$ M: r4 u& e
  96.   {5 f: V, I! ?7 L6 j; o' f* V1 H
  97.     return HAL_ERROR;
    + a% z; {8 `! O' S
  98.   }2 l, k4 B" g; ]* M+ |/ }& \

  99. 0 o, N5 ]0 D# [! A" |2 @
  100.   /* 验证卡初始化后是否就绪 */
    % n4 a; W: U, Z: z4 k" _
  101.   tickstart = HAL_GetTick();& M( n. ~1 s; w) F7 ~
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    : i/ L+ ?1 [9 w* i6 e( ?& X
  103.   {
    # t# @3 D) t, I& Q, V1 I. I
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    / b# k; B1 s* V, D
  105.     {
    ) V; p+ ^; h- f2 V/ @/ v( G6 {
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;& E5 }* q; F  Q- ]
  107.       hsd->State= HAL_SD_STATE_READY;
    7 o& s: z& y  u7 Q
  108.       return HAL_TIMEOUT;  i( p! m" N5 m2 |
  109.     }" f6 v9 d! |9 u3 x* \
  110.   }4 f# U9 D2 G- y' q- r

  111. ) a9 C- U9 T6 y( E) y3 C/ _2 E
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    3 ]" b6 L2 }! V

  113. 8 d/ V) L9 `3 T
  114.   hsd->Context = SD_CONTEXT_NONE;2 E2 e' {8 e3 P5 B1 ~: {

  115. 4 Z+ e3 V- h: i5 w  _
  116.   hsd->State = HAL_SD_STATE_READY;, F( D9 d1 V$ Q1 J* Y
  117. * y+ z1 F0 ?5 I* }+ j+ n
  118.   return HAL_OK;+ o" @  j6 C$ [
  119. }
复制代码

8 h6 v& b2 F9 k" }% L" u函数描述:  o7 d! a5 k9 C% }; W" e: F

5 `* Z, J3 g- \  j( B/ g( e, a此函数用于初始化SD卡。
6 x' W8 Q3 v6 C  H5 d0 u
( w; x/ \4 U; L. Y6 e# G& p( F函数参数:7 z8 ^0 s' R% D& J9 o3 n

. K6 b0 [# Y; O2 a& h  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
  L5 S3 q. H* m( w% A. ]- K  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
# b  x. s1 |+ m8 n注意事项:
4 z% R% {( @* z) z# U. s
/ Z% t& m) F! I3 s& e2 k3 G. |函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
$ ?8 [" m1 u& f: {3 n如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。* }' X1 x/ B! n$ E  ]$ }+ m5 q4 W
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。; m: ]9 Q' c7 H+ J& R+ t8 W% \
: Q. G7 |6 U6 m9 v
解决办法有三6 N6 y" z$ p/ \$ T. j4 Z
/ ?# Q& L: y; S7 h" L
方法1:用户自己初始化SD和涉及到的GPIO等。" f5 ^# @& o$ f8 k2 ~& w& p
- h7 ]3 p/ F% ~! @
方法2:定义SD_HandleTypeDef SdHandle为全局变量。! i6 s0 G2 J& W; s
& R1 }. A: K% D+ a, m: }; P
方法3:下面的方法
0 D; |9 Q) r& T9 B. C" p& P  A* L1 S8 p8 W
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)/ r" {0 t! F) m* S6 U. x5 F
  2. {3 g3 J8 M+ v4 u; Q! u1 b( g
  3.     Error_Handler();
      ~. B4 @; y# W! k
  4. }  / Q3 a( M: m+ ]/ I5 i4 M3 P0 C( A
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    " A6 {2 l9 G! h8 a, U0 F% N3 H
  6. {& s6 H! ^2 |6 [4 J, C) O, V* ]
  7.     Error_Handler();
    . q% R! y6 H5 w2 D$ ^' c
  8. }
复制代码
9 y2 W" q8 G2 \* w* C1 ~7 P9 z# z- c
使用举例:
8 y4 c/ t/ X# g  G  V6 G+ z% Q: W
  1. SD_HandleTypeDef uSdHandle;; J8 v* {/ [6 P) O
  2. 4 n3 M- O/ E1 j4 z
  3. uSdHandle.Instance = SDMMC1;
    , J" m7 l+ w) g7 H6 W9 G2 P
  4. " a/ S' h: t/ t1 I1 x/ I
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock9 {+ E9 c1 _% Q( w9 h' f
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].4 L: G: f; ~" n' g6 }7 Z
  7.      200MHz / (2*2) = 50MHz
    * ~; _' L" D2 m4 p! _: t3 u
  8. */
    % X% `  S  `& u4 l5 J* T
  9. uSdHandle.Init.ClockDiv            = 2;
    / x$ j( J6 I+ B
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;5 u6 J* t4 D' b' J, W1 b  y5 M
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;2 U6 F9 d( N! B, `6 c6 U
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
      I; k5 f( ?1 k. n' _1 Q4 p1 V
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;
    ( q" D/ j8 d( q8 x* U; n! V9 W
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    " \& A& ?3 t4 j: Z; M0 w( h
  15. {
    8 a) |7 ?* O+ ]* f: a6 j3 ^
  16.    sd_state = MSD_ERROR;# F# X, n- j! B( s5 x- Z
  17. }
复制代码

/ y$ N6 K0 P+ F: E' ]: t1 ?: i87.4.2 函数HAL_SD_DeInit2 J9 l, F' w$ u+ c/ n2 R$ X  ~
函数原型:
8 o5 h& u- }( F6 S1 B
, t  N! `' b6 @& X) N
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)4 I& m) @* O$ }" @1 a9 q
  2. {
    8 j9 k5 W+ W# f) k" F& b
  3.   /* 检查SD卡句柄是否有效 */1 g# `) {. h7 R) Q
  4.   if(hsd == NULL)
    2 g2 f! L% y- v* {
  5.   {
    ; R9 c/ p- ~# S
  6.     return HAL_ERROR;
    " I2 Z; z( E1 J$ w
  7.   }
    1 w+ |' q* a- X3 b

  8. ' r: B% ?5 r- V# i# m, E
  9.   /* 检查参数 */
    * W1 e8 `, t" E5 T) [
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    ; b  r  p; c9 O( s8 o
  11. 0 y8 }9 h2 C+ D; m" M1 d2 X& C
  12.   hsd->State = HAL_SD_STATE_BUSY;6 `: {" ?0 K0 }! L& ]

  13. ; w* j# n" o+ g+ }* A
  14. #if (USE_SD_TRANSCEIVER != 0U)& |& q7 r  e+ ]. @' @$ \) ?9 r
  15.   /* 关闭1.8V模式 */' t9 _3 G+ M5 X9 M1 o  p
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)' q3 J2 P3 b4 Y4 g+ a0 B+ E8 u
  17.   {- q8 x0 h6 j1 ]
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)( x, p2 Q! N- o1 w$ S
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)5 l7 f; p. E6 A# j
  20.     {
    4 Q7 r& ]2 ]# w/ D% v5 y1 ]
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    , g! d+ V# }: I; {- Y
  22.     }
    : h4 J/ `' D8 ^+ J+ S$ _: B
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);
    - C; E. Q) A( G
  24. #else
    5 C' H! A- S& x, H) Z1 _
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);2 m- c1 K, S# v+ L0 d0 N+ J
  26. #endif
    $ M" K* d5 [, u
  27.   }                                                                        
    4 w8 ~7 H& @9 g
  28. #endif
    * A' \! }5 x. g: N9 V: d

  29. 1 t1 d2 L1 f. _/ Y
  30.   /* 关闭SD卡电源 */
    , C! b2 c# w) ^8 u; [1 A
  31.   SD_PowerOFF(hsd);3 M1 M) i. s5 v2 f. r* j" n
  32. * f4 Z- e  f  T2 ~, U
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)  M! @' a: n8 E3 P
  34.   if(hsd->MspDeInitCallback == NULL)
    1 T+ W. r4 S) A0 f
  35.   {7 k3 i- ?) P5 ~" K2 F! F2 b
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;9 _! A8 x% Q( a* H" |  J) @
  37.   }
    # p( v$ [  s# Y6 b/ Y

  38. 9 E7 }. u6 F1 N- [, Z
  39.   /* 复位底层硬件 */
    ( |% W3 L5 Q9 [% L
  40.   hsd->MspDeInitCallback(hsd);5 x! F( ]9 O1 A' H
  41. #else8 V( B$ j6 ~) U' w, Y- W
  42.   /* 复位底层硬件 */
    : }2 b' Z) v6 J- @* Q2 S
  43.   HAL_SD_MspDeInit(hsd);% ]$ k( Z& `; W, P( D* L& |8 ]
  44. #endif   _  P. D- G! Y

  45. & M) A% q8 Z3 [% R( G3 q
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;& E" i. N. |0 ~+ |! M
  47.   hsd->State = HAL_SD_STATE_RESET;
    0 C* W6 \: j! }* f+ u- X; M1 d8 l
  48. 8 F' f5 a- O4 R; G& c" a: a/ x
  49.   return HAL_OK;. ]1 ^8 W% a1 p: t: s. z
  50. }
复制代码

% V( s. g9 i. n/ y1 C函数描述:
' n$ j8 a" _8 u+ }/ e4 K$ K5 k: L& C' y; \7 a  l
用于复位SD总线初始化。
, ]# A: s0 r+ S' z1 m- y$ o
, b5 i8 z7 _! q6 c$ p! s  j函数参数:
" h* q4 B- B% ?0 a/ j0 u7 o  {& \: R0 n) F$ L+ ~2 I0 q
第1个参数是SD_HandleTypeDef类型结构体指针变量。
" p4 P0 m" O# `: {4 O( k# e- Y. L 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。2 ~0 ]- l" W% Q& t# [; w
87.4.3 函数HAL_SD_ReadBlocks* ^" G2 O, t6 s0 P: A- e
函数原型:
" G( q3 C$ i5 T; E" P4 m! x' F3 b
: M8 V3 M4 r1 g0 d" N% r6 y5 b
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)% s; }6 G* x( {* A% m
  2. {: g6 A% a' z- h# U7 O% p* h# d
  3.   SDMMC_DataInitTypeDef config;/ S, o5 J% M: Y4 l' O! ]
  4.   uint32_t errorstate;; @+ t$ i8 M7 v
  5.   uint32_t tickstart = HAL_GetTick();( f! X! r, X. f2 l; |
  6.   uint32_t count, data, dataremaining;
      N9 z3 W( K5 N+ ]. H
  7.   uint32_t add = BlockAdd;" P, b) A+ I7 I! E% s; l
  8.   uint8_t *tempbuff = pData;( m0 |8 s& E( r- E" x- i
  9. $ Y8 Q. |. q  Y) h' |  N$ }
  10.   if(NULL == pData)
    ) O* \$ U3 d# R8 ~9 B
  11.   {
    ( a' R0 ]/ K" d* Y  }1 U" ~
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;2 V) q% H( C( W2 K9 m
  13.     return HAL_ERROR;2 G% }. j2 ~% Z% A9 P- N
  14.   }3 X! F& n% t" v' D" ~0 _

  15. ! S0 [7 I) M$ c/ y# ~' @
  16.   if(hsd->State == HAL_SD_STATE_READY)
    7 [4 f" [. V) G* x
  17.   {
    % m, Z; ~+ [' {* j# d* G& F3 m
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;) e% G  G+ b+ T0 W# |" L$ b7 q
  19. / o1 C& s7 x  ^+ E) V, j% ^( L3 T" i2 n8 P
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    " s2 M, q& ~1 R8 E, L7 k
  21.     {3 z; _& X& J0 n  Q4 I7 G3 |
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    0 F( ^3 }* K! Y- h
  23.       return HAL_ERROR;* J  }6 Z' P1 {) P/ g0 s; a: J8 ^
  24.     }( l" b, {: o* K% ~3 Y/ n/ J& d% L
  25. - s5 Z2 J" E- K# o$ c' f( c) x
  26.     hsd->State = HAL_SD_STATE_BUSY;
    " a% [4 M. _8 {7 m- u0 s6 X

  27. # d% i' M" Q# A- S) \! ]
  28.     /* 初始化数据控制寄存器 */" i( _! l- ]# ?! K+ {
  29.     hsd->Instance->DCTRL = 0U;. T0 M: V7 U3 c8 Y

  30. ( h8 N8 x, w+ O8 N9 Q
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    & c; d0 Q& [  D! Z# V
  32.     {
      |" f* M3 q$ L! o$ f$ }3 F9 k! k
  33.       add *= 512U;
    ) ^9 C6 m, B6 \" v" z& q, s
  34.     }
    , u" b4 y7 K' p+ }) ?6 o

  35. 3 ^% c. ^" m+ m% Q! o2 S: o5 R
  36.     /* 配置SD DPSM (Data Path State Machine) */
    * n. n1 V! @" }. v' K
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;4 ?  \, ]0 N% K; R
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;/ u+ p- K) Y+ l( m
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;1 O- ]) {7 e% w3 P0 f: S2 `; q
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;6 h9 S- N- p: u% a& W6 ~: ^
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    , S! \' g1 ^* L! I+ ?" Y, i
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    - `- }8 n+ @* b1 M+ E* s0 U
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
      q6 q  I$ l7 y
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);- T5 T- F; p9 S: ~' P

  45. 7 }4 z! C, J' N: x) S
  46.     /* 查询方式块读取 */2 r- \  H8 b1 f5 X4 i$ A6 @
  47.     if(NumberOfBlocks > 1U)0 P6 l  g5 ?6 M3 F
  48.     {' x; H" K4 g! F' z& @6 L
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
    4 ^+ ?: |) F% R1 n3 n- w% c3 n/ x

  50. - t4 x' [* c+ W' p$ _" a$ @! H
  51.       /* 多块读取命令 */4 x$ w3 l3 Q7 Y. o0 K) }
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);5 v. B) v+ E( q5 D
  53.     }
    / x; a" |- E1 l$ H- V* ^" w
  54.     else- i; k9 ~4 W: W6 }
  55.     {, |5 l% G! y, l; }
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
    & h3 D. D' r2 N) Z4 {, ]$ N

  57. 8 @' ~! g( a+ ~& o. g; a
  58.       /* 单块读取命令 */
    + h5 [, t% b( y7 p2 j
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);, o% ]! o5 s9 x' m2 A
  60.     }
    7 \! p/ c6 b8 c. E! t$ e0 A! t' G
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    ( @5 [! M3 o3 o3 O3 b% Z
  62.     {8 Z: z6 B1 r: @- d
  63.       /* 清除所有静态标志 */+ O2 ?8 ^" F8 e  y2 D  z9 J
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);1 U3 X% Z0 K& S( k) Z4 |7 l! P
  65.       hsd->ErrorCode |= errorstate;
    ! _: @) O9 P) e  a6 c1 U- J
  66.       hsd->State = HAL_SD_STATE_READY;! _0 v* ]  J& Q
  67.       hsd->Context = SD_CONTEXT_NONE;9 |  ?$ s7 @% P5 @! u
  68.       return HAL_ERROR;7 H7 `9 ~) }. n& q) p6 q% V* A
  69.     }8 @9 S7 d/ t! I
  70. # D- m) e/ N  t9 K$ q
  71.     /* 查询SDMMC标志 */
    ; V4 f9 r6 v5 n' Z; o7 L. G
  72.     dataremaining = config.DataLength;% k2 X* s* y# |
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
      ]" n0 m# @" Y  a
  74.     {2 ?, n3 Y% i0 g0 \8 T$ n' p# p1 k( c
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    , Y: i2 P# y; [4 c/ D
  76.       {
    3 Y4 X7 V$ `8 a9 g$ P
  77.         /* 从SDMMC Rx FIFO读取数据 */* j) n* T7 V: i" w
  78.         for(count = 0U; count < 8U; count++)7 r  I- f" `. f6 Q
  79.         {
    ) T, H7 L9 U/ k" {
  80.           data = SDMMC_ReadFIFO(hsd->Instance);  u2 J7 I' m; E, R" Y1 t: f3 o. _8 J
  81.           *tempbuff = (uint8_t)(data & 0xFFU);
    1 B$ |' s- G7 L$ B4 r
  82.           tempbuff++;2 O/ }$ S! C: ?3 U( N# [
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);) H  m0 A) U- x5 o) @5 V: o
  84.           tempbuff++;9 O% D- E- r1 D" d, g& k
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    : \) c/ u) s: O7 O  O; N
  86.           tempbuff++;* g2 X  Q3 q$ ]+ H; V. R
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);' \7 l, F0 v) U5 h0 n; l% E7 x* C8 l
  88.           tempbuff++;
    % l" x4 i" d, }
  89.         }7 C; ?% _9 S2 `1 _2 C$ I$ R
  90.         dataremaining -= 32U;' N- F& a2 V) U0 J
  91.       }
    4 o) b  `$ |  a0 O# p# ]

  92. 2 K+ O, S: q: [" n* |
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U)); \  c* F0 Z* r) e1 q# w& P# R; P
  94.       {7 \6 U( t& }* c% L' _
  95.         /* 清除所有静态标志 */
    2 |! V" L0 T& o3 {% X
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    % z4 T6 \9 r% k8 _7 a5 y& X: {
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;, C, o3 p. }& g" u  {% [4 T* A
  98.         hsd->State= HAL_SD_STATE_READY;) w; O$ r  ?) ]/ M& |% K( V
  99.         hsd->Context = SD_CONTEXT_NONE;: }1 {% Q2 F6 V5 E4 d, B
  100.         return HAL_TIMEOUT;) b$ C* Y8 `# K" G- S4 _- Y: j/ {
  101.       }. C5 w7 I4 n1 F# H- N1 Q! K
  102.     }/ m/ D( V! T" L% c' @
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
    - ~% r1 ]* o# v- D  a
  104. " ^9 a8 I) f4 K, p' P
  105.     /* 多块读取发送停止传输命令 */
    $ R) \- b7 {6 i- w7 L
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U)): e& Y8 d; ~/ }7 l& a% M8 v
  107.     {
    5 x  r4 L/ W6 E: }/ }- V
  108.       if(hsd->SdCard.CardType != CARD_SECURED)
    9 o1 J% c% z& b. M
  109.       {, V, G& ^1 w4 q% A% p( ^
  110.         /* 发送停止传输命令 */
    ; K* o+ S6 |, A( b
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);6 Z2 |; O" [! f0 e  M( Y
  112.         if(errorstate != HAL_SD_ERROR_NONE)% g# z( c0 }* n8 y& l& E3 o- I/ I& J
  113.         {
    , R; B" S7 J. w. x( f+ M8 Y
  114.           /* 清除所有静态标志 */$ Q6 A) `( o" X5 ?0 S2 y5 {
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    0 @, u, k9 t/ k2 a1 ]; Y2 o
  116.           hsd->ErrorCode |= errorstate;$ i. b6 S( D' X5 B( U
  117.           hsd->State = HAL_SD_STATE_READY;) z5 E% j  |  N8 I0 o7 Z
  118.           hsd->Context = SD_CONTEXT_NONE;
    . ^4 O6 O: i! f4 U1 O2 J+ c4 p
  119.           return HAL_ERROR;
    / e/ K. L- Q7 u: n
  120.         }- d3 ^, w; B% ^9 n2 H' e
  121.       }4 ^6 ?# A4 K* B& q/ H
  122.     }1 I3 `/ s1 e# x$ o& B! w( y9 i( y
  123.   b( x0 G( q/ J/ T
  124.     /* 获取错误状态 */3 S; f1 g1 S5 ^* t* Y
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    % C: {9 R6 R1 i' H
  126.     {
    9 \  U- q/ ?2 r$ S, w$ W
  127.       /* 清除所有静态标志 */
    " s! S6 I' |- v, L* N  [) p2 h& W5 o1 m
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    / n/ H- w7 }. T
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;$ n: @) B" Z- A" |5 e5 o% n
  130.       hsd->State = HAL_SD_STATE_READY;
    # w, R, w3 v6 h4 z
  131.       hsd->Context = SD_CONTEXT_NONE;
    # t$ G/ s' ~0 n+ M
  132.       return HAL_ERROR;. P4 d. w* i# E
  133.     }
    1 @! T" f4 \( D- R( R
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    8 t6 X) y% y1 S
  135.     {
    . F" n' i+ b. `+ E
  136.       /* 清除所有静态标志 */
    + v$ i7 f, j8 b  d7 y5 Y! Q, Q
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);# q$ U6 n7 S& \% {% {  P; m
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    ) R  [. X; }8 B# q+ ~) n* `
  139.       hsd->State = HAL_SD_STATE_READY;
    7 F' }% y# y/ H1 m+ l1 w1 @
  140.       hsd->Context = SD_CONTEXT_NONE;
      `# O' o# k7 h" l" s0 B5 b
  141.       return HAL_ERROR;
    2 H7 X' G# j3 O- O
  142.     }2 i+ ~: ^% f6 G1 ?, }0 B
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))4 b8 Z1 o( M- n; ?
  144.     {
    " k" R' ~1 j6 S8 g( G) M. x
  145.       /* 清除所有静态标志 */
    3 C$ o7 P/ k. |1 [# Z5 g  ~
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    4 ]: b7 c! n( Q( i
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;" }. g* R4 e! a& E
  148.       hsd->State = HAL_SD_STATE_READY;( G% k1 J% ^% f$ E; J  c
  149.       hsd->Context = SD_CONTEXT_NONE;# @' ]: X) |, T- H5 C& t$ g
  150.       return HAL_ERROR;
    ' \4 o6 b) M7 Y6 ]% m4 W8 G8 ?. ^
  151.     }4 U$ s6 d& C1 E/ u& C/ R4 v0 A5 W
  152.     else
    5 ?% I  k7 |0 H% S5 }/ S
  153.     {" n- Q! {' c3 Q- ]) c
  154.       /* 什么都不做 */
    % i& P" W- N3 R. e$ ?2 o$ q3 i3 [0 Q
  155.     }
    # l1 D8 y  F4 A1 d" O* ~7 l: H

  156. 1 E- T( a" H$ y' S4 m; e
  157.     /* 清除所有静态标志 */. h( A( T! o1 U# o
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    : r3 Y- s' V$ Q2 A8 D
  159. 1 k: q  o4 M: t$ L0 J0 U
  160.     hsd->State = HAL_SD_STATE_READY;  _3 K) x* w1 t
  161. ) Q+ l; E7 e( y  |0 e
  162.     return HAL_OK;
    & l7 O8 ~, e3 n
  163.   }
    5 H' M) E+ d1 B/ V& \
  164.   else
    + |# D7 [; u6 ]: @" w
  165.   {
    2 q* }  u" N. [
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    ! \6 j) x% R; t+ I$ F& ?
  167.     return HAL_ERROR;5 ~2 d/ `1 n( |. p( `7 i
  168.   }$ e0 o9 \  S$ H% h9 D2 z
  169. }
复制代码

+ p9 K& r; b) Q函数描述:8 O% q0 d' w' @. z, Z8 g& Z

  J+ F/ |% h8 o7 ?9 M0 e5 G此函数主要用于SD卡数据读取。
6 }- V: |5 B' n! m9 V
8 Q* [' t4 o/ p; q+ |函数参数:
- K7 V1 w" M3 z7 Y/ W1 j' F) _. J" \/ w1 g* c& _8 i  R
  第1个参数是SD_HandleTypeDef类型结构体指针变量。5 I0 d6 }( q" k' ~# }+ n; b1 y
  第2个参数是接收数据的缓冲地址。
" Z5 Z' x% p1 S7 @1 Z' p- [& m2 z  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。! d/ k2 I: o+ ]
  第4个参数是读取的扇区数。6 I7 M$ W( C) ]: `! ]
  第5个参数是传输过程的溢出时间,单位ms。8 c% ?7 W$ H- I2 O5 [
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。# p( I7 W! {0 w6 |
使用举例:+ J, K# Q* V0 R
3 F  D, o# A0 }4 }4 z8 Z
  1. /**
    ) W+ i1 A$ A8 ^, n: f# w
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.& V1 m1 g4 x0 |- T) z* p( c& N$ v
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
      L4 O. R( l) Z. _  P6 V( F% ?& y
  4.   * @param  ReadAddr: Address from where data is to be read
    # C5 h8 ^( r* b  v0 |
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    / m5 B! k$ F* U
  6.   * @param  Timeout: Timeout for read operation) o" r4 T1 Q8 K* u; f, K4 M: l
  7.   * @retval SD status
    $ S4 P+ s" k3 g; A& N$ [
  8.   */% E# t1 ^$ E# e2 A5 I# E
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)" L: o7 G$ ?7 G# C! {  {
  10. {
    " d% a- ?& c" E: |/ y/ F0 i, O

  11. 2 D, c0 n! E% _& _$ `) \$ q, G
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    + X4 }9 y' \# Z; m
  13.   {9 Q" n* i  ?5 f+ h0 l8 e2 B/ }
  14.     return MSD_OK;- [5 j/ c# j9 w' K+ i
  15.   }
    - z. J  u+ ~2 A3 T- x- V6 X# ~9 H
  16.   else
    5 ~* Y- `( }4 y9 K4 @
  17.   {
    ' b) t+ _% g. }' ~
  18.     return MSD_ERROR;, ?) w) U8 ?) I- F% P% y2 a) k  S
  19.   }
    ! L) q7 p2 K4 Z" G& T7 L; D2 U7 ^
  20. 2 ?1 H% M, ]/ b% j. g; c' @( Z* u
  21. }
复制代码
+ R9 w/ D1 R2 J
87.4.4 函数HAL_SD_WriteBlocks
7 ^7 V2 M: w8 n/ F8 S  E% g: S函数原型:
( }. X, l  }4 q" N2 G
3 o" {+ \& F1 e" y3 i
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)2 l  Q, }4 a( H
  2. {* h2 M, D) R7 Q/ O  h3 @& N
  3.   SDMMC_DataInitTypeDef config;3 Z, K7 h( a4 f4 O. @
  4.   uint32_t errorstate;/ p% R* I7 }) y
  5.   uint32_t tickstart = HAL_GetTick();% a3 D8 u* a1 s& p, P: {8 }
  6.   uint32_t count, data, dataremaining;
    3 x2 }0 A! ], r& c1 l
  7.   uint32_t add = BlockAdd;  X5 X6 I, Q" |5 r$ e  |, }
  8.   uint8_t *tempbuff = pData;
    + P/ G6 M  I1 Y' `" V* n
  9. 1 V. P* h. [( f" ]2 ]
  10.   if(NULL == pData)3 q9 l  \2 m8 d
  11.   {; `; `: g% K! x' i; W
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    2 r# X  w, V/ h. @' ?
  13.     return HAL_ERROR;  g2 R9 D- g+ g  i! i+ }4 L0 E
  14.   }" a8 W3 t2 b$ I* f$ E) |6 `6 b* D

  15. + E* r) G3 }$ T9 p/ K' }% |
  16.   if(hsd->State == HAL_SD_STATE_READY)
    # Y+ J' Y* k1 d, v. Q3 m! L
  17.   {1 Z4 ^5 ]" v  e
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    9 W) x* g$ {' f% K- u8 V; r# G$ h  {
  19. . v7 T6 K# @% c+ b& R
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))6 |9 V# Y& q+ R
  21.     {
    0 U/ E- `" ?' m; `5 v# l
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;! `& m! N- A! t
  23.       return HAL_ERROR;
    9 b2 x$ i: Y, p6 {% s+ \
  24.     }
    9 S' |) }5 C+ z4 ?
  25. ; p0 z) @) P( }& _0 _' [3 z( W- p
  26.     hsd->State = HAL_SD_STATE_BUSY;
    4 o( [) m& q: B

  27. + Q  o6 d, b$ I# B
  28.     /* 初始化数据控制寄存器 */5 ]; B/ a$ G7 C! `  G/ B
  29.     hsd->Instance->DCTRL = 0U;% }- n7 {# W; B: u: f% P: w
  30. # h7 c3 c- f( a" y
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC); s) C: N- j6 N2 P# C! z6 R
  32.     {
    . \6 Q( p0 X7 p- f, S) ^5 f0 E# Z
  33.       add *= 512U;" |7 L' B3 |, o, f- y4 c
  34.     }' V& f, M$ q4 I/ r0 D: u3 R0 ]

  35. 1 S! f; B$ m( ]0 D
  36.     /* 配置SD DPSM */, W# r5 f$ j! ?1 _3 c2 w# Y
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    0 j8 d& |  l$ @
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    # ~" ^/ k9 H$ z0 c
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    & j: `1 f+ t9 n/ c$ U- P2 m( ~  o
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;, Z, n' y) L1 [" [8 H
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;8 R4 W3 q, ~# [: q, V' a
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    % d/ d6 t* u3 i: D; A- p
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);/ X. c6 Y: b9 ~6 ]: W
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);* E" }& U& Z4 b& X) P
  45. 5 R* [- X$ r+ ~6 f" Z4 F3 e) P2 ?
  46.     /* 查询方式块写操作 */$ L3 x% Z9 s# ?0 t8 V
  47.     if(NumberOfBlocks > 1U), [6 ^" E' y: ^+ Y  m) k
  48.     {/ k- L+ P- N: v
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    3 |) \: f  t) h' `! s* L
  50. 3 Y7 T* q; F% y4 H
  51.       /* 写多块命令 */! ~- N6 Z+ q9 ?' M, E5 k% Z
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    2 ]3 x. c% a1 s. @" O+ D9 p: Y. M: O
  53.     }
    9 M/ y; m% \2 a7 j/ u: C* k: m
  54.     else# v- K- l% k- ?7 I4 m7 P
  55.     {
    4 d& k  }2 y' I1 K& r
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    - a# n0 ]9 ?- ^: m% t
  57. & \# n- Q/ G% e$ R) E$ _! g9 ^- j
  58.       /* 写单块命令 */
    . n6 c) A) j8 d- S8 K. i8 ]2 |! C
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
      \7 z+ o3 O* l( }
  60.     }
    ! C1 w- ~4 W4 D+ k. }
  61.     if(errorstate != HAL_SD_ERROR_NONE)# j/ b$ h% P% m7 V& s
  62.     {
    " G- T- |6 O! S% A" V
  63.       /* 清除所有静态命令 */
    6 E  v  p* |0 I. |, L: f8 `, |
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ) `" ~. G0 t, }/ @6 s- k
  65.       hsd->ErrorCode |= errorstate;
    : }" f  T, u4 e* R+ T: m  u
  66.       hsd->State = HAL_SD_STATE_READY;
    : c  l3 {( W- }+ V& \, [1 M
  67.       hsd->Context = SD_CONTEXT_NONE;' s: w5 ~9 U! C" B5 K% e) Z4 T
  68.       return HAL_ERROR;
    , f% O( W" ?7 M9 A1 P
  69.     }" G5 \. C5 }  I& m
  70. 9 M: E6 J8 B9 p
  71.     /* 查询方式块写操作 */
    " x7 I0 @9 e5 ^* J  ~1 K
  72.     dataremaining = config.DataLength;0 m$ F" `9 X" Z0 ~" x
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))0 t: d- T) c8 a5 b8 {+ e; ~
  74.     {
    ) {1 M6 Z8 p: T3 q4 s4 l
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))8 y# a3 x) d! A9 ~, Z
  76.       {
    ' J2 ^( O* C1 Y" X
  77.         /* 写数据到SDMMC Tx FIFO */* [; H3 N! F5 n' H" O2 |( A, x
  78.         for(count = 0U; count < 8U; count++)  C: G% ]' |$ c& l6 T* ]$ q
  79.         {
    8 I. ^: S5 j* i: D- C- h
  80.           data = (uint32_t)(*tempbuff);/ l' `8 r: r1 o5 E
  81.           tempbuff++;
    # p$ F; g' a7 }4 d) Q- W0 H& O
  82.           data |= ((uint32_t)(*tempbuff) << 8U);
    - W+ m0 g4 U4 g# Q6 ^
  83.           tempbuff++;' u* m! T7 `4 r0 ~
  84.           data |= ((uint32_t)(*tempbuff) << 16U);
      s- r* @- K4 r) N% u5 Q5 [
  85.           tempbuff++;
    + I& {" z( U, `! I3 M; p8 @- |* u
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    8 i4 Y2 o, X# B1 p* V9 X$ {
  87.           tempbuff++;
    ( w  h- n3 V8 f3 O8 u$ Z
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);9 e8 m- O4 K; ^7 Y; k
  89.         }
    9 w  y1 M* ^" c9 J7 r( t
  90.         dataremaining -= 32U;
    $ t1 M0 J! J1 F* a/ c5 j
  91.       }
    % i: |0 Q& V  O, E, J7 u

  92. ' c: ^; i- B$ p# E; a! q4 y3 f
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    - J1 B) m5 ~7 a& w" B2 {, a* M7 Q
  94.       {( F: M( w* u& F7 ^' F& D
  95.         /* 清除所有静态标志 */
    " I# r( F6 A; N
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    . c" {5 V# A0 g* k4 L+ Y
  97.         hsd->ErrorCode |= errorstate;- d' T# O, U( Z" u+ y9 P
  98.         hsd->State = HAL_SD_STATE_READY;
    , p; ~2 y! c: m& G8 f1 Z2 M
  99.         hsd->Context = SD_CONTEXT_NONE;
    - y: I  f- p2 N
  100.         return HAL_TIMEOUT;
    - r. E$ v% A) k2 h3 m7 f
  101.       }
    ' i* w3 X& _5 n8 k
  102.     }
    6 v/ l8 B2 I+ d, [- V+ z' R
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);6 V" E1 p) S" z: {; R
  104. ) R' D& [7 z) G& u" y
  105.     /* 多块写操作,发送停止传输命令 */
    8 w: x- k1 v# w6 F
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    ; v0 s) M+ b; J4 U& y
  107.     {7 W& ?3 d8 s+ W
  108.       if(hsd->SdCard.CardType != CARD_SECURED)% ?, R" Y) }/ A2 H) n
  109.       {
    + K1 `* r* ?: {6 E' b3 V
  110.         /* 发送停止传输命令 */& S( s( J% |; s+ X/ e
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);4 C# A+ {: J) l7 \- P2 F
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    : _: U1 A5 g5 {: i
  113.         {
    ; }. }" E, t9 L
  114.           /* 清除所有静态传输标志 */
    ! {2 ~" e5 O+ s3 L+ `5 r* @, k
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);  V+ _, Q% m' {; F( `& ?  R
  116.           hsd->ErrorCode |= errorstate;( h- F2 |% u' @; K# o
  117.           hsd->State = HAL_SD_STATE_READY;
    ' D" s& E, a- |8 B1 Q2 W
  118.           hsd->Context = SD_CONTEXT_NONE;& B5 O9 d# g' o( d5 U1 F
  119.           return HAL_ERROR;9 `0 X4 j4 R5 G9 C. U8 ?
  120.         }7 q; D7 ^3 E9 [( S" j
  121.       }0 k2 u5 C6 f" ]4 Q! d( P4 L
  122.     }4 q$ l8 v) U6 w: V1 l, P
  123. 9 W) \( \" c7 g9 }$ u0 S  v2 M
  124.     /* Get error state */
    4 q. c: a& K- R  r& D, m8 z
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))" S- q/ V# @1 U/ j
  126.     {; d9 \  f8 f0 e0 x  s0 e
  127.       /* 清除所有静态传输标志 */
    + c. ?8 X( f" s+ |- T
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    & r7 f- g, b8 v5 b/ R
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    * [. n0 k$ T; J8 B0 |" c
  130.       hsd->State = HAL_SD_STATE_READY;
    0 |: {9 p0 W7 h# r
  131.       hsd->Context = SD_CONTEXT_NONE;+ a, a& Z; e: P* f) A
  132.       return HAL_ERROR;2 E: J8 n3 p; Y3 Y
  133.     }, Z9 k' F) n1 j+ F' t7 O  Q" l$ V/ e
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    8 F& P: t3 c, l& a/ L& W1 Q0 I' _9 j
  135.     {3 p4 V4 v& Y/ ?! e( N2 d8 z
  136.       /* 清除所有静态传输标志 */- o; }" t$ \, e& m
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; q! O# {- x3 l& S3 I( o
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    . z2 L* A9 f% R/ C* ?; U
  139.       hsd->State = HAL_SD_STATE_READY;
    % W3 [( T) |. `: E" L
  140.       hsd->Context = SD_CONTEXT_NONE;5 s2 Q  J* F, L- Q
  141.       return HAL_ERROR;
    8 j% N! J0 |# |" P
  142.     }) V4 x8 M! [, E2 G$ }
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    ) r8 n  n7 T! T; s! E7 s
  144.     {
    3 b- M9 c0 ]- D* e. R
  145.       /* 清除所有静态传输标志 */# j6 X  O* J4 k
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);3 N  \% M2 f, O
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
    & U1 Q. _! u# p" I2 P$ P
  148.       hsd->State = HAL_SD_STATE_READY;$ g* o* a$ r! f: `/ y) c5 w* Y4 g2 b" z0 P
  149.       hsd->Context = SD_CONTEXT_NONE;4 [& |1 z. s: l3 B  @' G: O6 h
  150.       return HAL_ERROR;4 c* t* j& Y& D/ C) E% v- H
  151.     }. H* {: s1 N8 F; C
  152.     else) G7 v2 f) S- B: `& y) g4 `8 q4 L
  153.     {  N4 z, |7 O% c$ W1 f! q2 Z
  154.       /* 什么都不做 */$ T: ^$ u/ ^: q
  155.     }
    ( ^. R9 k( x* O4 F( g$ x1 P
  156. , k, U- y' N/ ^0 w) j" P$ L
  157.       /* 清除所有静态传输标志 */
    4 u7 z' E8 l: A3 }% {6 p, J3 l5 }
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    ( J* w* t7 ~  o. y, b
  159. 9 ^4 ~9 ]% b9 b# K& [
  160.     hsd->State = HAL_SD_STATE_READY;
    4 Q9 f" K, }: z, T$ d! L

  161. ' t+ p* e/ O# P
  162.     return HAL_OK;
    5 ~  k6 ?+ }1 g7 I) g
  163.   }4 H; R7 X6 ?- U  S5 i' m1 k% _# C
  164.   else# V' T3 Q/ T' X& `8 X3 @7 g
  165.   {
    8 C* X% `- a) Z3 C$ x
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;/ t' }# F4 a/ G9 V
  167.     return HAL_ERROR;
    0 p$ z8 h3 k# d  ~2 o/ ^
  168.   }4 J" I- E) S! j) j4 d3 a
  169. }
复制代码

  U5 [9 r( j  u  o函数描述:* h3 z* Z9 E1 E2 R! P- E3 ~2 o
9 P& u: f( G( G+ a
此函数主要用于向SD卡写入数据。3 s7 r: X5 G# r! O1 A
$ j% J0 A/ S3 [% |
函数参数:3 O# W3 \) Q' M

5 |2 y7 j" z- O% x  第1个参数是SD_HandleTypeDef类型结构体指针变量。
( Q. x+ m# s2 Z6 T: y7 s  第2个参数是要写入到SD卡的数据缓冲地址。: G1 x' C* S' b
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
- W7 R* W5 S, p: Z  第4个参数是读取的扇区数。
; y" y# ~( K9 G* ^0 N4 T& d  第5个参数是传输过程的溢出时间,单位ms。9 n/ A) q! h7 |* Q4 T# S' I
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
5 e4 ]9 ~7 p% s  F6 y% G使用举例:
7 {, G, u- I) X4 g& S
) L4 D0 F/ D' \1 A+ C
  1. /**
    7 K+ ~% Y, E8 U
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.* O! L% l! Z' m& Z
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit& _" o. K8 m# _1 v
  4.   * @param  WriteAddr: Address from where data is to be written$ L  A/ T) u2 ], R2 B  b3 t$ [
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    ! ]4 F6 W, G# _; T
  6.   * @param  Timeout: Timeout for write operation
    1 G% i1 P% |" Z' t! ~! R
  7.   * @retval SD status
    2 S6 F; X) k& ^% }7 }! w) n4 ?
  8.   */
    ( d1 P3 j4 w! W9 j4 v: D3 D! C8 \
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    " F7 ]. k# v0 A* j0 p
  10. {5 y. u8 w3 ?- X' L$ G6 ]
  11. - `; }+ _1 [, K1 t9 D6 H/ k
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)% l- A& w( X3 _7 F' a
  13.   {* ?; S& Y1 [, Z5 y% h
  14.     return MSD_OK;
    " F5 a3 [- Q- j% ?) C
  15.   }$ P1 w! y6 T% P, k+ t
  16.   else1 i$ i% n# T" G0 J5 `# {, C
  17.   {2 L0 q9 c2 d8 |  m! [
  18.     return MSD_ERROR;8 ?1 g7 d, B* c2 T  B% j
  19.   }) g+ y. ~; r( l) m2 j. }4 T$ K: z
  20. }
复制代码

' I: V+ C4 c2 f2 D3 R# }87.4.5 函数HAL_SD_ReadBlocks_DMA) a, Q! Y8 d* X4 o
函数原型:2 `- I2 V) H  I4 o4 b- V

. c/ f3 Z+ u# ]- {+ g
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    9 Z) \, x' s, X- D1 ?
  2. {
    ' }% |0 |& J/ H+ ]4 X5 x
  3.   SDMMC_DataInitTypeDef config;
    & @5 ^2 W  T' E& `2 `3 j8 x( S
  4.   uint32_t errorstate;
    9 i& f3 i8 t! ^4 ]7 G$ O2 P" ]5 M
  5.   uint32_t add = BlockAdd;
    * h. W. z" w% Y- |

  6. 4 {( C* u( d! E% W* @8 R' Z
  7.   if(NULL == pData)0 v- s. G" k. D: b
  8.   {. x4 T8 ]' \9 s* S
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    % p/ d; o$ d3 u4 E: ~# o. n
  10.     return HAL_ERROR;
    1 p( t0 S: ?* m" `5 H0 p; \6 Z9 c' s
  11.   }
    & d2 _; n. p) S: H  Z
  12. - l4 m4 c: _# y. G
  13.   if(hsd->State == HAL_SD_STATE_READY)" ~% v) e4 n! w$ V: x2 A1 J6 T
  14.   {
    # q9 ]2 G5 ]  h' g$ U
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    5 e. ]. e8 ^; h

  16. . j( r, P! w, |4 a
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    & Y" `) q' w' Z
  18.     {
    " q6 n" I; j8 h* {6 r0 O; c. p
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;. j4 E, f  `( B
  20.       return HAL_ERROR;$ J5 Q7 n4 T. P, Z& ?; j& c: a
  21.     }7 f; P4 a6 Y# H3 S
  22. # ~4 ]6 L6 a# Q( J: _$ D6 e) U
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ( S, F6 I8 R4 C0 t- @9 {% O1 b
  24. ! C* l4 {/ S0 j, x
  25.   /* 初始化数据控制寄存器 */" g$ Z0 }: @4 ~3 a4 N& n
  26.     hsd->Instance->DCTRL = 0U;
    7 T6 Q( H" g3 m6 p) m
  27. 2 u" ?  L7 i: m  }
  28.     hsd->pRxBuffPtr = pData;
    : X5 Z& W5 ~% p8 N# Z% m% }
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;; p0 f3 c- T% d9 E# D) ]: Z
  30. # L5 K9 e. z8 S
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    + b# G: a: d1 V) B+ B: G
  32.     {
    0 r& g' i0 p+ o
  33.       add *= 512U;& N5 z, K9 m1 @9 O! n) l
  34.     }+ I, O7 u& P" r) W- G
  35. - G- h, x3 L1 V( X" b& B* |
  36.   /* 配置SD DPSM (Data Path State Machine) */
    * s' u! N' Z) A8 a7 g: d# n) b
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;- |0 [$ p$ b) ?, C
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;2 R$ i" q: O( N- J% F. I
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;* Q$ F4 x+ b; C" n
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;! r3 J2 r) X2 K4 Y; e/ R0 A5 U7 }, m
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;# M. r/ x/ q: ^, X$ Y/ X
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    9 `# ^7 |8 @: n7 p3 K0 l
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    $ t. r6 \1 ]4 r8 o" ~2 M
  44. % ?. e1 Z" S0 Y: u3 N
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    , Y' g8 G9 [9 t
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;6 X' O7 X, Q5 a1 {" a
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    $ ^8 v9 Y/ t' j0 c7 j) ?
  48. + k0 g8 I# k; s/ Y) h& E  K& D0 _% O
  49.   /* DMA方式读取多个块 */% ]: g7 y7 M, c
  50.     if(NumberOfBlocks > 1U)
    . S9 K7 R) |$ H! n2 A( j; m
  51.     {
    5 c7 z4 a  {4 H0 m# d$ G, M; O+ u9 I. V
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    1 {: g1 a+ F+ T) B* m, M: U

  53. 6 S+ a. y! \9 L& e  B
  54.    /* DMA方式读取多块命令 */0 T  j2 C% K3 a% n5 K9 l9 T" H% _$ Z1 ?
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
      U' }# a) J5 K/ T" l: w$ R4 t
  56.     }
    " K4 l9 C$ |4 I  w; d% B
  57.     else  P- Y1 O% n" Z# S8 ^3 ~
  58.     {& V8 w% k/ J" A3 l1 C
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);. J5 M9 b9 @6 y5 g" J1 O  M
  60. ) J3 Z) S9 a7 B$ g: m  _
  61.    /* 读取单块命令 */
    2 k. G3 ^8 Q) @) Z
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);5 G5 i6 j4 _( t' w
  63.     }; j! g# t  s) K  r, n$ n2 F) Y
  64.     if(errorstate != HAL_SD_ERROR_NONE)
    2 V7 J4 V6 Z& p8 U* F
  65.     {
    ; T, N- E1 T& I! S, n
  66.    /* 清除所有静态标志 */, S7 i  o+ O: l2 s8 E' F, e
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    * {1 Y$ B1 H1 W/ K  g: r9 r& W
  68.       hsd->ErrorCode |= errorstate;) `& ^  `, l' m1 o$ }' Z$ ^
  69.       hsd->State = HAL_SD_STATE_READY;
    6 {+ Y, u" y1 I& z8 F
  70.       hsd->Context = SD_CONTEXT_NONE;9 |1 z4 o; [+ o! n) H* ?7 D  J; B9 L
  71.       return HAL_ERROR;7 n1 Y9 }% C! R+ t3 t& Z: \
  72.     }
    7 [6 J( D8 {$ d

  73. ! |5 ~, X4 a3 m9 ~5 g
  74.   /* 使能传输中断 */
    5 V. F/ E1 W9 K+ ~. J* U0 m
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    6 Y; c) I8 w/ |

  76. & P) F. O. [8 _" |8 H

  77. " T2 L) E) ?1 {. x4 L7 L& N0 E
  78.     return HAL_OK;
    / `$ E5 P& u8 J% V' Q
  79.   }# O% k1 z$ a( A8 j" V
  80.   else
    : h% x  C3 O% J
  81.   {5 l) e0 |9 T- `! T
  82.     return HAL_BUSY;' y8 M4 a. t, [& n
  83.   }
    9 h5 k! z; K) K( c0 \
  84. }
复制代码

1 M# s9 U0 [( B4 J) ^1 ?1 \函数描述:4 W/ ~" R4 {5 c) V8 w% ~' v
( n- }: ], x* h: m
此函数主要用于SD卡数据读取,DMA方式。
) V/ I1 y" F2 F. u
4 @  B# a; @2 w% Q! C函数参数:# F" X/ i$ f, s; D

4 e  C6 w0 F$ q3 y" _4 Q  b/ c  第1个参数是SD_HandleTypeDef类型结构体指针变量。! g2 Y9 b/ f0 a; y
  第2个参数是接收数据的缓冲地址。
1 X! K' q: F/ T$ K( t: T  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
8 g$ K8 g1 M/ y& B  第4个参数是读取的扇区数。
4 o9 q' R2 F& z) V  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
: G$ Z) U; a2 ^7 ?2 @% K9 I( C使用举例:
% P) i& l& _( p$ R, I) S$ F. S! A* f* R
  1. /**
    * A" f( i6 P% A! v
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    2 L  X. u& G+ s2 |2 ]5 U
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    ; p# s- O6 K8 ^- [
  4. * @param  ReadAddr: Address from where data is to be read
    3 f* W* T0 u& w* L$ J0 B8 H2 {! a
  5. * @param  NumOfBlocks: Number of SD blocks to read# H6 o9 P% y4 }; F
  6. * @retval SD status
    # ^; }3 R1 [. c. k' v
  7. */) [6 y8 m1 D0 [
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)( I; U+ v8 d  \, l& m' ~
  9. {
    ) F- A" G& a* c8 P

  10. 3 d% v# o" k; T- F; M* i+ U/ g
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
    ; E0 C6 g$ r" K: }
  12.   {! W, H: L2 u% v" l& f) B
  13.     return MSD_OK;# {. c7 N: {& z- w
  14.   }
    4 u% h9 A+ I: w8 \3 D' v
  15.   else. s# m# N7 i9 E: u5 ?
  16.   {; {2 I) p: ?7 h+ j$ X( C" H
  17.     return MSD_ERROR;
    ) P( Z1 r: u/ X& R
  18.   }
    9 X, O) H' g/ U1 G& l9 I# d
  19. }
复制代码
8 n. q0 P8 P: O0 e) `
87.4.6 函数HAL_SD_WriteBlocks_DMA8 c% K" ?2 X: k; J6 ^3 p: k
函数原型:
9 e6 h/ X6 U9 }2 Z( U1 D- n: G, q' x
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)( y5 ?% L' y" O
  2. {
    . t: E! M0 S" L- p
  3.   SDMMC_DataInitTypeDef config;' G& ^6 L: \9 j; I) K; G8 |
  4.   uint32_t errorstate;0 @; ?$ R  O( B9 D4 b
  5.   uint32_t add = BlockAdd;
    / {* F. `7 y5 s% {; \- F8 {. M, g' O  G
  6. 7 p% m0 k5 O/ S0 g2 d
  7.   if(NULL == pData)8 S, i5 _6 P. S2 Y
  8.   {
    ) s( p, p1 w9 {" ^$ c( a+ p( I
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    . j  I& @' ]! ]
  10.     return HAL_ERROR;
    3 w: e  y9 ^. U: w+ M4 {  j
  11.   }3 p# L/ ?4 @/ K3 j

  12. # _7 B+ m/ t  S5 C3 u+ w/ L4 v: D
  13.   if(hsd->State == HAL_SD_STATE_READY)" N3 V2 O: F7 @0 n& H
  14.   {* ~) x% t# k+ l1 I, u: n. w; u
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    0 T  R8 e8 j* Q( R9 u- t

  16. $ _; y) l( f# Y
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    . ]! [! k7 p% Z( s
  18.     {
    2 A# v0 q* H7 ~6 Z2 d  e/ U
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    & N9 E  E; n0 T% t6 B, G
  20.       return HAL_ERROR;
    - z8 Q# n, T. J. E! c7 Q
  21.     }
    , W% g& |: A) T0 g! l

  22. 1 ?( O) x, A+ e0 p: S
  23.     hsd->State = HAL_SD_STATE_BUSY;
    0 v1 d# j" Y' \9 V
  24. - `3 A% V' b8 ~+ w: U
  25.   /* 初始化数据控制寄存器 */
    # ^- P( p( |3 C9 V
  26.     hsd->Instance->DCTRL = 0U;
    $ D1 D3 i% V8 r
  27. / v3 I/ U6 _5 v
  28.     hsd->pTxBuffPtr = pData;$ j1 ?, T% o+ Q
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;, `1 y6 X. v0 S, `- F+ ^4 F$ O; N' O

  30. 5 ?0 v" F5 N& Z
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    9 g* v( h  R  C
  32.     {: i& P5 W  a- W/ M( E! c! h
  33.       add *= 512U;% s" Q  }8 ?4 o: l6 z2 U1 y5 ~1 }
  34.     }) L; l5 M: g4 }; S  p6 w
  35. * W: c! \% b2 V6 [2 v% d
  36.   /* 配置SD DPSM (Data Path State Machine) */, }5 j' R* o, Y3 |/ L" Z
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;9 q, \" f/ Y' q  p/ q7 E$ O6 q
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    ( v- n; s6 I/ [( f* ?  ^) k6 z# G
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    ! A) y9 I: y& }! _/ `# ?, h5 m
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    0 o1 Z6 T& v( n! _
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    2 c3 Y0 U* s: \, t
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;2 p# a! t: H" S( j& z; b
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    4 I9 l9 i2 k* U+ X$ n

  44. , N. p( o$ l5 F4 ^- c! s
  45.   u+ }/ e' X. L2 p; U% {( {
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);" y+ v% J/ F- E, t& Y4 l1 ]; a
  47. 9 I( f1 p/ Z, L; O: L
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;* |3 i( ^- X% x  G
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
      |7 a; }/ w4 u: _+ C& Y

  50. , u. }2 t1 b( Z4 {& O% o6 J
  51.   /* 查询模式写块 */* T, ]6 J: ]% g! C6 E3 l1 \( y
  52.     if(NumberOfBlocks > 1U)1 a' r5 E( R4 j& {
  53.     {6 [. y+ T) Q* ]. F  \
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    9 q) _, p6 @. O/ j; H
  55. ; m! }0 A6 w1 G; r
  56.     /* 多块写命令 */) K! H8 E/ j4 m# o3 P/ V/ q, _$ C
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);/ D2 g" X) i/ y. ]3 z( C
  58.     }& g, G% H$ F9 J2 T; }
  59.     else
    1 R7 p3 u& P  l% j7 I7 q
  60.     {
    1 I  ]3 {6 ]/ E2 G- C# P1 u$ t6 d
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);7 h' f$ ?# X3 I& v; ?
  62.   U1 k/ a/ N; N6 u$ Q6 b" J
  63.     /* 单块写命令 */, e8 S9 B. G8 m/ C
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);7 V3 H9 R8 {6 l/ G
  65.     }: T3 I& s# v" e7 e
  66.     if(errorstate != HAL_SD_ERROR_NONE)7 p& L6 R" r, g  ]$ B
  67.     {7 K" q! L0 B( \- E$ J
  68.     /* 清除静态标志 */. s* U+ a; M6 R# m& _
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    # g* B  |( i; q- [% [9 u, G" P9 Y# `
  70.       hsd->ErrorCode |= errorstate;
    - n/ n! P* n! [6 `9 ^" v; p$ {
  71.       hsd->State = HAL_SD_STATE_READY;
    ) q* T  g1 A8 E
  72.       hsd->Context = SD_CONTEXT_NONE;
    ; H" A0 l4 q, m- M4 A1 |1 D# M
  73.       return HAL_ERROR;% D' ?1 L4 C' f. B7 e( P/ ^3 c6 o
  74.     }5 P4 J4 y- V" Z0 |

  75. " t2 X* E. v2 I* Z& S: Y$ L
  76.   /* 使能传输中断 Enable */
    , F( p; z  J$ c+ ]) f
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));# e8 z& `8 T: T4 Z' Z( g3 \3 n
  78. ! D( |# t5 h" }. g
  79.     return HAL_OK;% l+ J7 o! F7 \1 ?  Z+ E
  80.   }
    & d; z# y( S; l
  81.   else5 [4 a, L( ^: H9 z. F; f4 W, k
  82.   {
    7 \' v8 E' {+ I& x/ y+ Y
  83.     return HAL_BUSY;
    . E& l" i* b1 T) B( [
  84.   }# v! A$ L6 x# |4 {  }
  85. }
复制代码
* ~8 s- m' y( l$ s' H, R/ ]6 {
函数描述:
. {: l6 s! C1 q4 @) n7 h( p0 S0 h* r  N
- X1 d  \9 {; ?# D1 q# M此函数主要用于向SD卡写入数据,DMA方式。0 n, d, n& }- ?( x
$ g+ ^. k! M1 f) {1 m
函数参数:
$ B+ \* E* e  u' E
; m7 N( b7 ]. g3 {: c  第1个参数是SD_HandleTypeDef类型结构体指针变量。
4 d* }! P$ B5 L' k4 w+ ]/ A7 K+ z4 ~  第2个参数是要写入到SD卡的数据缓冲地址。
$ M; c  s7 Q8 Z5 [; a7 H  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
) \- m# ]0 d& W- H) o7 ~  y  第4个参数是读取的扇区数。$ O: [4 s+ z! F9 ^
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。( o, d1 P0 p6 |( Z+ \  E
使用举例:3 e. B: K' }' a( W9 V; L0 R3 b

( L- L/ ?/ d7 u) P$ \3 E0 t
  1. /**8 a8 L  E1 t, c; i6 {
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.0 }& }6 L) C+ A4 B: {
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit" n  e" X/ q; Y8 l% }1 `8 w
  4. * @param  WriteAddr: Address from where data is to be written! V1 r$ C4 F( R% g
  5. * @param  NumOfBlocks: Number of SD blocks to write
    ' F, j0 i( |3 _8 ?4 |9 l; w% y, ]
  6. * @retval SD status5 g. {. G' U; a+ o& H2 D1 V% ?9 W
  7. */
    ) ]. Q( k% e/ C3 ?9 M
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    9 c" N& m5 q0 P* X
  9. {3 @- h5 Z6 f6 P2 p: r* Y
  10. 5 Y; s& g* u/ G
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK): b* ]  g3 v: f9 Q. \5 k
  12.   {
      b# M" O2 i# k6 Z/ N
  13.     return MSD_OK;! Z8 G/ ]8 t) R3 Z0 j& {& K
  14.   }! T6 e$ J" {0 i/ J! p
  15.   else
    8 j% t3 Z( [6 L% \" \5 j+ S4 L9 C: ?
  16.   {, u. m% `* J! W! G9 R
  17.     return MSD_ERROR;
    $ `# C! D  j6 f5 s3 m
  18.   }. K/ k3 }8 l" q3 m; X
  19. }
复制代码
9 m: l2 K# G3 i5 V
87.4.7 函数HAL_SD_Erase$ z( }6 I/ `2 r8 X6 }) e) L! s
函数原型:
% b. k% ?8 z4 g# g, @( N, T( U5 Y! \1 |
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    : z/ Z. |0 ^& L: U+ H8 N6 E  o. \
  2. {
    , p0 u% e8 O, j, ]2 W# u
  3.   uint32_t errorstate;, M& o3 U, S$ Z" ]
  4.   uint32_t start_add = BlockStartAdd;1 C$ B( N3 h. [$ b6 d8 C' O
  5.   uint32_t end_add = BlockEndAdd;5 g& m8 I" Y+ z+ F

  6. ) H( A  f( V' _7 x7 a- q$ i  U" s1 D
  7.   if(hsd->State == HAL_SD_STATE_READY)
    % u8 ?1 n& o7 b$ m8 |
  8.   {* S' [' R) n6 W  j4 o
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    & C0 O$ Q# E$ C3 o
  10. - b7 b# a$ x0 `9 p2 V- p$ O
  11.     if(end_add < start_add)0 c5 _7 V) {* a4 U0 N, ?  @
  12.     {
    ( ^5 ?( D; x7 u7 o" Q' J# S
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    ( q( {/ U, U3 @9 o0 T0 A( m
  14.       return HAL_ERROR;/ ~1 w0 V4 n3 V% D6 v$ {! n
  15.     }
    ' p) o6 ^9 V* A5 ^+ y

  16. 4 O$ H3 F+ `% x' D5 C, i8 S0 ~
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))5 D  I; H. C0 G; \  Y& B; E3 i* P
  18.     {
    / q4 ]7 j) Z% R2 M8 _+ o4 d0 ^
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    1 i- Y, i) Y1 B7 ?9 \, v4 q; d
  20.       return HAL_ERROR;9 ]# G6 T/ u  p. v/ S: `5 N
  21.     }
    " t' |. K" w( \

  22. ! Y3 H( q% a5 Y  l( T9 w
  23.     hsd->State = HAL_SD_STATE_BUSY;# U& B5 P4 J' h- r* q: Z
  24. # ~; f& n: z8 L5 `+ q5 W
  25.   /* 检测是否支持擦除命令 */
    # y% K( f2 u& ^8 w/ i" w
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U), X8 x: Z* i% ~" |6 d5 j
  27.     {0 K. \7 E8 J* j, }' v! `
  28.       /* 清除所有静态标志 */
    5 ?; t# h0 D5 }5 {3 V3 x
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    # o1 s: {8 z8 i
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;& C- D' }2 n$ s. t. x- z
  31.       hsd->State = HAL_SD_STATE_READY;/ G6 s8 G" I, c. i
  32.       return HAL_ERROR;
    ( V% K$ X+ F- x- M# i# q
  33.     }( Z9 j/ s. H: S

  34. 3 \. C! e# a+ i
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)- k2 i5 ]& Z; p$ J  k" ~
  36.     {9 h2 u2 ~  w, ]4 {8 k6 A0 Q
  37.     /* 清除所有静态标志 */
    + _$ t) B0 e  {6 \
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; [* n$ C; t$ {8 y* M
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;, \) `* z/ u' l/ ^$ g' |
  40.       hsd->State = HAL_SD_STATE_READY;
    8 D7 ]3 ^) I+ Y* F. o
  41.       return HAL_ERROR;
    ; {- l  H$ L% H+ r" j
  42.     }
    9 d- n! N, u# s$ C) R

  43. ) l" `1 ]6 s6 x% e" n0 Z
  44.   /* 对于高容量卡,获取起始块和结束块 */7 ?# L% X4 t; j2 T$ [- h5 r: x
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    5 M4 V: C2 A& Q5 I1 z; X3 g
  46.     {9 `* m2 T7 |1 n. A. e$ Y/ B7 W2 r
  47.       start_add *= 512U;3 B$ L8 ]* e5 H0 @, w
  48.       end_add   *= 512U;
    ' H5 z& D4 g( O
  49.     }
    # x, b2 {( q) i0 W( t+ ^2 d/ v; ~
  50. ) _: Z5 Y' O7 B6 A2 ^+ [9 F* K$ Z
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    4 }4 t, S) F& ^  f# x
  52.     if(hsd->SdCard.CardType != CARD_SECURED)0 F& a. A0 V; ~6 A9 Y- s' W
  53.     {0 s* v! f6 k) X: h; _
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
    $ y, @  n# k7 z. }8 n; h. H
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);5 F# v& T9 c7 C% h
  56.       if(errorstate != HAL_SD_ERROR_NONE)
    9 F; ~& Q. P- F' D# ^! D6 M" l
  57.       {
    " J; r2 ]! \% r6 t
  58.         /* 清除所有静态标志 */" L) L$ {* E3 Y1 x) o
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    8 N7 v. f# }9 y( u0 {; ^% C8 l
  60.         hsd->ErrorCode |= errorstate;
    . t" a2 j4 s" |! R/ l3 t. X$ L  R
  61.         hsd->State = HAL_SD_STATE_READY;
    . Y" ]) i2 t& e, O; V
  62.         return HAL_ERROR;% s4 [/ P' g; `! N0 K
  63.       }
    ; o. i! y" x9 K4 I, v
  64. 2 z7 i0 ~8 p% Q# b
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */) ^, [2 {9 M) w% u
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    - c1 l7 _0 i* {1 ?  W: @0 Y
  67.       if(errorstate != HAL_SD_ERROR_NONE)0 w) L/ ^# S) S$ L6 s' s: t
  68.       {  V6 b2 L9 F2 s
  69.         /* 清除所有静态标志 */, J2 `  M7 O5 C
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    " M, X1 V9 L5 C( z" ?" d& E/ K
  71.         hsd->ErrorCode |= errorstate;8 j2 k/ d7 N4 N: m4 ?! O( W
  72.         hsd->State = HAL_SD_STATE_READY;$ M! Q8 ?: |7 P% C
  73.         return HAL_ERROR;/ X* C% ~- G" k* P8 a7 x1 k; n' f
  74.       }, ^( m- [% b6 u9 @6 w: c8 U' Y, K
  75.     }' A1 B: j( h5 K

  76.   h' b. o* F1 D; q4 w$ \' R9 o
  77.     /* 发送CMD38 ERASE命令 */, z1 M3 E, k& x3 s7 p5 [
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    1 \* L5 R# W4 s
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    6 h" b& k+ I" }# l7 ]* L
  80.     {- E. V3 ^6 U1 n8 M( |7 n, |
  81.       /* 清除所有静态标志 */
    8 D/ r) Z3 |+ d& G7 A
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    0 M/ Z' o% ^& Y
  83.       hsd->ErrorCode |= errorstate;
    2 N( k1 z6 y& s+ I6 E
  84.       hsd->State = HAL_SD_STATE_READY;
    ! P* V" U0 @2 a: s* w) H
  85.       return HAL_ERROR;/ e# u( |8 T" W  A& F
  86.     }) t7 H+ l& E5 U) [+ K( C3 T0 j

  87. : `) k/ ?8 i3 G2 \
  88.     hsd->State = HAL_SD_STATE_READY;
    " }/ X# X' E% Q, A' n

  89. $ e$ D9 P) ]" e  z
  90.     return HAL_OK;7 S, I4 i% e0 q. m  [3 V6 H
  91.   }/ i5 {, v! B0 E
  92.   else1 j$ N1 J3 d- q) @0 C, i3 B! t7 Y
  93.   {: j! W4 f( |0 K+ A* f" F
  94.     return HAL_BUSY;3 f4 ^* T3 J7 ]
  95.   }
    3 ~3 A" l! ^' d
  96. }
复制代码

3 v! |& l, x1 {函数描述:. u$ W- O7 T5 s2 Z- Q% y

; K+ q0 D7 b; H  t此函数主要用于SD卡擦除。
9 g0 z3 T# [/ P  s0 e. W& }( C1 D
7 U7 f/ x% r! W6 @函数参数:
* D, l, Y0 N/ V- x6 [. Y9 t5 _* U9 Y9 z5 |2 `) t& f. S8 |
  第1个参数是SD_HandleTypeDef类型结构体指针变量。0 j% c4 T2 Q& G# [! ]4 p; z4 H0 W1 {
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。  x) V" z4 u* q: L
  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。7 ]! l4 E" a' v% H- \0 o0 A
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
1 a* P! W* w7 H6 z& [9 `使用举例:
/ t( n, E1 Y& q* a
6 p( @9 z) ?0 L; W& f
  1. /**
    ' V1 @" `+ B6 E  n4 A9 e
  2. * @brief  Erases the specified memory area of the given SD card.
    ! a' f& n- a+ X% ~9 Z
  3. * @param  StartAddr: Start byte address
    4 J; n3 S4 b0 E; k6 q3 _, T
  4. * @param  EndAddr: End byte address4 K2 t; r3 C' Z$ R
  5. * @retval SD status. B7 s  x& ?$ t, `! P6 K
  6. */
    / ?) W& D* S$ H6 t
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
    2 E1 w% U4 \! r
  8. {
    ' P) I& A) X; V. T. j
  9. + Z. ~3 L* S9 s8 ?: C/ c& G0 C
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    ; a  @- w$ s6 x4 x0 S
  11.   {7 F' ^# ]& s. k& Q) W
  12.     return MSD_OK;
    3 i% _9 x* h. j# D- k! `
  13.   }
    0 z0 d, c1 u$ K8 f
  14.   else* M3 `2 S& c5 B. I2 q
  15.   {
    8 H- ?/ m, t, w4 c  ^" @
  16.     return MSD_ERROR;
    ( i% @" m$ |4 y0 W2 c
  17.   }
    8 _( c! [% O5 c% [" e5 ^  J
  18. }
复制代码

$ w4 V0 n# {# Y87.5 总结
& s+ v+ z2 N* ~% L: M( d本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。0 i$ N. h. J4 A4 u3 ^
# T) `! l" V1 a! N3 {3 Q" L
9 c. e% J& m) z
收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答

所属标签

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