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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示
0 [& W- ~6 k7 t* N0 L0 d3 h3 W- |  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。3 Q& e$ Y* K, K
  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。# _9 A$ W3 R  ^9 M- m
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。7 _1 y! ^& g6 i9 b# |5 j3 }
  SDMMC驱动SD卡支持1线和4线模式。9 z/ ?+ n( e, S2 k+ D6 @/ X8 ?
  STM32H7的SDMMC也支持eMMC:+ l* Y4 f. ]' g; h5 _; E
  
3 o  C3 D+ }; M- g. Q87.2 SDMMC总线基础知识1 V* G+ |$ |$ E& H' U% `
87.2.1 SDMMC总线的硬件框图7 I) I: N7 Z0 I
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
) Z/ V% s- ~" @  G) y7 }  `7 ~0 K6 `7 \% K& B/ n' a
6eea62abe623396815a50adc87205b83.png
$ s$ ?0 A- t  Z

4 \! [- e- L) E* ?通过这个框图,我们可以得到如下信息:2 Q$ x  U! W8 p# h! j
. c; F! L0 M& J, `7 U
sdmmc_ker_ck输入
; e* b% |. S; [6 m- [, }" ISDMMC内核时钟。, Q, X4 ?4 W6 C' T9 x! z
, F, r) B0 d4 |8 V, H+ A
  sdmmc_hclk输入9 d4 @4 k6 p. @6 N' w% Z
AHB时钟。
# f& M; X9 h, l7 \# |, r& ]& l+ D3 _  B" g. q. s, X8 C
  sdmmc_it输出
9 L- V) s# v2 D* w. t& ESDMMC全局中断。
/ Z' O$ f* J3 `# @
- H4 v( ]7 \: m# l; ]/ N  sdmmc_dataend_trg输出
! z8 f) ]% k4 ?9 j6 VMDMA的SDMMC数据接收触发信号。
+ W3 X5 _; M9 I/ b5 V: d* C) I
, r& v% k* B4 x8 K  SDMMC_CMD
$ i0 l, j' Y* l  qSD/SDIO/MMC卡双向/响应信号。
0 B* G; N0 V% U3 \; q$ A
5 Z! m1 \9 f5 q; z3 E5 Z  SDMMC_D[7:0], H' v) {5 F4 _
SD/SDIO/MMC卡双向数据线。6 U. m" ?% y# Y  ^- N) O: C  E

/ x2 P6 a  H: F( z; P  SDMMC_CKIN+ n1 u: ^* v4 l
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。+ o0 H, Q- U6 J6 l
; n1 A2 G" ]1 v6 g
  SDMMC_CK/ \# \% g' X: L, K! B
SD/SDIO/MMC卡的时钟。
9 V' K9 o) {+ ]' a" I9 Q8 ?( v1 z1 s0 f8 f
  SDMMC_CDIR; u7 ?" n8 @$ |$ G2 g& R0 l0 M
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。/ n% ?6 j! ]! F- ^

  A- e$ I/ l4 }% z) ], E, Z  SDMMC_D123DIR
, y7 h% X' \( ]# O# U1 ZSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
( R! _' ]/ u& l8 a% L( r* N7 a  Y; V+ u: e
  SDMMC_D0DIR
! j8 ^+ ~! n! z& m$ N% x! lSDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。/ _. E$ Q2 ]# L8 `1 C

6 ~( g6 X  P+ n  LSTM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
" @( N" X! o( |9 R) M7 L+ h/ Y# y, j, `+ T- Y( z1 V  z4 E) U
87.2.2 SDMMC时钟
) J/ F: N+ e. F; F0 O1 t9 e3 kSDMMC控制器的时钟来源:, p6 d3 a# O) p

  s" f* N1 E: s2 t% p% I0 }
676ec31792fcb80bee640ed979d48084.png

  i, H% |8 U, q% I/ l4 V' O
+ }' y* m9 w/ G+ r* s9 M, ySDMMC1和SDMMC2时钟源是一样的:
9 m' z, X+ L+ [4 u
; B  |3 e2 f/ A
79b1c69986d1ee5bc090bf1676f396fd.png

+ Y- I* Q: V+ B$ _/ H& v1 ]# f- r: f! e' N0 I  K, C
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
2 f' N2 Y6 S$ [0 |注:大家应用时要特别注意这个问题。
1 n/ w7 l' j* T- F" k  A3 E( C
) @2 X5 G3 `* {! [使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的0 o5 l6 N7 e, b( q3 s, \/ R0 ~! w6 Y
7 [! Y) s1 e4 T  }
6a5491d2f4a8740d838af58d034b7597.png

* O6 N/ z- d+ {7 J# B; M
6 j) k7 s8 m* ~$ {' b87.2.4 SDMMC支持的速度
% v9 F# y. D& a; b0 u驱动SD卡支持的最大总线速度:
) A* k1 x% F# L& f1 m
- c6 k- O  x! R2 g
b70ce31107b38ea820dbc28c3caec38e.png
. M- b1 A  y* Y4 M

/ c6 }% {' V0 s驱动eMMC支持的最大总线速度:
; K& Z8 i; H6 A, G" v, H& I2 ?" Y9 F9 d' Q2 i
843bf7a054944ba7d5d137ca84e1d4ed.png
) Q- K! n: i4 P) G

4 N" S8 h8 ^' p$ T- w3 p关于这两个数据表,注意以下几点:
. a& @7 {8 f6 W
) q( x) H' `6 K& ]' d/ i. [  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
3 @$ B7 ?& W- K9 z/ F9 p  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
0 `  U, h4 H6 _1 ^6 }  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
; Q' W! r9 O3 M$ w: u$ A1 {87.2.5 SDMMC支持UHS-I模式0 }, H$ B% s! [+ ?
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
$ l: c0 ~8 Q* M0 y  x* G' D6 Y7 R) w) G( [' K- }+ }
2b8e4430b8a60dc5a1b342d7c7f75f52.png

; K' [, a* Z. K: ~8 N# v# E) m, t5 F6 M" c0 Q. i
85f975745619c9afc64f8889289dad58.png
. J4 i+ \# ?8 V/ f
' x, |2 C  [9 ~4 c0 X
87.2.6 SDMMC自带的DMA控制器IDMA: T7 S; h8 d: N$ Q2 u; ~
STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。; M5 {& s2 P9 [5 h% p

5 G% x6 T$ V5 z0 J: ?/ e" h87.3 SDMMC总线的HAL库用法8 ], k9 Q% }0 }/ \. {( H0 H
87.3.1 SDMMC总线结构体SD_TypeDef
5 o/ T- W( ~* F6 T! w8 bSDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:' C" d  n0 n; F- v
6 e6 E; J- \! d  F
  1. #define SD_TypeDef          SDMMC_TypeDef1 s$ i( v) h6 Z; E& q4 ^4 n% e
  2. typedef struct$ Y4 J- C! p  X  }: f/ l# h8 ^
  3. {. F7 |% Z' I+ ~- l1 X! X5 n2 H
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */9 L1 F) a# ?% @. G+ F! d2 i& q. \
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */- n8 E* u4 V; @7 U* p6 G0 Z
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */
    - i; h0 R5 T9 O6 ]6 Z) l/ K- A7 |& _
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    & e7 W; v0 M: Z' m6 f9 s  U
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */* ~8 j3 u2 v7 n+ N8 p! X. N
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */! n, k, Q9 }) u1 H) w
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */
    ( q5 }" _4 E  r9 C! u
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    + S: v8 Q! w3 @, `! Z, c
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    2 Q* N/ g% B6 I# l4 F! y: m0 ]
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */1 [& T; _/ C7 B& ~0 {* _
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */
    & [$ N) v& m9 @5 t" J
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    , G. A' d; C3 Y# E) Z  [+ F- b
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  *// F7 K3 |) v7 r
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */
    . B9 `. v- k, Y, Z( y6 |
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
      I# Q0 t5 x, P  j( V
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    : ]5 e2 s/ B% ?6 z8 b; f4 L
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    ) M' Z1 Z8 h3 h# R) c  ]. A4 L! Q4 z% P2 [
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */
    ( p& k9 z. E* S9 P+ Q& G) Q
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    + e) H9 L$ a# n4 Y. V' O9 [
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    * C% o; J1 A: {3 d% v
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */
    ! z$ p# s0 r% y- f% J$ H
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */: i$ b! F5 Q0 H* f' w
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */, |4 Q& ?6 S$ h6 x1 `9 X! m! O9 I
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    % t- r- D/ X" X" ]
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    9 c' d& A0 F5 y- O6 b# @
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */
    ' k. X: W0 Z$ ^$ q0 H9 R
  30. } SDMMC_TypeDef;
复制代码

+ |- E) [7 a; V5 l这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
' y% `2 p9 `6 L- C' A: F8 A" C& @% [. z$ M7 z7 V9 w7 y3 I$ `
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
7 i( |; j$ a/ W% Z
; Z) p2 v: q' F' l0 i8 j7 o- ^% m
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    - j" `9 g# v' m% k0 b9 L
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
1 u* q  B/ }* n* k6 i0 U: v
下面我们看下SDMMC的定义,在stm32h743xx.h文件。" q6 g$ ^/ X# y2 {; k
) a: U' d8 w# \/ a9 b7 }( d7 o
  1. #define PERIPH_BASE           (0x40000000UL) $ F* n1 _- Y% x9 T; h
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)' d. X' B0 E8 k1 f8 O! R
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)" A. H6 S0 t( w" P) U* k

  4. 7 `9 P1 M& q7 b: _, x* _0 H  r
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL), Y; S# D7 q" |- \7 H5 p3 _0 N
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    ( }4 M: S: {$ _2 N

  7. ( h+ w- H0 z- Y6 H+ ?/ U5 u
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)2 E: z1 c- A$ x4 X7 O) r
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

# O' T2 ~; _( O* ]我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。
) X4 |# [2 D& k: h7 l+ O) }
3 y/ v* A) ?! h/ E. j87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
6 W: p, o; y) A2 m+ o' B下面是SDMMC总线的初始化结构体:
  ?) ^4 W1 e& }6 ]" g5 A% s1 [  w$ W3 o9 ~! K
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    $ [' ~2 I1 [* i5 T$ B) l! E8 u
  2. typedef struct
    9 y: E! D" H+ o5 v
  3. {
    0 q) _1 C( k; K- k
  4.   uint32_t ClockEdge;            
    : z' l0 Y, z' o7 U
  5.   uint32_t ClockPowerSave;      
    6 N1 x3 L$ @1 a1 p. E8 B/ [+ b& ?
  6.   uint32_t BusWide;            
    # ?3 a8 Y( _4 `3 X1 C
  7.   uint32_t HardwareFlowControl;  
    8 c. y4 n" _7 L; h9 [8 a* h% |
  8.   uint32_t ClockDiv;            
    / S/ f2 u  Y1 P+ X; T/ U+ q' Y
  9. #if (USE_SD_TRANSCEIVER != 0U)0 z$ J3 G6 P3 ?- H+ p' q
  10.   uint32_t TranceiverPresent;    4 k) j- T9 p' e& b  v9 Q# {
  11. #endif
    7 k$ I0 L9 A$ T! l- \
  12. }SDMMC_InitTypeDef;
复制代码
9 j- Q; i, z4 S; I5 c" j6 r8 ?" G* [
下面将结构体成员逐一做个说明:1 J9 d7 ], r) y$ I. `  P
0 E. b  k" b% d, i& M$ u9 m( Z- |
  ClockEdge- Q) z' G9 A2 Q4 q, I' ]' g
用于设置SDMMC的数据或者命令变化的时钟沿。: q" j3 a& t* i7 u% X' h
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    " V9 i) ~9 _1 f' v$ q( ?
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码
# c$ y; k. E/ _( [
  ClockPowerSave
4 c+ I1 s% i8 @6 {' O4 W! t用于设置空闲状态,是否输出时钟。0 c5 V/ L# V# l  E/ }* m' y
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)
    , w- n4 U8 Z2 T+ l1 b0 s* U
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
+ O) N+ w" w* l4 c
  BusWide
* x: ~! i; `# Q( h; a" @用于设置SDMMC总线位宽。
* y/ x% ]* ~; `. V5 Y6 \) Z$ O
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)2 b1 ~1 D& _! Q
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0
    3 A1 q, T2 u! Y1 R2 m
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

8 B- n; g- o' X  HardwareFlowControl
% D1 [. W) D% B' T' }7 e# R用于设置时候使能硬件流控制。' ]1 B/ s% ]5 K& }( t4 b
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)
    0 @+ ]3 F  b3 i- m4 l- p: t% Y& c
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

9 N) t  {) R# R; ^" D  ClockDiv
3 I$ b1 E1 i5 R3 n! Q8 ]: ]用于设置SDMMC时钟分频,参数范围0到1023。  c( \9 F7 u/ W5 b; p
+ r- E' p: Y- H' k2 O- A
  TranceiverPresent' V# ?0 ~4 n7 ]. X, C  w6 [+ x* H9 T
用于设置是否带1.8V收发器。
" j: W7 e* |  y" X6 U4 c
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)3 Y' s. R/ }* f; b$ f/ |8 H/ {* C, `6 u
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)
    6 n! m+ s" ^5 v: r& {, F  n( C
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码

% [" B$ z" g8 ?; T: z5 h0 ^- r3 P87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef' k( ]7 {- }% H
下面是SDMMC总线的卡信息结构体:
1 t/ _# w# \6 E- `; ]- B" c+ W
  1. typedef struct3 y$ N# f9 f% K& D2 x9 l5 d: A
  2. {$ U7 ^, B7 G9 M
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    . o# [) B: K( r. }7 n5 ?% ?& f
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */7 m/ z3 C* {6 Z# X9 v7 F
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */% T  e4 W- g5 j3 D7 X8 H+ R
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    6 Z+ c( K4 h$ I6 k: t( b: [0 e1 H
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    ! F, N+ T9 _8 M
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */" S( n# D+ W, g8 ]' q
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */5 H+ Y+ L7 F% G+ L/ v) e( Y
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    6 S+ |. r3 k8 _3 A3 ~
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */
    7 H- d* L' A7 Y: C/ \: p( G! a
  12. }HAL_SD_CardInfoTypeDef;
复制代码
' S2 J+ p$ M' Z+ k
下面将结构体成员逐一做个说明:
+ B8 e0 M0 a! b( j3 b+ W( w# z4 g& `9 m4 z8 g# v
CardType
9 M' G" u" D# [: `卡类型。
5 r: a# N8 O3 G  _
  1. /*!< SD Standard Capacity <2Go                        */
    & i4 ?! Y) a! d7 a
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) * }5 K# b8 f7 Q
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    * s# f9 I. L" O* C
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    & S+ ]/ U& {1 L3 T  l3 j
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

. ]/ E: u, ]2 p" Z! Y, I6 Y. A  CardVersion2 z2 v% M9 u0 g7 g) d- s
卡版本。* a' j8 W: W# f% U
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    * f" R# I* {* {! J4 q$ r
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

  }2 V; u* B: ^  Class
  ^! u4 J: i  b& Q0 F! h. c8 E卡类型。
3 |" P  P( `9 H) \( j
+ u0 V& y9 [1 X8 l  RelCardAdd
2 n  ~% a6 Y7 [. y! e  m! q2 Y卡相对地址。5 ]- [2 Z7 C  ]0 ^" G% H& X
8 m9 ^4 k3 n! g/ z1 j
  BlockNbr6 c' {5 `1 q% Z6 G+ o! T
整个卡的块数。, }2 B$ s0 a, {, C# p! M3 t% r! d
% [7 r' E- R  p  ^. c# V
  BlockSize5 ^6 S/ [2 T) y) }
每个块的字节数。
* V/ @* p1 b* c) K
0 M+ O1 O# M0 p# a5 L! `  LogBlockNbr$ {; ]7 V% `6 Q( H9 A! c% q
整个卡的逻辑块数。
* _% d. N2 ~/ S' U# i0 R5 K/ j1 Q' J1 A8 M  d9 ~
  LogBlockSize
" m# o3 [3 y) }# k7 W. |; Q逻辑块大小! @! w3 B) o+ _6 o/ w7 ~
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)/ P9 e2 z2 o% P; Z( V
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
2 y, y9 j% [5 `3 I. E7 S  I
CardSpeed& ?4 p( E& E% k7 [
用于设置是否使能SPI总线的TI模式。
( }5 E7 i% o* J$ C2 ^
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */2 d0 m: [" K/ s& _# X
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  
    ; z' ]3 O9 T  X8 b2 i
  3. + @0 [  @0 w& X! D7 K
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */ 1 U" ^4 C( Z5 p- s3 {  x0 @
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    2 R' j1 @( n* l1 r" A7 U0 ~- S  R% y

  6. & J) p. v4 K" }
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards/ |; M: g/ n" z8 \( ]. A
  8.      and <104Mo/s for SDR104, Spec version 3.01        */7 O3 m4 c9 F4 n# i( `1 D: k( k
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

" d( b) O5 U2 }4 o+ B& I3 x87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
+ D, K2 D& N9 h下面是SDMMC句柄结构体:
0 ?/ R; P! _  b/ {% D
' V' V2 S: |* A9 f8 |: U
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    ' G# I6 K2 T' F
  2. typedef struct __SD_HandleTypeDef! u' P0 k- e1 ^( y$ \* C0 K
  3. #else
    ) x! b; ]* a# l$ Y0 P7 j7 ~
  4. typedef struct, I0 O; y0 Y  l9 C2 o
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */9 M4 B9 ]" s3 o
  6. {
    $ ?/ R- \+ F% j. H$ Q/ A9 f2 D1 W, R; W' n
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */
    7 {  o# K+ [, Q% X4 o
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    ' l7 f$ f) ?& a% \; N9 @, a
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */
    " X0 f' P- c6 o' ^+ j
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */# O1 e  j6 |7 ^3 u+ l: r, p9 }, }: ?
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */
    - i7 _: ~: d, ?% ]( w% J. a5 R0 k
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */9 t+ R7 w( R0 Z$ w0 u/ d
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */( O4 q1 R8 U1 O9 x
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    ' f) A+ F$ M' O/ w3 A2 j
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    2 O) c5 \3 E7 s) V
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */  ?8 C& l$ _6 V1 @4 a3 y8 Y
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */: z2 V! I# @; k) l
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */# a) @' @9 C+ Y% I" }
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */
    6 |1 V" @2 D# r

  20. 2 Y0 X" B( T" B0 u" f4 T2 A$ q
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)& }: l" i: |% R, ~
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);4 m( {% b3 p5 f( A/ a
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
      v! G% E5 z: D, |  s: B. K+ J6 ^5 Y6 [
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);5 T! o1 o& B# i4 x8 J, T8 W
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);. w8 k3 ~/ \* Q! m& Q: [1 x
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);7 n9 Z8 |! t- d
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);/ W! R5 p8 i* E
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    * Z9 |) K8 n+ [3 g0 q5 J: y
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    7 W6 K! ?3 J% m* |
  30. #if (USE_SD_TRANSCEIVER != 0U)% [/ I9 p4 _* |5 o- ]5 j7 t2 Q1 Y# h- o( G
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);
    % `- V+ l5 m9 U. P  v
  32. #endif /* USE_SD_TRANSCEIVER */7 Z9 A  u; t! d0 Q/ c

  33. + c( [# ~0 d9 h% k% j1 {+ d% A5 Z
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    ! N& h7 D7 p; Z2 v
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    5 x5 h3 H. o; F5 j& Y3 n
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */6 r4 J  q" t8 T
  37. }SD_HandleTypeDef;
复制代码
" a, d, m# K! d9 g; N( O6 c7 f4 E( y' K
注意事项:0 ?- N: q' L+ j! @# ?+ I
; X4 y# c5 A+ Q7 l9 E' j, ~
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:6 e& l( l7 w, C, u

. {& [4 V: X, W9 c1 e  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
8 o. }* A% D, W3 b
) f0 D& a  x+ Y- n通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。) F7 l1 T: C( U4 F
0 b7 e. R$ t# L7 \# g7 D
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。1 S0 M5 ?. J: V$ V% F
7 V/ r8 B5 f- o) d' d: c' l
  SD_TypeDef   *Instance
4 B: ~: ^4 h7 e( B这个参数是寄存器的例化,方便操作寄存器。
1 N  M5 m: \1 g1 x8 T
+ ?3 ~% t0 c( c. Y$ A& J) ~+ w& N  SD_InitTypeDef  Init7 V' o1 V/ [7 R2 E9 H% v6 i
这个参数在本章节3.2小节已经进行了详细说明。
1 x/ k. ]- P; H* n' O: w* _% X' z- r1 L4 P- g$ r1 ]- O9 B
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c8 k. s& a" J  W* y/ f
此文件涉及到的函数较多,这里把几个常用的函数做个说明:6 d7 a) r1 b5 O0 s

' g& e9 R/ M4 Y0 Z1 d  HAL_SD_Init
2 Y. x6 Z; ]7 {% N& ~$ D6 I  HAL_SD_DeInit. K" W& D7 v$ A2 n
  HAL_SD_ReadBlocks
4 ~- w; m0 b) R  HAL_SD_WriteBlocks
8 N0 q! h0 e; r0 H  HAL_SD_ReadBlocks_DMA
+ c9 M6 k  Q$ D/ T  HAL_SD_WriteBlocks_DMA4 }! K: c; h* V" p# v& e: y2 a  |
  HAL_SD_Erase
( b$ t8 @7 y9 \8 D: z5 ~87.4.1 函数HAL_SD_Init5 D, t; V" l+ \! u3 A' `0 g
函数原型:0 i5 n. J4 }) e3 c* h/ b

1 ]  J3 C4 c0 D+ f% R0 m6 O
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    2 ^* U5 E) L. B7 T
  2. {$ n# h' a9 d# y7 X% q
  3.   HAL_SD_CardStatusTypeDef CardStatus;, p0 J: s! y! I3 I7 M& w* E; U4 o
  4.   uint32_t speedgrade, unitsize;
    " E8 W- X5 Q7 p' h! k0 u
  5.   uint32_t tickstart;
    9 `1 I# a) ~% ?) f9 \

  6. 6 t5 m& ^" q- i5 E
  7.   /* 检查句柄是否有效 */
    - y7 b7 W: c: e6 `
  8.   if(hsd == NULL)8 l* S& y  I- t5 p9 f. w, `
  9.   {3 E) }, M5 Y6 T; j% s
  10.     return HAL_ERROR;
    $ A: [6 P" g5 V5 ~1 T$ j
  11.   }2 A' \$ }9 d8 n. X) P) g
  12. $ c3 y  O$ @# e+ c$ {. b
  13.   /* 检查参数 */
    , S5 ]) F. S$ D4 o2 p# y
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));( l! |( S4 y' r. b% a: ]- A
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    ) a$ M6 c; N/ J$ Y8 d
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
    5 R) ^6 V8 F3 v) v2 e
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
      S0 j+ R+ F+ `1 D: L2 z& B
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));' o$ S, [$ O5 u
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    0 k0 p1 W7 i1 O1 o% L; L
  20. ' h. ]5 I% h5 ?5 t7 K
  21.   if(hsd->State == HAL_SD_STATE_RESET)
    # a( G6 |3 \; p* g+ S
  22.   {& v! X9 Z; S( a% }: {( p3 J: ^
  23.     /* 开锁 */9 l  g( v- {/ j' E$ |1 N. C) {8 ^
  24.     hsd->Lock = HAL_UNLOCKED;
    / f# x1 f! }/ O+ U( O9 S7 Q1 A

  25. , j5 j9 V& ?: Y0 s& ~* y
  26. #if (USE_SD_TRANSCEIVER != 0U)
    3 N& Z: T5 g+ H
  27.     /* 兼容 */( v0 a  M$ v0 R0 m/ l1 t
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
    5 L7 h4 A2 ^5 b# X% T- e
  29.     {
    2 n. K7 r6 |: k+ o7 ?" h* Z# ^! H
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
    5 a& \1 b4 I5 H( I  ^5 N
  31.     }
    9 B7 q9 b% W( N7 k- t5 O4 n0 n9 z& z
  32. #endif+ R" [" w7 T8 b9 U6 y
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    1 o7 y6 q" h- w( G! P8 F( ^% ?3 [
  34.     /* 复位回调 */
    * n# Q+ r, s6 ^" W$ s
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;- }4 B1 y1 r" }0 X
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    " L( {" ~3 K" Z2 D: y% S4 D
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;$ o, r4 i5 z, W1 Z: x' L' L% K/ F, t. o
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;( D- H6 E+ m9 m$ H$ D
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    ! }3 X5 B3 z& r, }
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;- [* ?( T8 \0 s" y( V
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    : P/ Z; c' x: Q3 H# Y4 S* Y: n
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    6 e2 A) R- v/ f+ ]3 Q
  43. #if (USE_SD_TRANSCEIVER != 0U)) q. x& q8 b" ~$ ^" [; y
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    - v/ c1 b) N3 C" @$ S0 k
  45.     {8 W' ~( N2 i4 f
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    4 c- ^, \9 E+ w0 J  G# b  a1 q& d
  47.     }
    $ K9 O& ]! P- w6 y+ s
  48. #endif ) H, K% D6 [* d( \3 [2 c
  49. " t- M. B6 t; q8 b* I
  50.     if(hsd->MspInitCallback == NULL); t/ C- @3 }4 Y
  51.     {5 T3 f' A3 O% |. K) W
  52.       hsd->MspInitCallback = HAL_SD_MspInit;( v! U+ ~" f+ \
  53.     }
    ) R5 ^2 T* R( I0 Y+ f2 _

  54. + d( R2 y4 r% O
  55.     /* 初始化底层 */, `  ~4 B1 B1 S% N9 a' B
  56.     hsd->MspInitCallback(hsd);2 u( H* \6 e1 a8 v. J. j- J
  57. #else
    6 j+ R1 Q4 C, X7 \6 a  o( i7 i
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    . _/ q9 V8 b* O8 K3 P% i* Q
  59.     HAL_SD_MspInit(hsd);# t8 A  O; X3 U) z5 D" ^
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS *// @1 J( @) O0 \, Q3 |9 b5 ~
  61.   }6 G2 m( d* B: w9 c" k: l* M1 T7 K

  62. . |7 B! g7 D" G- ], W$ k- d( q8 M
  63.   hsd->State = HAL_SD_STATE_BUSY;0 J+ k+ I( \. D; c: o8 H  |* c

  64. " v& t. h8 w; e, H5 k& e
  65.   /* 初始化卡参数 */& K* h7 _! }! t# ]5 f2 u
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    . U. m7 T! }2 b2 ^
  67.   {: c( G" U# w0 S! b8 K# @
  68.     return HAL_ERROR;* H; U  a  C* ]& ~; F3 P
  69.   }
    9 e: c  G1 s/ R
  70. ( u. ]; X0 U. B, _- q9 |0 H& F; v0 t
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
    ; ~" Z& p8 x0 T8 g' A
  72.   {. V; j$ F8 B" @3 i
  73.     return HAL_ERROR;0 l; C& z2 M$ ?: |9 }( {
  74.   }6 B2 w. {4 r1 h9 g. [& Z
  75.   /* 获取卡速度等信息 */
    . n; R, N/ I' e. z) ^
  76.   speedgrade = CardStatus.UhsSpeedGrade;* _: {6 o1 _4 Y
  77.   unitsize = CardStatus.UhsAllocationUnitSize;* F) f2 ?( c: q& `' F
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    0 ^, P+ H( x8 {& }) b
  79.   {  c9 X% J5 k1 i. L! l2 o0 `0 J' f
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;5 N6 v8 D9 j% w5 t& i
  81.   }
    % ?$ p7 T. z$ `6 R
  82.   else
    : E, a1 u2 M$ D
  83.   {# s7 p. w- Z9 S+ a  F
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)4 c; z  G' t. n
  85.     {
    + \+ X2 Y' r# _8 B, q
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    - [7 Z6 A  Y4 R; A- _! ^3 w
  87.     }
    : s; w( }4 w6 Q2 Q+ }) N
  88.     else
    ; G5 s; C' B# R& p
  89.     {
    / l+ b2 Y' _, s& ^8 _: ?+ |
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;$ U# G) f; C; `: z* o5 k$ ?* s4 d
  91.     }
    8 x5 C5 P. ~1 w3 T+ J. O

  92. & Y. @# D  M6 n) \- R. F
  93.   }
    5 \8 N4 N6 w2 D7 }
  94.   /* 配置总线位宽 */
      ]3 t( L& d% N( ?8 B! t( x, v- Q' o
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)/ A5 {. f! s, |1 v( p
  96.   {
    2 J$ ~( V( W, z" \' g
  97.     return HAL_ERROR;
    - j; M' C7 y- `. q1 z
  98.   }1 P! }* \- B3 a$ X& H9 S- V

  99.   e% v5 a! u% e8 k: c" p6 ^
  100.   /* 验证卡初始化后是否就绪 */- ^! m0 P3 v; o8 Q
  101.   tickstart = HAL_GetTick();$ W& g/ [/ ^* e: a3 p
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))% Y9 p; R! z6 J( [) n
  103.   {
      ?* D: {, S7 r+ v) ?
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    $ Y' o% u8 s0 j8 S& G4 m
  105.     {$ ~* h3 I' m% Y! g' S+ E
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
    ! M7 Z8 a' Q& r" x# d  G+ @$ ?
  107.       hsd->State= HAL_SD_STATE_READY;
    * s4 {( u, v6 |* l  r" \6 d  O: G
  108.       return HAL_TIMEOUT;
    0 o0 r8 v( r. r+ E6 H, i# _
  109.     }5 H4 R- {; M, S: [5 c" ]
  110.   }8 D( S; e- m. Y/ h

  111. 0 P. O1 K: i8 Z$ N. v, e
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    7 G! x/ m" f/ {& N

  113. ; ]. l8 i- |) w+ z: g: X
  114.   hsd->Context = SD_CONTEXT_NONE;
    , N1 q' E; ]5 C! ~9 _
  115. : u' Z0 ~4 y, q9 n) T8 R
  116.   hsd->State = HAL_SD_STATE_READY;: m1 D$ t/ B& @9 J8 l) |
  117. $ g+ Z/ n/ Z( d( w$ k- z
  118.   return HAL_OK;
    ) P. E0 N, ^% H: Y; _! Y. d
  119. }
复制代码
& D9 N0 M$ H/ b3 `4 o4 @
函数描述:
" y! U3 t$ M' T$ M
: B9 S* W5 `; `$ P& m. ?( c' v此函数用于初始化SD卡。
- H* Y  q1 y2 C1 U# @6 S6 H+ z9 W7 }* n7 {1 p
函数参数:
! T" P( q% e5 r' U" e
$ L9 B2 w% U; J* \0 l% x0 r  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
7 t; Q# C4 @. c; {  E# k  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
( ?$ R6 }% j2 K1 e注意事项:$ v' ], W8 I/ J
+ `! V! ^- G2 t% f5 p4 z( {; z
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
; ]' j; B$ l- F* k" s5 L! S2 V如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
6 h2 [/ M1 {+ m对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。: v8 n8 ?0 A/ p7 v3 M3 K
4 W! B9 I) J/ K* r" K
解决办法有三! ?8 @: |  @3 N! o% e- J* ]- d

+ N" O& {  i  U+ ?3 u" v方法1:用户自己初始化SD和涉及到的GPIO等。$ I- `! G. t6 F4 n; c

, I6 G9 g, v9 o& `方法2:定义SD_HandleTypeDef SdHandle为全局变量。
/ A9 w& M) n0 i9 }" G7 G+ c# C5 _6 u
' m  s" }7 S1 A. u0 S' C; o1 \1 T* u方法3:下面的方法& s) @7 X  E9 p7 ]2 c: ?
+ _9 P; o; ^6 Z) M3 m) y2 K7 x
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    ' M( E3 G0 ~5 K/ q$ C0 c
  2. {0 |  q0 y/ H6 G2 a  v" h
  3.     Error_Handler();
    ! [" X3 a4 U% {
  4. }  ; h; P* T1 ]7 J* w" K
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    8 G; g8 e2 v* Q& X( y
  6. {6 }8 l! Y) M9 M9 P! [
  7.     Error_Handler();' l8 p" J; @! p! C# j
  8. }
复制代码
4 w/ X3 Z: Z7 W6 b6 |
使用举例:; T8 f0 J% ]5 K$ J

" Z, Q$ h$ |/ G( @5 o: B. g
  1. SD_HandleTypeDef uSdHandle;% z  T8 h: r' k% U# p: M# P3 \6 e' O

  2. 9 o1 g) C/ m) N# g' t# t
  3. uSdHandle.Instance = SDMMC1;
    0 t: _& d5 S0 t. F! {/ R
  4. 2 }, _$ Y, T) |8 B7 O3 W
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock: t! Y- w- x( O. L3 \2 C2 [
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].
    + F: c8 U# M  S: C- t
  7.      200MHz / (2*2) = 50MHz
    * |; s0 o( L. g' |  z
  8. */$ G7 W) ?% `: ^2 `; Z1 v
  9. uSdHandle.Init.ClockDiv            = 2;
    $ c' P: f  Z1 K6 I; r- `
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    ! [! {& I; N+ O, i  e% s. e$ B
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    8 x; t. w" w) @
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;' x) |4 X0 x' r1 E. q
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;
      s5 M0 l2 c& ^* S, h8 _
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)# C/ _4 C9 L8 T( [1 [+ |0 V
  15. {
    2 a" T( i; _. R  p
  16.    sd_state = MSD_ERROR;( T! U7 D5 }6 a2 ?+ W  s9 ^
  17. }
复制代码
5 T: E2 c. B8 \+ i: y1 ^
87.4.2 函数HAL_SD_DeInit
. [5 _( q% f+ Q7 G: z函数原型:, S7 _$ h& ?: p' x# j+ m6 x
( O& G8 R# F0 g, ?
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    ! y" \5 J0 @" H% Q; U5 r; h
  2. {
    4 ~8 g4 G, X$ b3 q- [/ z
  3.   /* 检查SD卡句柄是否有效 */8 F' _- W3 d) Y5 i! ?
  4.   if(hsd == NULL); n" v8 K1 }, W) J3 z
  5.   {
    + ?# S3 `4 ]7 A4 v! B  w
  6.     return HAL_ERROR;$ t0 e7 _) s& z4 ^" I" _3 K
  7.   }
    $ C8 c! Q. n5 T* D3 y$ a

  8. 4 v( C& w( j) s! l
  9.   /* 检查参数 */
    1 ^* P! @# P/ o2 U1 H
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));8 ~. ^1 S8 T8 I) K6 d

  11. 0 u% p8 m$ Q. S. r5 ~0 Q5 f
  12.   hsd->State = HAL_SD_STATE_BUSY;: @" q% }4 i4 B4 A7 j( i
  13. * A1 u1 P. l7 S  V) @
  14. #if (USE_SD_TRANSCEIVER != 0U)
    1 t1 l$ k- Y8 T3 A! {$ {
  15.   /* 关闭1.8V模式 */, `" L; a  m3 I6 ^. z6 C
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    8 l; }+ z1 |8 e, R
  17.   {
    # n! h6 F& m+ x+ Q* P! o9 w6 @+ x# E+ L
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    ( J; z) T: M! _& P& j& R7 ]
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)+ f4 _1 N" q9 k
  20.     {
    , L' P1 g6 U% Y
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    : H( d8 _; _; ~% X$ }
  22.     }
    * e$ [1 U: H6 e. H+ M
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);* B3 N1 F$ D; r- \9 p5 _" ?, d) J
  24. #else- a0 N; k  ?- v+ g: W& S
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);  H# U1 h: i3 I0 g/ b& g
  26. #endif
    " Y  n6 G, I2 ^, e9 M5 r" y
  27.   }                                                                        
    7 O3 D: ]- H, P6 ?5 ~
  28. #endif
    , f  o/ S3 _1 x

  29. ( I1 |$ @: q  W3 y
  30.   /* 关闭SD卡电源 */
    1 t# G. T: x' y' R+ e# a  I, r7 f
  31.   SD_PowerOFF(hsd);! Y- S" i) F! ^2 D2 O0 V2 ]/ d# X

  32. 9 a  W2 o/ x) I8 B+ _& V* p
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)) W  x2 s0 A$ T/ h3 P7 O6 n
  34.   if(hsd->MspDeInitCallback == NULL)+ m  V' a8 u  o8 {
  35.   {7 D. m& U8 w+ k, [1 J( Z- x
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;
    $ v. {* m2 Z7 v$ o& h$ j, E
  37.   }/ A& z# g9 d% ]7 l% n3 g

  38. 3 t5 T: N3 g5 i  x& @6 I) W& D
  39.   /* 复位底层硬件 */. X+ Q& f$ Q. Z" x8 O
  40.   hsd->MspDeInitCallback(hsd);: e6 C' }$ q: h( C" C0 y* S' d
  41. #else) D- G" Z, q& \( |6 K4 j9 ?5 W# x
  42.   /* 复位底层硬件 */. K5 \. U* X5 r! t7 W0 n
  43.   HAL_SD_MspDeInit(hsd);( u4 k7 c& M0 Y3 z
  44. #endif + F9 d  I+ X- {$ A6 e4 D) M' d

  45. 2 I$ e+ k3 j7 K: L. ?% D; O: Z- c
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    6 H- W6 b. ~0 p! f0 I
  47.   hsd->State = HAL_SD_STATE_RESET;
    9 o* K" i: ?" A; T

  48. * S0 ^- Y; Y7 _
  49.   return HAL_OK;. J% h2 S3 P  P* ~& p- k
  50. }
复制代码
, q, f( `& I- Q* ^2 A
函数描述:
' T6 I. q6 Y( D6 f
8 Y% r# M! ?6 |/ _9 u8 T用于复位SD总线初始化。1 S6 A' M' W! x7 y- X

' r9 V4 f" N% J$ {% D+ B函数参数:1 A+ J) \4 E- V1 J8 U
0 v6 F) e+ k& ^; v
第1个参数是SD_HandleTypeDef类型结构体指针变量。
" @, b2 I; r& H2 K3 k1 X/ n  H 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
. l2 F# w  C( l( l87.4.3 函数HAL_SD_ReadBlocks) |/ Q- Z, h( c; m: ]$ m
函数原型:% F* ^1 U9 V* A
3 ]* z; n4 f  Y. ~& q5 Y. ^
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    8 ]6 d8 I# \3 v9 \, U/ ^3 p
  2. {
    - I( c9 Z9 e% e% i
  3.   SDMMC_DataInitTypeDef config;" o8 ~6 p7 [1 O8 C, ~& Z/ X6 x
  4.   uint32_t errorstate;
    + |" j& Z; z& B) M
  5.   uint32_t tickstart = HAL_GetTick();
    5 o* Z% D( {0 a2 Y3 E9 L. \4 b
  6.   uint32_t count, data, dataremaining;
    6 g7 d" L; z! D- a% m! s
  7.   uint32_t add = BlockAdd;
    0 d( g, }2 {8 x
  8.   uint8_t *tempbuff = pData;
    0 c. Z7 j; ^/ S# K2 v% v5 ]& Q3 ^

  9. 9 s+ [% J# f/ u8 _( i5 \- y1 h
  10.   if(NULL == pData)
    % Y" Z' \' K& p5 ~: Z/ l4 L
  11.   {/ i0 o1 y6 s5 z% k
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;: o5 p( G1 q. P  ~2 P, v0 H
  13.     return HAL_ERROR;2 q8 q3 [- z7 y/ q( O0 l
  14.   }
    : }; e/ b6 W4 l8 C% d6 }8 y
  15. 2 x+ U, J" z. `( w9 o
  16.   if(hsd->State == HAL_SD_STATE_READY)
    . o# K* \( x6 L  Z
  17.   {
    4 r8 K# j, ~3 y8 \6 i6 F# m9 @7 d
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ; S. O+ M) \/ g. u$ }

  19. - p! h  D" ?' i" o* k& I
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))* N* ^! O  U8 S
  21.     {, r7 S6 V! ^8 N9 V$ A
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;3 f2 |! |" p( @0 P
  23.       return HAL_ERROR;7 J0 R( R; J. L9 j
  24.     }
    7 @* i/ C' T. X$ W
  25. & v4 y; T( g6 e; D9 G# }
  26.     hsd->State = HAL_SD_STATE_BUSY;. a) E3 `9 O7 N% g- u
  27. 3 S2 K1 e- I4 i
  28.     /* 初始化数据控制寄存器 */2 _9 Q1 G/ u& }1 a* U/ y% W
  29.     hsd->Instance->DCTRL = 0U;
    - k8 z* q# j( F6 U
  30. + J4 w! j  F1 q
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ) b% A$ g. n) C  \1 W9 k' m
  32.     {3 q: a! U2 j, \$ S7 B
  33.       add *= 512U;! G9 V0 e* _* G, d/ ]4 t. I% [* m6 m
  34.     }
    0 X9 Y& J' ]5 y2 Y; Z. ^$ i; n
  35. ' M" g4 r' g% T' _
  36.     /* 配置SD DPSM (Data Path State Machine) */
    : |6 q8 G' l* E/ S
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    * P6 x) I5 J7 E9 w) T
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;7 [1 ]7 G$ f; h8 k. ]
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;% Z( r% u, M' |
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;. u' e6 X7 G0 }2 q1 F$ k% w( b
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;; M& N" b5 }5 Y5 B9 w
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;% ?$ t: a1 G/ D( F6 b& E+ G: N
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    9 Z5 E0 Z) Y, @8 q' u$ D% x
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ! w2 `! r; W; D/ k
  45. 6 k9 G: @* P7 b/ z1 g
  46.     /* 查询方式块读取 */1 C$ {' _8 f6 J: `$ T7 `; d5 K7 @  i
  47.     if(NumberOfBlocks > 1U)
    ) ?8 q; V# P; @% f5 e$ s" [6 D
  48.     {% ~. T# N* R# u9 z* W- p+ |( q
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
    ( m' K- F' m( m$ J2 {. l
  50. , A, n3 \2 v& T6 I
  51.       /* 多块读取命令 */' r4 d  k" a3 c' O' @5 b
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    / q# A3 {/ ^* g" O9 p" \
  53.     }
    1 L5 b' N  D! z4 W
  54.     else7 I- W$ e& o! {1 V
  55.     {
    ! m9 }  S  f, p6 {& z9 P- {8 r( e
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;9 n4 z% l3 ?4 @8 M1 A0 U* s. V/ O
  57. ( y4 U6 D! w( y7 Z% u
  58.       /* 单块读取命令 */
    5 f  a; \5 l4 {- T6 A
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);/ F  j5 O. B+ N4 `
  60.     }
    ' o7 v) X- M; n( E
  61.     if(errorstate != HAL_SD_ERROR_NONE)$ \7 q4 |* b! t9 |6 C
  62.     {
    ; m( X9 A. N5 J6 L/ Z" i
  63.       /* 清除所有静态标志 */: b) f  A1 Z! N5 t
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ i5 ]2 b: x. u1 i  J7 U) w! k# ]1 h
  65.       hsd->ErrorCode |= errorstate;
    ' M) R6 N( f/ t( c( c8 ^
  66.       hsd->State = HAL_SD_STATE_READY;! d+ \) L6 L  W% E- O" U. x4 O
  67.       hsd->Context = SD_CONTEXT_NONE;
    0 q2 t$ O7 f) f# P7 e" m/ t- ~
  68.       return HAL_ERROR;
    # k( v: W: i- x1 O8 f* f
  69.     }9 K  z+ G" l. _: J1 F& E

  70. $ z: T, z7 ^% O7 Z' a* ^8 _
  71.     /* 查询SDMMC标志 */. G- N1 z: b  L
  72.     dataremaining = config.DataLength;
    6 k& m: z, G4 _
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    / |7 z. m# g! J$ ?. r+ c/ g
  74.     {5 D+ G" f6 ?+ S$ C, k$ a
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    8 {: I6 c7 M  ]( h9 a
  76.       {
    4 S6 W' k* a8 x5 {5 ^
  77.         /* 从SDMMC Rx FIFO读取数据 */$ z8 Q8 n+ I% y& V, U$ p' I. q
  78.         for(count = 0U; count < 8U; count++)) }. o! A! |) F5 j9 R1 f
  79.         {4 G7 T" S  Q; ^
  80.           data = SDMMC_ReadFIFO(hsd->Instance);
    9 g! Z" A& K# `+ ?/ g7 [
  81.           *tempbuff = (uint8_t)(data & 0xFFU);
    ' ^% S" R) e0 U" P% i
  82.           tempbuff++;% C% Q  M% O" k8 [) ^9 M
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
    * P' n0 Z, I4 D# c' t4 B; A. a0 Q
  84.           tempbuff++;( d+ T7 K! }( P2 m% z3 }' c
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    : |$ ^1 R+ f# I# e- }. T$ V
  86.           tempbuff++;' h( d4 A1 ^9 e. |9 p2 s6 o6 ?
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);" o2 O0 W0 u$ B( C
  88.           tempbuff++;
    1 N: G; ^8 t' |% C3 N( A5 n
  89.         }' {- q8 V4 G; w9 i
  90.         dataremaining -= 32U;
    * Z& A9 J- U: Q4 U, ^
  91.       }' e+ M# @9 L$ b
  92. " `/ d, e8 k0 ^* {' A: _
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    ) V/ r1 d: Z* Z6 N) W% y7 w2 t
  94.       {" |, b" h4 c9 ~2 r
  95.         /* 清除所有静态标志 */2 V5 i  W$ o& q* J
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    . [$ M7 y) W3 n, [8 u; ?9 L% L: F! a
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    $ i- B- c8 T0 D( g! a% O1 g) A
  98.         hsd->State= HAL_SD_STATE_READY;
    / m* P- N8 q- y
  99.         hsd->Context = SD_CONTEXT_NONE;  D; t' V  L. l+ k$ G- Q. F
  100.         return HAL_TIMEOUT;
    2 U( U" X: i$ _$ f$ @6 h
  101.       }
    ( m, O" s7 r' r
  102.     }
      F% E( Y7 Y: f6 B+ L9 U" H2 P
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);- p3 C: C! ?' G; f7 x
  104. 8 p! Y& f4 N/ P; s. B* F$ Z9 h
  105.     /* 多块读取发送停止传输命令 */  c) g' t, |- l$ s+ ?
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))2 V# g" M" n) o
  107.     {4 c; h7 X2 @( l+ ]
  108.       if(hsd->SdCard.CardType != CARD_SECURED)
    7 h$ a1 P9 G. |- R' }3 t
  109.       {/ |8 ^. w1 b* j
  110.         /* 发送停止传输命令 */2 |3 F) C  c0 d. \6 F1 U; h0 c1 V
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    $ i. ^& o. C0 i
  112.         if(errorstate != HAL_SD_ERROR_NONE)- r) \( A! f0 N- [+ [4 J
  113.         {0 _( X) y* m2 |6 m! m3 R! b; O
  114.           /* 清除所有静态标志 */
    6 T2 H, K6 |" n0 b; O: j
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' \$ E. i* b8 S- f# @
  116.           hsd->ErrorCode |= errorstate;
    4 {6 [! G: V6 C# z0 \; d% E
  117.           hsd->State = HAL_SD_STATE_READY;8 H; @" H* C- i, C6 N, Q/ U# w
  118.           hsd->Context = SD_CONTEXT_NONE;, S* m% o/ @0 A) ]# ?* I5 Q# p" y
  119.           return HAL_ERROR;
    ' P: q, o3 R! j' `# @0 P3 h/ v
  120.         }% W$ l0 M5 A; a2 i& Q9 Q
  121.       }, W* X/ o2 e: V) ~
  122.     }; R# ]( G; a( S. x8 D- V5 K" a' e1 I1 s
  123. " p6 \* e  J6 |$ ~
  124.     /* 获取错误状态 */3 ~  M# u2 K6 a+ R; h% k/ z: r
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))- A3 b2 ]& Y/ K/ B. I1 U3 k
  126.     {
    3 ^" H4 ]5 y! F1 M5 D
  127.       /* 清除所有静态标志 */
    : s0 C% p- s1 O* t. }6 o3 i4 S. V% \. L
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);* K- \. q' N8 U# ~- u6 O
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
      G: i: Q! [9 Y7 L9 W8 _* H$ }
  130.       hsd->State = HAL_SD_STATE_READY;' S1 Q& V: T* J/ m. I  c
  131.       hsd->Context = SD_CONTEXT_NONE;
    $ D/ Y& n5 z' }/ H& I  ?
  132.       return HAL_ERROR;# ]2 _% M+ I  X% `! O
  133.     }6 c$ a6 v0 \1 H3 z
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    5 D: v3 w; U+ u' t% C2 |! H
  135.     {+ d, f+ T5 k# [8 ]* v, }
  136.       /* 清除所有静态标志 */, ^5 b  c! @* l" ]8 w( \- ]
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 I% a; I( d3 T  U
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    * b7 P" A3 N! g( ]. h
  139.       hsd->State = HAL_SD_STATE_READY;6 e- Z  K/ C7 n
  140.       hsd->Context = SD_CONTEXT_NONE;
    * o, }* H: D/ t& ^! P4 _& J/ P# K" Y
  141.       return HAL_ERROR;
    1 i& {9 S* c; G8 A3 v' r: S
  142.     }
    3 D: N' r$ M$ e# u. E4 Q( g8 |
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    $ w' B& {. K7 r6 l" L
  144.     {
    7 B4 O$ q- \- o4 Y, M0 c
  145.       /* 清除所有静态标志 */
    , g: V4 U6 Q" G; O, {8 A. e0 W1 [
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    - X/ Y2 w. ?, M: V+ P' D
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;& N' w4 ~5 Q/ N
  148.       hsd->State = HAL_SD_STATE_READY;7 \! I' f. d. i0 H* t( V
  149.       hsd->Context = SD_CONTEXT_NONE;% t/ s( M3 ?$ E3 T
  150.       return HAL_ERROR;1 y3 x% b$ V9 k; m; {; y
  151.     }
    2 g" x; b7 `+ @
  152.     else$ ^- U# Z; H1 ]. F5 x
  153.     {
    ' \$ h. [+ b$ V+ P3 ~
  154.       /* 什么都不做 */
    . }* u$ ~2 [! z! n5 F: y' j) W
  155.     }
      W9 w) ]- I, K9 V7 j: o. ]
  156.   v+ ]/ X1 C- }8 r/ O3 x- ]8 G
  157.     /* 清除所有静态标志 */& ^& m( S3 r2 Z: ^
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);7 G  K7 j" N/ q7 T
  159. * L0 J' W" t5 F# H( c
  160.     hsd->State = HAL_SD_STATE_READY;. L$ \; D! x3 B/ i) ]4 \3 x
  161. + f( e; C0 k$ z' @1 K$ @7 s' M
  162.     return HAL_OK;  X' O3 |; {: ?' ]) f* m( v3 \
  163.   }/ p5 u; |2 Q3 o7 h
  164.   else
    4 [: p0 K" b6 T; l% m
  165.   {2 g0 I* w3 g  R4 `  J
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;0 ^: I4 o0 x) w# B. i
  167.     return HAL_ERROR;
    & y1 x& _$ w7 K; C5 A( w
  168.   }) C, z; C$ ]* ~4 ]
  169. }
复制代码

, |( q% D. B/ F$ q5 _函数描述:/ v) l2 n6 V4 i& r: |
8 p  }8 w3 e$ t$ `# Z; e2 A/ V
此函数主要用于SD卡数据读取。
2 o2 O+ [! |! P/ X
. _/ y! l: W+ X1 Q2 I  z# k函数参数:
$ ]8 l) n) u" w( c
' h+ T$ R  z% S' {: `$ X  第1个参数是SD_HandleTypeDef类型结构体指针变量。
  T+ O; X, I7 o  第2个参数是接收数据的缓冲地址。
7 w5 J1 y% a! m  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。0 g2 c+ ^4 l" e- q
  第4个参数是读取的扇区数。- C+ x" D1 o( C
  第5个参数是传输过程的溢出时间,单位ms。) P$ [, W! p* r' r& J
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
& R% A" ^+ B$ Y3 ^3 M- l1 J使用举例:
" r  p% x2 x" y8 H' ]9 L( _! @
# w0 g: c. X! F) B9 l) G+ |
  1. /**
    0 E5 o$ b3 i2 z& g6 `8 J  |
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.# Q; q) t" L% y: c( u# T
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    ( H5 K  t; K' \% y( J3 O
  4.   * @param  ReadAddr: Address from where data is to be read
    ! K* t' Z$ v& _4 V, E$ R
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    ! J6 H# m) r# O) }3 G
  6.   * @param  Timeout: Timeout for read operation( j. r+ s, E4 k% Q. k. J0 i) q4 [
  7.   * @retval SD status
    ; g: H4 T2 U6 c' g; O
  8.   */) B" G  {6 z2 X% p* G( v
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    # v# {3 I+ k; A1 v2 S
  10. {9 I: V5 ^8 d7 Z6 E4 X/ }6 g
  11. 9 W  T+ z+ C6 h/ q$ J
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)) w" x% v7 Z) X+ L  ?+ L8 n
  13.   {. C0 Z: u6 e" x! j
  14.     return MSD_OK;$ y' u# @5 {5 i4 w
  15.   }( ^6 N* ]+ _. N
  16.   else
    8 o; [+ N' C3 r8 k
  17.   {! j1 v* j0 I. \0 K1 p% P- \# K
  18.     return MSD_ERROR;8 B3 Y, K: R1 `" M% ?: }
  19.   }! w) D5 X% l8 K& u$ l- d+ c
  20. ; ?( X4 h/ F2 l; b; s% b9 w
  21. }
复制代码

8 Z5 `$ G4 ]( R8 Q) t87.4.4 函数HAL_SD_WriteBlocks
, E! z7 I7 s& d+ C6 O/ t4 r+ m函数原型:4 z7 ~/ M/ k; R2 f/ ~
0 M2 w, V3 |: {- c9 u* N( O
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout). _# c3 W6 _* V- p: {/ Z
  2. {. D$ K- t5 X  k/ E+ o3 B9 s* u
  3.   SDMMC_DataInitTypeDef config;
    . k  o& _: {0 ?1 s+ H6 k
  4.   uint32_t errorstate;
    2 w9 W2 n$ n, z2 w* H+ \
  5.   uint32_t tickstart = HAL_GetTick();) T0 f1 W( k' r& C
  6.   uint32_t count, data, dataremaining;
    5 p8 N6 n2 q. K' _
  7.   uint32_t add = BlockAdd;7 ?* i8 }  d5 b2 T
  8.   uint8_t *tempbuff = pData;3 ~# e0 @8 j% D- V( N
  9.   |  Q* J. t3 P4 f
  10.   if(NULL == pData)
    ; n5 b: ]8 j6 ]$ F
  11.   {. J  j% S  l: h* M* k; i
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    7 X- r1 m5 T/ N: z6 z7 M* h- Y/ G
  13.     return HAL_ERROR;
      W8 c- U" S( t8 O: n$ N
  14.   }5 ]& b8 i% F# p

  15. - v  q+ g2 n0 m* f
  16.   if(hsd->State == HAL_SD_STATE_READY)
    . ^, {, N& K  U0 ^3 N+ U
  17.   {2 c" r. @, o/ W% E$ j- Q$ |: ~
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    3 s) f2 i& K; U8 X$ O# B1 B

  19. ' M1 P# X: g, _/ z0 d6 ?
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    $ c, J: H9 [& V) y
  21.     {. U+ \/ }" K$ n! E
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;: ~( G' V5 d2 k, F% I7 P
  23.       return HAL_ERROR;" k$ c7 F6 H" j! a) \
  24.     }
    0 ]7 N5 z1 |3 _2 Y

  25. , U3 o6 Q! W$ T% b2 D7 m
  26.     hsd->State = HAL_SD_STATE_BUSY;
    ( C( i6 X2 I  W4 y

  27. : D1 a0 x" H& l! y. i1 i
  28.     /* 初始化数据控制寄存器 */5 f" p8 j4 N7 M/ [) B4 i' q
  29.     hsd->Instance->DCTRL = 0U;
    $ s2 H" q  m. _$ W. n9 q+ D4 M5 n
  30. & R& W- b/ o/ n8 o# K8 Y6 c; B
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ; [* w2 M- Y% P/ {. Y3 F" z! C+ D: w" Z
  32.     {' ?1 o1 U  x; @$ Y" h  N. V
  33.       add *= 512U;
    7 x; O& n/ l" G# s
  34.     }
    7 q, e* j% c( S" w  k- E
  35. ! I3 Y( f% C  G% O- R8 W& Q
  36.     /* 配置SD DPSM */
    5 s1 K3 L3 q+ Z. o7 a' s5 i9 {
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    8 J$ L- s. P8 b9 c
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    / b4 m) ^: ^+ g  {: ?
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    ! a( @- H, t' t; ~
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
      q: {( E: D. d" y3 _/ @/ C$ j
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    $ W; C& q( [4 v. d0 t! T* F
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;+ a- o! N- W0 F, b( Z, o7 K2 ~% J
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    - l' R, ~# W8 f8 C7 e
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ( p+ u7 ?1 r5 y+ |& m, ]; a
  45. ! R  K1 Q* d2 G
  46.     /* 查询方式块写操作 */
    0 G" `6 w. ~& \9 N" B' I. \. \
  47.     if(NumberOfBlocks > 1U)
    " t1 Y& ]$ k/ l6 n
  48.     {
      }- J8 G, Z0 i8 C- v4 ?- b5 V1 t
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;4 e3 o% N0 @& j

  50. 7 T5 P0 w' J4 y* X
  51.       /* 写多块命令 */& b8 G( l1 g5 B* x/ N8 }" [' ], F
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    - r. p# p6 n5 U1 |: J
  53.     }6 l9 R5 r7 _0 a2 K' _8 K% U# V
  54.     else
    , N6 z4 r6 T9 \. t
  55.     {: o8 q4 F* ~- v$ B  p, m2 J
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    ' @  _) e4 p. L2 I; v3 O. v- T

  57. ( k- s& Z3 p0 t9 f3 k. y- f* _$ n
  58.       /* 写单块命令 */0 Y7 T) G3 F  A+ M1 z8 s8 m
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);' s3 v- ^) o8 I$ g
  60.     }
    ' m. O' M2 I+ t. K+ [# v- y" X# M8 W
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    5 v6 A- g7 \% o/ l$ e
  62.     {
    ) [( {7 U: S7 ?8 v8 E1 d, o
  63.       /* 清除所有静态命令 */
    , }, {% h/ ^2 M
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);; \, Y& _. \+ t9 r: p
  65.       hsd->ErrorCode |= errorstate;: x( B# B) o* C& o; i7 _
  66.       hsd->State = HAL_SD_STATE_READY;* w4 `2 B" T4 g$ S+ V* U
  67.       hsd->Context = SD_CONTEXT_NONE;
    + c) L+ J& x' }  M( Q
  68.       return HAL_ERROR;
    - ^" E# ?5 R, E) r! k
  69.     }
    % M; P, ]6 o! i
  70. 7 k4 a& h- D9 @) l
  71.     /* 查询方式块写操作 */4 j$ u& d7 p/ M! T) `* a+ B$ D
  72.     dataremaining = config.DataLength;2 d$ S1 e2 l, G- j2 I+ G
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))9 s) r6 T/ A* A/ Z: @
  74.     {* f) }3 `7 L+ h
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    8 |  L" y6 j2 `' z6 ]
  76.       {- K  ~: h" o8 f5 W/ ]! @
  77.         /* 写数据到SDMMC Tx FIFO */. T8 F5 I( T$ W, o6 }; O  u
  78.         for(count = 0U; count < 8U; count++)- G5 C. I+ B/ r/ d4 X
  79.         {" K5 V/ W2 ^0 z4 H  ]0 C. D
  80.           data = (uint32_t)(*tempbuff);( W( t& E& W6 s" A3 v0 \
  81.           tempbuff++;1 F" Q: J& Q) Q/ s  Z; B& b
  82.           data |= ((uint32_t)(*tempbuff) << 8U);# c) ]- @5 z9 g5 \1 v2 J8 y+ |
  83.           tempbuff++;
    . G+ G0 \4 N# s7 `" o
  84.           data |= ((uint32_t)(*tempbuff) << 16U);
    9 M. O% m+ ^% m+ d
  85.           tempbuff++;) B, [8 v  f6 |' P" Y6 J  a
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    ( b! _. k% ^1 I3 ~: x2 f
  87.           tempbuff++;
    - x) d. l5 j5 |1 C9 U1 `
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);
    + _0 t, {5 D$ P, k
  89.         }
    5 J* R0 u- g6 d2 m; V5 g$ c8 \
  90.         dataremaining -= 32U;
    . ~; W: D% q2 U: |3 e
  91.       }
    6 A7 `' M. D& \5 j1 ~! f9 e3 L
  92. 1 {$ v( e+ Z! H3 n9 c) I! L
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))- ?- G' l9 U* T/ \% ?1 S
  94.       {6 H' ?* J, L, P* d5 L
  95.         /* 清除所有静态标志 */8 L3 R. q' _: {0 S4 c9 p
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    4 X! F) R0 _& ~6 k
  97.         hsd->ErrorCode |= errorstate;# D9 g5 {: Z8 R. ]
  98.         hsd->State = HAL_SD_STATE_READY;
    . P4 z4 k- B$ T; _1 J
  99.         hsd->Context = SD_CONTEXT_NONE;
    # R" C/ P, P" \/ F+ u- Z6 Z# h
  100.         return HAL_TIMEOUT;
    , U* ~! ?6 e+ W
  101.       }
      M- ^+ h+ r, I: X4 E# ~3 ~
  102.     }- B  h9 T7 I/ {5 Q& F% M
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);0 C* q$ ?0 [6 C
  104. 5 {/ g0 d. p9 h1 b/ C7 I
  105.     /* 多块写操作,发送停止传输命令 */
    : b7 `/ `( O8 N# Q1 N6 h, z1 h3 L
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))1 E% q3 ]: X1 m3 r
  107.     {5 @3 Y0 i3 @0 g
  108.       if(hsd->SdCard.CardType != CARD_SECURED)$ T. H. N/ U. e: z3 G
  109.       {
    - q3 A! Y2 }8 B" |0 K3 f, [5 L1 t
  110.         /* 发送停止传输命令 */( J) j) ^0 _) ~+ T' S+ \& P# W2 z
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    8 {$ r- c5 h) [* G+ B# |
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    $ n" Y6 @! _8 K8 ^# g1 C
  113.         {
    ; K1 k. y2 q( _& X1 J( v" B2 V
  114.           /* 清除所有静态传输标志 */
    1 n) [/ I$ c. c2 c
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);/ S0 |% D7 `% H& e# g% Y7 P9 k
  116.           hsd->ErrorCode |= errorstate;- N/ l4 V. y( N# L9 j1 T0 P
  117.           hsd->State = HAL_SD_STATE_READY;
    1 s8 I9 O" J: ]. F& y+ ?& A) Q  q
  118.           hsd->Context = SD_CONTEXT_NONE;
    ( l  X: ~8 Q  H  C) F$ ?! P7 V5 [: y
  119.           return HAL_ERROR;
    7 x9 {/ N7 e  {8 B7 u# C
  120.         }
    / n  R; b: ~5 g) h2 j
  121.       }! q8 U. M- `  `+ U. d
  122.     }/ M* v& S, Z, q6 O' Z4 j) z

  123. $ d, u7 E2 E  w& j; T7 f9 Q
  124.     /* Get error state */0 X, v  R2 E' m
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    / d: a5 n+ P4 m  f9 F0 m
  126.     {
    . Z) q* P* q* |2 y
  127.       /* 清除所有静态传输标志 */
    ; W6 u/ W# [. |, M
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    & b; O) {* d' s" O+ m1 r+ [
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    ' T' ~* H' w- ?# n/ `" v: o
  130.       hsd->State = HAL_SD_STATE_READY;
    ! h  V+ ]# m0 j7 F4 C
  131.       hsd->Context = SD_CONTEXT_NONE;
    5 H9 A- C- v1 D: ]4 s) A
  132.       return HAL_ERROR;
    5 u. c  d6 V5 P* D
  133.     }6 |: ~& K5 |- i1 Q" z
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    $ y+ U. {! P# N$ E! \: F) B
  135.     {
    : w: B2 S* h$ N( A' c/ |
  136.       /* 清除所有静态传输标志 */7 a  [" q& }0 D% M& f2 g% x* d5 u
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 |( s' B7 s, q/ u' N* U4 u- F8 H$ q
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;9 k. h- }" ^! r' V) e( U
  139.       hsd->State = HAL_SD_STATE_READY;
    ) P' y9 O' w" d, a7 S' n9 e* ]
  140.       hsd->Context = SD_CONTEXT_NONE;! u2 a  R, P7 E$ ]3 {: ~! f  J
  141.       return HAL_ERROR;
    * g1 {- i% q) D# ]( }
  142.     }
    . \$ k7 V/ {7 }! K2 @, l8 q
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))  i% D/ v7 _4 ^. ~" V; G
  144.     {
    * x+ V* H6 |6 C: V! l8 U# |( Y
  145.       /* 清除所有静态传输标志 */# L4 c  U" w5 |' G4 V8 m$ f
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    6 R8 J: S" e! c
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
    ) K9 J3 ~0 P, e: ]) d
  148.       hsd->State = HAL_SD_STATE_READY;2 q# `' O3 N' |: R2 Y
  149.       hsd->Context = SD_CONTEXT_NONE;
    $ Z& v& D8 u6 o/ i% @
  150.       return HAL_ERROR;+ H  k2 }0 }- C( P3 g
  151.     }' w! Q7 ~1 B; b
  152.     else
    $ [. c! g" ]; G0 K
  153.     {; q6 b0 P" T9 {4 Y- v
  154.       /* 什么都不做 */
    0 [0 ]+ m7 A( u6 F
  155.     }" g2 P% n. e) G) \
  156. ! c3 o8 g& B* E* w# h- o8 t' {
  157.       /* 清除所有静态传输标志 */. ?8 s9 b2 C, E3 A
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    ; v4 g( ^- X' o6 o+ P
  159. ' O$ W2 Y1 f- _+ l) W
  160.     hsd->State = HAL_SD_STATE_READY;
    7 L9 i9 a4 {" M- ^# k2 s8 \( u
  161. ; e; E' f- N/ R* T- E; p- Y
  162.     return HAL_OK;
      x% w' l% \  q: a( [
  163.   }. {+ K/ {7 S8 e* {* h4 B# Z
  164.   else
    ( a- A2 P4 G& q; x
  165.   {; p$ D# e* {& d- t
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;6 O, {6 h" W' [( r
  167.     return HAL_ERROR;4 q0 K1 ?* \' c. L5 Q. w
  168.   }3 P4 m- H, B, ]) }
  169. }
复制代码
5 v, p5 c6 V- S  d! v
函数描述:
. `9 ^! H* g% m" s; A* G
/ c" Z. ?' @$ H* d3 y, l4 C此函数主要用于向SD卡写入数据。
9 l7 d8 w# [9 z& l  o9 l9 s1 w- @( Q! t' m8 c& r
函数参数:
/ F, B% ]/ D- B/ x4 K! O0 V' h5 \" N0 v
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
& ~) l' f8 q1 u# ^+ ]/ m+ v$ }  第2个参数是要写入到SD卡的数据缓冲地址。2 _, N1 L! s% c# @0 u" ^
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
0 {9 y) _7 @/ Z% {  第4个参数是读取的扇区数。5 V! T. ^, K) x/ J4 N
  第5个参数是传输过程的溢出时间,单位ms。
& G( U+ |! Y7 i$ r) U+ V' A  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。! n* J! @4 v5 p& }
使用举例:% [) `( @7 ?: T; |5 _/ v5 ^" W

# s: [: j7 z& ]1 i. ?" _3 W- M/ j
  1. /**
    3 R- N. U1 T' ~, d" c+ {2 B+ j  N
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.- g+ @+ m9 @* W* n7 U
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit* j2 V: W6 D- g/ @- _  Y
  4.   * @param  WriteAddr: Address from where data is to be written& k! q, |' G! u5 l+ Y
  5.   * @param  NumOfBlocks: Number of SD blocks to write  F/ {' w8 Q' M5 R1 |9 w4 L! u
  6.   * @param  Timeout: Timeout for write operation1 J0 j8 `$ G- u; |& H& ?( D0 q# T
  7.   * @retval SD status
    1 |# Z3 h  [+ N) h  x( L
  8.   */5 n! B" Z+ @! u2 \2 S2 y5 ]
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    2 ~: N1 b  ]3 n$ ^2 Y: `9 K
  10. {
    , C8 p& O7 N0 Q/ a( j* r
  11. . T5 m9 n" i: v
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)+ `% |( R3 E, T4 ]% J2 J( v, \
  13.   {# m0 u1 i- Z- Y, {3 x
  14.     return MSD_OK;
    0 F: C! w7 C5 R3 r9 t
  15.   }8 f% r. [* }0 F
  16.   else
      |) l' b3 |* V' o
  17.   {- ^1 |, o( L; M1 x1 ]+ e& F
  18.     return MSD_ERROR;
    5 o- c  l  e( S4 [# L1 M
  19.   }& n$ K# O1 R  o/ {# h/ W6 ^
  20. }
复制代码

9 c, Y. P' I7 W: o87.4.5 函数HAL_SD_ReadBlocks_DMA# ?! D4 ^5 D8 N+ h  g9 a" h
函数原型:6 |1 n8 n9 s9 }% O

* q) Y' h; X; G7 A
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)3 c# ?, t3 G4 f2 T
  2. {
    , m( I9 K9 K  M
  3.   SDMMC_DataInitTypeDef config;
    7 h$ n: b, H" k0 P6 v
  4.   uint32_t errorstate;# V8 j9 C1 I7 a) n
  5.   uint32_t add = BlockAdd;2 V# s6 o( C3 _3 f7 x; F  k
  6. # {( x* Q4 L% s9 }4 I  O$ G
  7.   if(NULL == pData)  @- q" A+ |6 f; W/ O
  8.   {) n; `+ j  s% g" w& a6 b4 F0 o
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;# `7 G4 F2 L  W1 L. n
  10.     return HAL_ERROR;
    1 B$ L+ K  M- A$ U% }; u8 c5 D
  11.   }
    4 f7 ?+ x" m4 ^, [) Y5 q+ ^

  12. $ S5 o% n: Y* Q5 B/ j% S( L1 n
  13.   if(hsd->State == HAL_SD_STATE_READY)
    6 d; V  @. [0 k+ r( C1 h7 b
  14.   {: ?" y! e3 H9 P
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;" A) G; w" `( M( Y
  16. , C8 E. Q! o) R1 y9 h8 M% L
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    / h2 J0 ?' L8 d( b# {
  18.     {+ R+ a2 ]  }0 P" L* T; U" i: q. n+ r
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;# Q8 F6 |/ G1 h7 ]
  20.       return HAL_ERROR;
    9 h! W: q0 m$ A! o
  21.     }
    - m# O% E; A( y. Q- a; K
  22. 4 d/ Y) _& i9 {0 C& c/ f5 _5 U
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ' x& ]: S0 x" l9 W; t0 y' k
  24. ' c7 p0 x9 k4 ~8 O6 w. g
  25.   /* 初始化数据控制寄存器 */
    , t8 h/ R- G# ?2 p) M, O
  26.     hsd->Instance->DCTRL = 0U;* l: A5 A& a; p; s3 _3 F
  27. 3 A+ v9 E# m' h4 n
  28.     hsd->pRxBuffPtr = pData;, o% _5 g7 s' r0 k' L* j, r& S
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;9 I+ E/ h$ {* g0 H( y) b7 g7 U' B

  30. * u) ]: q$ X9 z# r
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    - O" j$ U' ~; s
  32.     {
    : g/ G3 X/ L7 I4 ~" E: n% b% U% P
  33.       add *= 512U;
    3 B+ V+ d3 W  P9 n3 o
  34.     }% J$ \7 M" Y2 D0 I
  35. ' b. k+ J3 S0 Z' n. v+ @- N2 L: f
  36.   /* 配置SD DPSM (Data Path State Machine) */: o# {6 m% j1 m- W% G" r
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;/ D- O3 ]9 j7 S" v8 P7 w; H
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;' P' |  H/ F: b2 q- f* f: E
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;, A" G( c; G- y7 a9 R
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    " `, Z3 f" [) V5 [# n2 L2 j
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    : H, p: x$ b  F1 t/ E! W
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    . ~: ~) M/ y1 `( R
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    * P9 P$ Y% @  {1 c8 [

  44. & f$ K7 k( c% k( F% Y) d6 G
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ( a; H# t/ y% e, O+ z; |
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;+ F/ Z, ~: @( Z0 U* J5 V
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    ! G: E9 p( O$ }0 Q% T

  48. $ W4 L8 f& P. i3 K) ]6 c
  49.   /* DMA方式读取多个块 */" }: A) ?; ?1 N, p  X. S( y) `
  50.     if(NumberOfBlocks > 1U)/ i+ x$ a( j2 N( X8 v! E7 r# L
  51.     {: R; B( C" b' D) j, H, H9 Q
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);2 \! ]8 I3 z. [; a/ A. y

  53. : o, L% L  n, `9 S/ f3 x
  54.    /* DMA方式读取多块命令 *// t, P- W: ^1 S) A7 Z: G
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    9 v, [: C4 \* N6 i7 N* |
  56.     }
    : S# K( N+ U& J; z( W+ w! @
  57.     else# k. n6 o, H( R' ~" ~
  58.     {* F) T7 o$ |% a! q
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);. W7 w9 \1 ^& w: l' l6 S/ x# `5 ]

  60. 8 d/ \) O" {& T) ?" J
  61.    /* 读取单块命令 */. S. Y1 Y/ B: A
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    . f; s3 F& n( r+ \" r/ ^
  63.     }; p; L! y. ~' d: o8 ~$ o
  64.     if(errorstate != HAL_SD_ERROR_NONE)1 X6 }/ z' D' {- i6 s: V
  65.     {
    7 D0 j+ o9 E* v! m! W% E
  66.    /* 清除所有静态标志 */
    3 j/ z; [" w- X; I
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ! G: `2 n7 K1 J7 |7 F6 n
  68.       hsd->ErrorCode |= errorstate;
    + n/ ~  q0 b  t" Y5 m  s
  69.       hsd->State = HAL_SD_STATE_READY;0 M- Y8 t  A9 O$ R
  70.       hsd->Context = SD_CONTEXT_NONE;
    3 V0 I$ [* {- B' Q, C
  71.       return HAL_ERROR;9 C. U% H, l, r2 {- t1 u, j
  72.     }
    & O/ B+ l' v; y1 `( a2 B) K: K
  73. : e" T! o" @, S* C+ e9 i
  74.   /* 使能传输中断 */
    ' U" J* _: R* Z- V* |$ j$ h$ B
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));5 f. U, J' X4 S5 K) k7 o, \9 d6 {
  76. 2 B) H8 O& L( D) K4 V8 P

  77. % o$ Y& O" z- Z" b# X
  78.     return HAL_OK;
    ; ]/ c3 a0 Q& W' l' i8 @
  79.   }# q6 c9 @* u5 G9 K5 r# l& O
  80.   else) K# ?$ {- E  }3 b2 ^1 X
  81.   {
    0 @) ]) r" g7 I( R
  82.     return HAL_BUSY;
    ) c. N4 S9 F! |) i7 N
  83.   }
    & C, I: f' z# l7 D* T
  84. }
复制代码

9 ]+ s, e. Y! y- t函数描述:
. h( e3 _9 k# m' o; J/ L: f# v! w! V
此函数主要用于SD卡数据读取,DMA方式。
; [& g8 q& Q" c8 }% @8 w& N* k
0 m/ |6 V4 z& o( i0 H. V( D- p7 }函数参数:: a& t0 N6 B0 b) ^' w7 X  u

* M9 @$ D4 P! ^% T. ^  第1个参数是SD_HandleTypeDef类型结构体指针变量。
4 g) s. S% R7 U% _/ q  第2个参数是接收数据的缓冲地址。  j- A1 K8 o& K6 Z- n, ^* V* n
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。  h3 K% F" K7 A; c# X
  第4个参数是读取的扇区数。/ y+ F) d8 o1 g
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
& A6 u5 g- Q1 ^6 O: F使用举例:
7 Z( r1 g: H+ b3 Z2 z4 K% {, N: F& z1 w% X6 M' U, L( H7 ]
  1. /**
    6 P0 E1 C, X* F. `' o
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    ) Z; Z$ n  ?" t( T( X
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    . ^& Q, W- Z, l2 n" w+ W
  4. * @param  ReadAddr: Address from where data is to be read2 w# t# F0 j7 y
  5. * @param  NumOfBlocks: Number of SD blocks to read& L7 A- O9 Y; R
  6. * @retval SD status# w) e2 ]$ Q; B& [  F
  7. */; U! ^5 f" y, b
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)( Y! I9 J( v2 |3 B9 E6 B# P7 r
  9. {
    : P1 }; z. A9 M: [' U
  10. - n2 k6 T. R2 Y  S# I7 |' }
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)# ~4 H+ q" O& D% R; w/ V& H* e, w! Q
  12.   {3 {% y. q$ P7 `( V! I$ W
  13.     return MSD_OK;
    2 o: Z# ^3 S6 w# @4 {: D7 _
  14.   }
    + @' c6 R1 K" n6 p/ t
  15.   else2 N( m1 R3 c9 K# i8 T8 t
  16.   {8 J; P$ e) c) Y
  17.     return MSD_ERROR;  S6 z2 N  u: U2 Y4 H
  18.   }
    7 ?# j% t  L2 f4 u6 n3 b
  19. }
复制代码
' O/ t1 F% a$ H$ |$ R0 [8 f
87.4.6 函数HAL_SD_WriteBlocks_DMA1 T# x: t3 K: [- \" c7 r9 n. ?
函数原型:) s$ |, P6 a9 N6 N. p( i2 T

* o+ Z0 B8 N' |: V6 a' B" |3 J
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)0 a3 R* A% O' J1 F( x1 i: T
  2. {! S. J$ |; m9 v5 z' S2 q0 E! N* D
  3.   SDMMC_DataInitTypeDef config;% r3 R" e5 l. u1 b* O. B1 r) E
  4.   uint32_t errorstate;% x9 H' ?8 o/ K" d/ Y5 \" x
  5.   uint32_t add = BlockAdd;, @( B( o& Z/ q7 e* X* v& W
  6. 5 ^" R5 u- c3 A
  7.   if(NULL == pData)
    % D" N5 `2 m5 B
  8.   {
    ) u( q# ]/ `' b' A8 I4 z
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    1 J  ~* }/ ]8 s) L1 B3 p' Z. V7 N- l
  10.     return HAL_ERROR;
    8 D0 Z3 T. c( A" R/ f
  11.   }/ i$ r9 i& P0 J( v% p( A/ h) x2 `
  12. 1 g) Q% M  I! a6 g. K
  13.   if(hsd->State == HAL_SD_STATE_READY)
    9 O) i; I0 ^. Q4 O9 {+ X" ~, a
  14.   {  L+ N$ Q, Q; E) a
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;. K: W) ~+ j) n/ B/ e' X0 i
  16. 0 \; v; b1 B0 G8 A7 V  X
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    . f( v: ^; A4 t, f
  18.     {) c3 }/ D; a3 D
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;' x6 l6 ^  ?' @9 z3 s. L
  20.       return HAL_ERROR;, \2 ?, a3 t/ W
  21.     }. U6 M2 J3 h5 }! z+ ]
  22. ' V# m; V5 b1 X0 X
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ( [9 T% N; k7 u9 t2 ]  a) e

  24. ; j0 F+ x2 a; E' U9 o5 l' a; z0 D
  25.   /* 初始化数据控制寄存器 */
    2 d0 g* B( }8 f9 S
  26.     hsd->Instance->DCTRL = 0U;/ J% O; \2 m) Q& U  O' ]
  27. , j# f% ^5 y0 e5 i. A
  28.     hsd->pTxBuffPtr = pData;( i0 c  u5 O$ q
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;" o. Z. z9 [7 Q6 T$ S' _
  30. ! l) s" u$ k% u/ M, u5 D
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    6 R6 Y. k( X, ~* \1 C( D$ N
  32.     {/ S. S* a( Z6 z% V. X0 D# Q" c
  33.       add *= 512U;5 b7 Q+ g  F+ U! i* a3 c
  34.     }
    ' `: P- n7 ~! x4 r  p' i8 C

  35. 6 {  v+ C3 [* N( `) Y
  36.   /* 配置SD DPSM (Data Path State Machine) */
    " _9 G# ]1 h3 i7 y
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    5 Q$ e# o2 E6 H3 a1 ^" }& l
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;$ I% B$ }2 G6 t0 w
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;+ }2 v) Q0 @$ \* y0 K4 f; s+ T
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    ( }$ D! X% u$ ~
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    # n- y7 ]4 M0 u4 W+ O, l& c9 a
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;. t  `2 x; a/ R
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    & q: U) G9 \; U/ B% Y# g( i3 m: W

  44. # J2 n- F  F. X

  45. 0 y" K- i. \6 O
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);( a! }& q- p* Q1 P5 E" D! ], E

  47. 7 S5 B; a& p3 [4 R# V( h$ Z
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;& Z9 |+ S1 b6 `; S. H8 R
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;, ]2 P( D5 `; R
  50. + o* o4 C# |$ `; \: Z
  51.   /* 查询模式写块 */
    ; J& W3 S5 f1 m0 H
  52.     if(NumberOfBlocks > 1U)$ F, \4 `! Y5 m1 O
  53.     {* X$ R+ T0 V; R
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    - d+ w0 ?9 B9 H( J6 m/ R8 V
  55. 7 L* Q- p% V/ F+ s; [8 B5 ?
  56.     /* 多块写命令 */
    + r- Z& c% x7 r
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    / c5 a$ h+ M5 l2 o; X7 Y" D/ h
  58.     }+ H; g3 a9 l1 }7 R9 G8 _
  59.     else
    8 s: f# Z1 m, F+ \5 F( V3 M; p; w
  60.     {
    3 X  ]* S6 T( p+ B
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);+ B4 X: q8 h+ R8 V& E! Y7 G9 @

  62. : G# O8 n( K1 E! Y
  63.     /* 单块写命令 */
    0 F, F9 r: B- y" m) s; Q
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);9 U& s% y. M; g1 k: A, x, b( i1 K
  65.     }
    * O& C8 X1 O' K; ~; K1 Q
  66.     if(errorstate != HAL_SD_ERROR_NONE)7 {; p$ W7 J/ L6 M3 k, {- I! J
  67.     {
    0 v& @& k5 r( o# }, L# _
  68.     /* 清除静态标志 */9 V' P0 Y+ X0 G9 b: }, s4 y
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" K1 v. O# i: x5 S6 K2 L6 F
  70.       hsd->ErrorCode |= errorstate;
    * v7 F% _0 n. e: Q9 |, F4 H: N  M
  71.       hsd->State = HAL_SD_STATE_READY;. u0 t/ G% h# b* h+ ?& h
  72.       hsd->Context = SD_CONTEXT_NONE;
    8 {% o1 ]3 C* L% j% }$ ?9 w# t
  73.       return HAL_ERROR;
    ' X0 L5 y' I5 F( J- ^& I- e
  74.     }' r* X0 r  L/ l' r! P& q9 ~
  75. 9 f8 b( z+ F7 c, i4 C
  76.   /* 使能传输中断 Enable */9 W6 y; w7 o4 G7 a5 b1 ^
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
    / V1 j2 C* e0 d, ^; S% W

  78. ; L/ U$ s0 v7 n# t
  79.     return HAL_OK;
    1 K% o8 C) ?9 W
  80.   }
    ) X6 e+ \: P+ q# ?6 K9 ^. h: _4 L
  81.   else
    . A/ W! S; m* C
  82.   {
    . C2 O- K$ m3 l# S) C. r; d7 h
  83.     return HAL_BUSY;
    4 F3 p2 B' x" \
  84.   }, t" `) i# H+ W; `" E
  85. }
复制代码
* y$ L- i+ P/ [
函数描述:- j) J  w+ R# E- H
. v" N1 {9 _' ]0 R9 }2 s' D/ e1 u
此函数主要用于向SD卡写入数据,DMA方式。; _0 Z' D" @6 A/ z0 }' P

* b# m0 @6 |. y8 w8 h0 C' u6 `函数参数:2 i1 q; L; v. g3 T. G4 n% N

0 t  Z- J$ X1 _  第1个参数是SD_HandleTypeDef类型结构体指针变量。) J8 l$ ^; X' J
  第2个参数是要写入到SD卡的数据缓冲地址。
) l8 u0 `, F  a% p; _% S5 B  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。2 v. B$ i) w6 e& N( A: p
  第4个参数是读取的扇区数。8 ]& s* f! o6 b% E% J
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 r1 }' |3 W9 C! f- C
使用举例:
+ P8 t4 c# x8 V: a$ K4 b0 b
# T, ~8 _: V3 y* S0 v: Y$ j
  1. /**" V0 C" C6 j% F4 X5 D, e5 F
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.+ q& Z) w3 F0 \% W/ b
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
      W* a/ a0 {! Z: v
  4. * @param  WriteAddr: Address from where data is to be written
    $ @% R2 G5 F. Y# a# `
  5. * @param  NumOfBlocks: Number of SD blocks to write
    - b* V7 `/ a/ u& l
  6. * @retval SD status
    5 l5 v6 C2 @; q& O. Z
  7. */0 G% c% h; e$ v5 ^& K: X" m. f
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    / o# }. C. O: @
  9. {) H4 D. h5 P* I1 m) O4 @
  10. 0 D6 M# m2 x4 R* V, E) s7 G! d9 g" \
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    2 V% I) I7 j( Q$ T, X9 q& |; \
  12.   {
    , J9 k- i2 \" \0 {
  13.     return MSD_OK;9 s& h1 E, ?) o8 w- k
  14.   }0 X1 T8 ]" _6 G) q7 k/ ?
  15.   else
    2 {7 Q% X! A8 X1 K! N, B
  16.   {
    ; c. k3 a: Y5 r. A! R: e/ \. I
  17.     return MSD_ERROR;& r6 V6 _2 ^" R+ l" }5 ]
  18.   }
    2 M; w8 S7 _1 l/ m; D* w
  19. }
复制代码

' H3 [, B8 K9 J, \0 K87.4.7 函数HAL_SD_Erase( a, S0 |' y/ h: X+ T0 n2 p0 C
函数原型:
# ]0 n+ ?) Z. }7 A
! q# ~! Y- c( R' s" B/ p
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
      _9 `+ Q$ A4 S; K; Y
  2. {8 V# u2 F( D1 E) Y& }/ a; O7 N7 D
  3.   uint32_t errorstate;$ g: Z8 A; J3 d; P; z  O3 e* ?
  4.   uint32_t start_add = BlockStartAdd;4 n% c+ B, l: f! y% i
  5.   uint32_t end_add = BlockEndAdd;# [% v' o/ x$ i' }4 C
  6. ) Q# ~+ S9 y- x/ [0 ~# `
  7.   if(hsd->State == HAL_SD_STATE_READY)9 Y" Y0 G8 }0 v3 q& H
  8.   {: ^5 L6 w. E7 b" p
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    7 z1 T+ V! |1 x+ I" @
  10. ' t8 Y2 v. Q( w2 U# |% ~  K# s9 D2 N
  11.     if(end_add < start_add). j4 e' w0 G; h0 }* b/ ~) _8 |
  12.     {
    1 O0 Z7 N* i" L/ Q, k
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;9 V# B6 O0 j- X( ?6 L3 M1 i
  14.       return HAL_ERROR;7 r# o  q/ r8 a1 G
  15.     }
    ( P  e% @# }5 B5 ]3 d' p; L) d2 }

  16. . p, @/ v. j- S  M9 X5 z" }9 f
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))# G6 Y  ~, e) ~" I, J  L# x0 u  j7 C
  18.     {
    3 B+ G: u* _6 c, q  x
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;5 e! M  @0 f# ], d
  20.       return HAL_ERROR;
    $ T4 W5 h& S- ]. [: O, B$ K
  21.     }( E" V+ Z( i1 A2 s; Z3 s
  22. % \1 k5 j9 R  p2 ~
  23.     hsd->State = HAL_SD_STATE_BUSY;
    6 b* x/ |5 F6 a
  24. 2 w0 Z9 p3 f$ u) I) I, q- m6 E/ f- a
  25.   /* 检测是否支持擦除命令 */# h7 O1 [- p/ }" A$ Z! o; i
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    5 x( L/ p5 ~- @. i, P3 i" {; i
  27.     {8 V/ x7 j/ }" P3 z0 V  Q
  28.       /* 清除所有静态标志 */- C0 A1 ~) Y) _" B; ?9 i
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);% ]2 z* f; C/ ^0 Y4 X
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;/ _; V: g1 p1 i4 F
  31.       hsd->State = HAL_SD_STATE_READY;! `! C1 \  t1 |; K7 B' |: ?9 ~  Z9 }
  32.       return HAL_ERROR;3 U* p3 |+ K/ @+ ~$ t/ I" q& A
  33.     }
    / K+ l' u3 G. z8 F1 S2 q
  34. / w( \7 d- f4 P" ?( R  J9 H+ N& W
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)) X5 q* K" D3 g  l0 k
  36.     {8 z  d! I9 D7 S5 M
  37.     /* 清除所有静态标志 */5 L) w# v8 k; i# J
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ! g, H, J) g9 \( B+ L/ y' Y
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;2 `/ _0 e3 H% A
  40.       hsd->State = HAL_SD_STATE_READY;' u- D; P) g& D6 ^- h/ f$ A! d
  41.       return HAL_ERROR;
    . q, F0 x2 w* b8 J
  42.     }
    9 p. T3 X; u4 |6 r; H( a% ?
  43. : F+ `3 X( t# X
  44.   /* 对于高容量卡,获取起始块和结束块 */, ^# C& H' u* p4 Y" j" Q9 P
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ( E5 }: T5 W) ?5 W" x  X$ p+ C
  46.     {
    : k3 x1 y" T. J/ r
  47.       start_add *= 512U;
    ) F+ o$ ^4 {  }
  48.       end_add   *= 512U;
    % w( U" F% v' o9 |) h" ~
  49.     }( \' w' _, T- T% z! d! z( s
  50. $ V+ X/ P% l& [
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
      V% g2 ~$ {& |& a$ Y& Z5 A! S  v
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    ! F0 L/ @* r  I5 M2 G- _& K, h" Y
  53.     {# V4 V! `( c; T* I, b+ @, T
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */7 I* w# M) i% c
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    7 O9 R4 ?# T! |$ {- ]
  56.       if(errorstate != HAL_SD_ERROR_NONE)6 d3 n4 W4 t/ U9 W5 J2 `: E
  57.       {
    + {; c* G& v: c
  58.         /* 清除所有静态标志 */1 B- O7 D5 a7 s" K, M3 c
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    * f' A0 R% `  ^  u1 n
  60.         hsd->ErrorCode |= errorstate;
    / j1 N  w6 ]. A" t# h
  61.         hsd->State = HAL_SD_STATE_READY;
    8 i1 d1 @- i) |6 o+ \( v
  62.         return HAL_ERROR;& ^/ x) x" L2 Q; d1 t
  63.       }
    5 G; S, L8 [) W9 \9 x5 R

  64. % _" |8 j* }  `1 s' e- x  I- ]
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    ! N1 M0 B% u9 R% {2 u
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    3 V. v3 `  F, _
  67.       if(errorstate != HAL_SD_ERROR_NONE)4 W, O" U3 v4 \% h3 Z9 ^4 {
  68.       {! ^6 n' u- H5 d+ d7 b
  69.         /* 清除所有静态标志 */
    / ^2 q6 F  l) _7 u9 b
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    " r' G/ R$ z1 \
  71.         hsd->ErrorCode |= errorstate;
    , m9 O/ m: X' Z% j9 T8 l  e
  72.         hsd->State = HAL_SD_STATE_READY;
    ! _  A: X( \  k8 F, z2 @  C
  73.         return HAL_ERROR;) h- d4 q. Y! `# h0 D
  74.       }
    / Z: X, w' {8 r7 E
  75.     }$ ^- Z) U- a8 T& n. [
  76. ; `- i& }6 ~8 i* f/ Y5 f
  77.     /* 发送CMD38 ERASE命令 */
    0 b' M$ u5 l6 n! f, V4 F  z
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);+ I& e9 f' u% x; I) U4 k
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    # a) s8 W6 l7 K5 F4 }
  80.     {: L7 @4 F7 s/ g! c8 n& X: H0 G0 K
  81.       /* 清除所有静态标志 */
    ! t! j0 t( X/ U4 L' `
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ) ]' J9 M6 ]3 ~; D+ B' p1 B
  83.       hsd->ErrorCode |= errorstate;
    6 t" ^& F3 @0 s4 ]: A/ \% A
  84.       hsd->State = HAL_SD_STATE_READY;7 G. E8 o+ f/ C/ b6 @- w: a2 r
  85.       return HAL_ERROR;% @9 [5 H  Z+ ^9 \7 U, I' I
  86.     }3 |5 T$ T/ B  m2 h: i
  87. # r) R4 G- j5 T6 P2 T5 U
  88.     hsd->State = HAL_SD_STATE_READY;
    0 ]' d1 k7 Y' V0 C' ]6 i' S
  89. ' P! F; L- z& g
  90.     return HAL_OK;
    ! o! B; @4 t5 v
  91.   }: N0 l5 Z9 P, Y1 M' n3 h$ {
  92.   else- O$ T* J' D6 n( S1 L$ j
  93.   {( l$ Z  L8 r: ]9 k
  94.     return HAL_BUSY;  Z. ]: p7 [  B! k0 i5 b
  95.   }& c, y: t1 c0 o
  96. }
复制代码
/ g) Q6 ~* [% D, ?
函数描述:
  i2 U, ?6 E5 A8 K3 C
) z+ o8 M0 a* v) p1 j8 B2 A此函数主要用于SD卡擦除。
* p" J4 P$ _3 K- W' @
/ ?! Z) t2 b4 S3 K# Y5 {8 G0 ~函数参数:& ~" l: _, m2 e% Z) I% A
  M- V/ ^$ m0 s3 ?! U4 Y: Z& q
  第1个参数是SD_HandleTypeDef类型结构体指针变量。/ b# K& i* X3 X( A, r) O% T
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。  {- i( _$ [2 ?2 O1 t: y. m2 ~* m$ ^
  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
5 y$ t, t* m5 l- H  |* r  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。: f  i( i$ Z, P# N7 s# }
使用举例:
8 T) N% \$ [. D1 q
6 F% P+ R) {( E7 x
  1. /**' Y! y* a9 D1 Y" I1 M$ U
  2. * @brief  Erases the specified memory area of the given SD card.& K, y' A# E* h1 K
  3. * @param  StartAddr: Start byte address
    1 R2 ?- E4 M+ |: u7 e; O5 h
  4. * @param  EndAddr: End byte address0 S5 V$ f. X  y' b
  5. * @retval SD status9 w5 E. t( ?0 e  u$ q
  6. */) M" j2 e! T: C3 F( z
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)* D- x. T1 ^# g- J/ u+ @
  8. {
    ( @0 R/ g/ x6 f: L4 F

  9. ( b' I! s+ y7 g" V. Y8 p
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    % H' f% l* T5 O# k( b4 j% g
  11.   {
    % ^. D- B1 u* l" Z' W4 @4 _2 o
  12.     return MSD_OK;
    # Q% z1 p0 b4 ]& t1 J, L
  13.   }$ l3 H3 U  J# p) W# Q' j
  14.   else
    + y; V2 ?9 l; {% \# |5 U
  15.   {
    ( [) T( Q6 H! x- a5 m
  16.     return MSD_ERROR;7 r% B- H: l4 D  b* p8 C% n
  17.   }
    " V) H; ~5 M2 l1 g
  18. }
复制代码
0 ?9 W5 D2 S6 l* l, }8 _
87.5 总结
, Q  {. e  }) @2 S& {. w本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。
8 m  ^0 G* K8 p: t  p
# V4 G+ {- D7 X' G: @7 d& B' p  n/ g, q" k# m* l
赞 收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版