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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示
1 a! F5 f+ b4 e2 l  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。( u5 W- V. ^" H; ]1 ?& j7 s
  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。7 S0 D$ f' P# B: H( Y
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。  b" l$ {6 @9 i5 V
  SDMMC驱动SD卡支持1线和4线模式。
' a- N) E6 k% w: A  STM32H7的SDMMC也支持eMMC:0 b5 V1 p9 U) X. N- |% F; a
  
( g+ K7 E8 F/ I; z- Z) W# `" s& x87.2 SDMMC总线基础知识' y3 j" q4 O( H5 P
87.2.1 SDMMC总线的硬件框图# @$ c+ q2 b% @4 t6 z
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
5 [  `, ^1 f# n4 z8 p. o
9 o3 l- a) p. m3 j4 T
6eea62abe623396815a50adc87205b83.png
# j( P6 f7 }6 C& \8 N
3 H/ ?( S& q6 s; T3 p
通过这个框图,我们可以得到如下信息:3 Z" ]; E' I% l# {9 L  Y# J

, A) q8 A+ X9 l+ ^3 {# d% E sdmmc_ker_ck输入
, L& L7 }+ O# X2 b- Z" USDMMC内核时钟。
3 _% `. O7 C& F6 _! m* b8 |) {' ]2 q: t1 }7 d
  sdmmc_hclk输入
9 h0 B  q( o$ p' c* VAHB时钟。
! A- P5 f+ S7 V) {! D- P4 r
5 n- I5 n; X7 J9 ^  sdmmc_it输出5 K# O* B" ]) ^1 U" x
SDMMC全局中断。, \" k, O; S: {" }: j
7 N6 S) d0 a( }: f$ T
  sdmmc_dataend_trg输出
' ^1 }, G5 o) O) vMDMA的SDMMC数据接收触发信号。
+ g: I- w" Z0 C; Y' l; ?6 ^% p9 ]( Y; y4 @/ ]) ]; E% e5 y
  SDMMC_CMD
. m2 G- J1 a% pSD/SDIO/MMC卡双向/响应信号。1 x" r& x( f) ~
" c: X; n% o# w$ D
  SDMMC_D[7:0]- p4 C' @, E6 f- y
SD/SDIO/MMC卡双向数据线。: m0 S  ~& B$ J9 e& f# N
8 e9 g; S- q/ q+ }& L3 l# u; j6 a' V5 \
  SDMMC_CKIN8 m9 D% m5 g4 g) ?6 k6 `
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。+ X3 [$ E* {! g7 h2 i8 N7 G9 a

) c4 y2 S5 q  ]# T8 [  SDMMC_CK
; M0 }; G4 M- a) gSD/SDIO/MMC卡的时钟。" y# h; s, g- R+ C* V

) l- @) a6 ?3 G8 |( g2 g# j; @$ R  SDMMC_CDIR
0 s: D, D. z1 _0 M  sSDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。& r( h! y- ?1 c# }5 |( q7 f0 \$ ?

& [  X& \# s) d8 U4 Z  SDMMC_D123DIR) e  M& [( |, ?5 L& L& v
SDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
% r# S$ d5 c# R3 x3 u* [% S( [; [( `& n. }5 F* w
  SDMMC_D0DIR9 G3 R4 e. ~" B6 [1 g* U6 P4 K; r
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
# |* d& V* r! b5 }" M% {2 f$ `1 h4 Z* p2 b7 K$ D& V
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。2 V7 L+ p% a6 `; Q# G# e
5 q- b) U1 {) F$ s: R6 S% l. U7 @
87.2.2 SDMMC时钟0 A% m# ]/ ~3 K7 o% ^# n
SDMMC控制器的时钟来源:
" `" [4 }6 W! Y, i3 a% e' v: H. U9 \% Q6 u: @* q- ]
676ec31792fcb80bee640ed979d48084.png

3 V& h  a' Q+ [' _( K  `6 Z; t4 R, i4 \+ q/ [; n( p
SDMMC1和SDMMC2时钟源是一样的:# Y! H* X) `0 x. k0 k' p

* \! H3 `8 d3 ^( M6 v4 D
79b1c69986d1ee5bc090bf1676f396fd.png

% W9 O4 A4 a* l! ^$ S
2 l6 j4 g5 y- N8 q4 O87.2.3 SDMMC1和SDMMC2支持的RAM空间区别: J# y4 R, ~# H# n9 K. X8 J
注:大家应用时要特别注意这个问题。
+ L2 m8 q; M( r2 {
) m4 n( e- F' n& F$ z. V- B使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的$ Y  m( Q' m! D
9 f  N$ {! G1 V
6a5491d2f4a8740d838af58d034b7597.png

  ~* ^* }7 Z3 b0 h# ]3 k5 A% c% d2 R8 p9 A) ]* `
87.2.4 SDMMC支持的速度
; F: l1 g( w$ q2 a. ^驱动SD卡支持的最大总线速度:' t6 F( L9 r$ O; m

5 S4 w  y0 @6 X) z  |
b70ce31107b38ea820dbc28c3caec38e.png

4 \3 U8 B/ I1 ?, y( G" z4 {9 y/ o9 h
# B2 z0 f) S9 w6 w, f  M4 d; B8 s驱动eMMC支持的最大总线速度:$ L: p/ c7 F2 M: d/ y5 h
/ a( K, ~- \& F# i) h
843bf7a054944ba7d5d137ca84e1d4ed.png

5 m& z, y$ V% s  V) z# I; n/ a
) \# f' O6 N2 M6 S& S关于这两个数据表,注意以下几点:
- [. ]# p) O1 R
% Z( W& _0 o0 }1 E  x  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
9 T& ]( g8 I" e) @: I4 s  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。$ \7 q6 l  R: X: R- R  v
  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
# W5 [) q) Q' I5 Z2 |: F; ^87.2.5 SDMMC支持UHS-I模式
4 n; G: W1 ?5 O8 y. |' F9 ?STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:! A/ O+ e: |6 b0 a+ C
; ]! A9 x1 ^( e
2b8e4430b8a60dc5a1b342d7c7f75f52.png
2 B# s- Q% u+ O: t/ q% \

2 ?) ~& H/ s9 f  r4 L
85f975745619c9afc64f8889289dad58.png

6 ^" E1 k8 ?$ m! |  R6 e! a* l
  s. B" {; K/ U. s; v87.2.6 SDMMC自带的DMA控制器IDMA
2 \0 s  z) H0 Q. rSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
3 |6 _- Z" G: N
2 D& L# X- [  L87.3 SDMMC总线的HAL库用法, ?2 m8 ?' T/ ]( @
87.3.1 SDMMC总线结构体SD_TypeDef/ G/ z9 O* Z4 V- I2 j
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:) O* l* G$ e9 O+ K+ S
* i5 F6 o- L0 ^
  1. #define SD_TypeDef          SDMMC_TypeDef4 f- v) P" T3 E6 ~* f0 j
  2. typedef struct
    7 D+ \- N& V6 k  y
  3. {: S4 K$ }- a  z
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */' s8 b$ h5 j& d  y' ~! ^+ a9 F
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */) V8 c+ b2 S8 ^) T3 A, f  k
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */# \1 Z3 ^* \7 k8 u  f! H) C; Z( v
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */1 g# ~# w3 O0 I7 S
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    : t) V/ e% M/ e& u' B7 ]
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */$ t/ n2 n" i' b
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */2 J+ ?; l0 |) Z+ h, c
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    2 Y, _3 V# h3 d1 R: }
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */
    ' f6 l$ P2 U$ {% d5 {
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */! }0 ^6 y: L  b3 w: w/ p- X( T
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */
    - l$ w5 w+ F8 j9 b) F
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    1 d1 W, g# e/ [; @# U4 D
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    % G) ]6 t3 q. I
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */
    ( {  m( o" I) [
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    5 E% i+ k6 ?* J
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    ) @5 P2 D1 J9 d" L8 i/ }
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    2 Q, H( @2 v4 i- d
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */9 H7 E- d+ W  a! V+ u
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    & O! w3 P- O/ l5 j) r
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */# T8 u( b  b" j/ ]4 N
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */
    ) `' x* L1 v- T
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */
    - Z% K! X2 b+ h& N, R2 D7 X: z
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */+ C1 ~: x  f+ H" q' J3 G/ ~3 J
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    ) h: R) a  {' F8 g! v+ }) ^/ |
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */: N, P4 ]$ d8 [, O& m7 U3 L4 p
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */
    ) I1 v, W) G* f8 k
  30. } SDMMC_TypeDef;
复制代码

# m- Q6 {# _; C4 i这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。! w$ v9 h3 g- q' p) u! Q
* E/ ~, t0 F6 F2 P3 y
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:! C2 E0 k2 g4 |) g7 N6 u* Y
. q& J5 u7 P3 x; F. @: L& }8 |
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    0 f/ L% Z- _7 ]
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

1 b5 @6 U) J, A下面我们看下SDMMC的定义,在stm32h743xx.h文件。0 [( Y& x) c- `9 y
# g4 K4 l, l6 j( K  n6 D
  1. #define PERIPH_BASE           (0x40000000UL)
    + ?$ i3 w' N/ R* q
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    7 Y/ h6 H# s# B2 M; w
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)& b2 @. @. \) F% `
  4. 6 C2 w5 V7 P  U1 e) x
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)5 u; }7 q" ^$ p1 U: P- H- X
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    5 J! j; T- |+ _8 G9 X( s) h2 e( r# n# ?

  7. 9 H# z+ I1 q$ C9 e0 e! M
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE), k' ]- N: b! ~
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

# H$ h: y% J) Q6 x5 Q我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。0 {! @$ g# q4 o4 l" ~5 }: R

  x1 R% L: }: U9 t/ P# o87.3.2 SDMMC总线初始化结构体SD_InitTypeDef4 `1 S- P0 ^" ^2 h9 o, M. I
下面是SDMMC总线的初始化结构体:
, s# k# q4 `0 I6 l1 o  n2 [" E
$ k( h! `! e, ?( h1 O/ t- z
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef* }- o6 c: w8 P. f0 p& W+ r
  2. typedef struct" L/ N% r$ f! F* ?
  3. {
    # O# K- G0 l" G* x5 i
  4.   uint32_t ClockEdge;            $ a2 {2 _) t! V2 x: ^
  5.   uint32_t ClockPowerSave;      
    ( X& n( m% k1 ^2 e) _3 ^
  6.   uint32_t BusWide;            
    " F& P; X9 \2 h0 Y0 r4 o
  7.   uint32_t HardwareFlowControl;  ! F$ s, J* r( y: ]' K2 _8 G
  8.   uint32_t ClockDiv;            
    3 G* H9 m/ S7 d- z6 Y1 G/ E
  9. #if (USE_SD_TRANSCEIVER != 0U)
    2 U5 g+ B, N. W5 Y2 n, Y
  10.   uint32_t TranceiverPresent;    * ?) r! [* u3 }6 h- O8 x* g/ T% |
  11. #endif : y% p" d! }- M! W
  12. }SDMMC_InitTypeDef;
复制代码

6 Z9 ], j- ?1 F/ F* Q4 y7 v下面将结构体成员逐一做个说明:
: a8 H: t3 u; K2 I. M
3 Y1 z5 G, n+ H3 b" M  ClockEdge" X  A4 `7 t: B  X4 D" N) J
用于设置SDMMC的数据或者命令变化的时钟沿。
; X" ]1 W) q1 r& N, a( G: i
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    5 P  ~$ Z" r1 j  u' V
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

5 m, n, v7 {2 [9 p2 H& d: q6 ~  D  ClockPowerSave0 ]: k9 q9 Y4 Z  Z
用于设置空闲状态,是否输出时钟。
4 C5 I& l) D8 F# R8 y
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)# c3 |1 W0 j0 V& `
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码

0 ]( N% m5 E4 b6 P& s- l  BusWide- D4 `# X5 O. E3 f7 a) _/ ?: E/ i- K
用于设置SDMMC总线位宽。
4 A5 \0 b+ c4 t% |. x$ I) ^* r; n
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    & v  W! b0 i" V/ d/ O
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0) u# N, h" }/ d+ w
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码
7 m' L2 l- l( u! N* a; [3 l" N
  HardwareFlowControl" w, F8 A4 s) M+ s5 E, i
用于设置时候使能硬件流控制。
% p# F) B7 {/ G+ u& `0 M- D$ c
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)9 G; R+ I" K4 i4 P: J5 g
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码
$ D+ i' [; [& d1 l; N6 ^8 f
  ClockDiv
4 w  R, K. c9 |' R2 S6 L用于设置SDMMC时钟分频,参数范围0到1023。2 B5 e2 E! ^' T: u% L" m9 s  C$ N

3 S: f& I" Z* V  TranceiverPresent, i) M1 c) c: M8 \* R, R  Z# H4 A
用于设置是否带1.8V收发器。& q: ~0 J7 `3 ?" U, B+ o
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    2 T5 s& h6 c0 m. E/ L3 l7 w
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)$ d1 D: O3 X3 Q
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
0 S0 z; \9 n* V  R! [8 K( k
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
, z9 g2 i4 B) h6 C; G下面是SDMMC总线的卡信息结构体:
1 }3 F/ c8 Q* m
  1. typedef struct
    ) v/ q9 x  w" x/ N- K
  2. {: _7 h1 W! F$ n) K1 o; z# Z
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    # q, r7 ~' n9 t$ ]
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
    ; e# g) M: G5 ^& ?2 k$ k  z# v9 `
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    % U; d# D% M; j7 y/ F) W" ]1 f- m
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    : t3 }( D. c2 E5 N, n) r5 Y$ m  z
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
      P4 a' w& m% C
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    : p: u; D' x. R, M
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    . q% E: }/ m# t' @4 o
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    4 V' i) J! [) ^9 L9 n4 X
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */! t8 e/ r0 h& d: N3 M' P6 O
  12. }HAL_SD_CardInfoTypeDef;
复制代码

6 C! v( R8 \$ y下面将结构体成员逐一做个说明:% O5 C" g+ Z0 D. B6 a

1 @0 e4 A9 w' E5 w CardType: c+ V6 Y/ B0 \
卡类型。
( }- _) O  K4 D- T
  1. /*!< SD Standard Capacity <2Go                        */
    " d6 y2 M: s7 b4 l' k
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) 3 y6 Z7 d+ q% t: b5 Z
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    ' H6 Q4 [/ x. |1 ~4 y3 ?
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    : j% m9 d4 Y5 X4 S  c: y  ~
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码
6 J9 f# B& p) Z% X5 j
  CardVersion" k! D6 p1 T# C2 D
卡版本。0 L! p( }) M) \) P+ F/ z; ^6 h
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)% d1 K9 \5 W, {! ?9 X/ v. ?- U: q
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

5 q$ D9 p. |; I8 Y# \  |& ^% l  Class( C5 U: v6 {- c' ?, n( f) T
卡类型。) P. F, f( X; c# Y* _* R2 r3 ]

, ~/ L. z, T8 k4 @  RelCardAdd
5 u! a* g5 g, ~2 x卡相对地址。
  w. ]$ G: ^+ L3 X1 T# e
3 e0 O6 k  x, b. B& ~  BlockNbr
8 e9 I1 b8 w. ?8 L$ G! v整个卡的块数。
- N# S" E/ L+ g* ]% V# X4 E/ b2 x! K% k* ^
  BlockSize
. e: Q6 |0 O5 S- M$ W8 Q每个块的字节数。
- ^! F8 D1 k1 a2 f8 H* @4 J3 T0 Z2 H; Y) K3 Y
  LogBlockNbr. H# D- k4 N) l) D, ^8 C! H9 D+ n
整个卡的逻辑块数。
2 {9 U2 o; b3 @: I8 e
- J* q& W9 J; O4 w' P  LogBlockSize3 f4 i& ^1 j, \8 B! j9 W
逻辑块大小
5 C0 T) u+ Y" C" ~% R7 K5 z8 o1 Z
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    & d1 S) g- o+ y
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
/ n1 N2 N$ x# Q' c' B
CardSpeed
2 m8 C5 o! G6 K用于设置是否使能SPI总线的TI模式。( }) f0 R# R9 E4 g/ p
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */, x) Q" i+ v- E: D- O- v3 Q5 ?) Y
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  + h( x( a! g- Y. E- D, i
  3. 6 p. l. q% l$ R
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    5 a/ B+ O9 `, u' u. V7 d/ _
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U) + _' C: g8 m& N3 s9 @1 v
  6. ) C) g$ o. V6 H+ f
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards5 u' n; R3 u% |! Z) T
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    ; w$ }5 F. f* `
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

& ?- G; W& l1 H87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef! q3 v; O' ]9 ^# f
下面是SDMMC句柄结构体:! ]% b0 c  t! U: a2 D* `: Z
% @8 K# ~3 L2 I1 F% A
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)* D3 L, C8 _! e1 e. C- ~3 w
  2. typedef struct __SD_HandleTypeDef4 P/ W6 Z: ?& ~. o; U" I2 y
  3. #else
    0 T6 {( n! D, f+ L
  4. typedef struct' G7 v0 x' \& s$ Z
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */3 Q4 w! j2 e- L2 Z% s9 T
  6. {% L" E+ U- ~) \0 B: `/ c3 U
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */8 j( a/ K* V5 i; s
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    9 t( c8 N( c& u$ X3 o
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */- ~- ~! U1 E3 C: _% A
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */7 Q6 T  v" B8 E$ y. {# S# [7 {9 M
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */
    . c. Z. J; p) ]( X3 V& c
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */
    2 o3 l: @9 \0 V3 D0 k/ t/ t1 Z
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    % ?+ H  o& ?) x5 [9 r9 w8 t
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */, q; j. m! T% \* ?+ L
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    2 c, ?7 _9 T) p8 `
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    7 [( K" H( ]' E4 ~: c2 d) n+ L
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */( {" s' E. n* R2 ]5 H: M
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */
    8 e! I1 q1 O' K' E# d# n
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */! x% Y! h/ C5 Y' t. z* Y+ g

  20. + |8 W4 ?5 e) w: }/ i/ b/ s' Z" \
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U): d" S2 I+ F3 q8 R6 I6 A$ Z
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
      S. x) |& y/ i0 S1 P
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    + P. e+ W3 x. u0 {3 ~, |2 ]$ ~
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);
    ! [* |8 R; e% b
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);% U8 t" r6 [1 \( Y" f
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);+ }, O  i; M! Q# o- Q. R
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);8 y4 P& p' J# {8 ~4 G& M
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);! I8 S9 U5 W( d9 f; v
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);7 F, H. i/ F/ U* _
  30. #if (USE_SD_TRANSCEIVER != 0U)+ n4 B: ?) |8 @
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);" W+ _. a0 k  g
  32. #endif /* USE_SD_TRANSCEIVER */
    9 t  J& H7 o' n. {. A/ G3 |
  33. 2 A7 w4 e' b. L2 ?& m5 ?
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);- `; P1 A. g- U2 J0 D* K
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
      [4 s6 _9 P4 P, l2 {0 c
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    5 x% M! c3 ]3 H' ]/ k
  37. }SD_HandleTypeDef;
复制代码
4 K9 G- s' A) L5 k" x! |; Y, P
注意事项:; \0 e3 O1 z1 S; H) v( y, X
. t, Z$ X7 V5 g& b2 Z3 N
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
+ M6 M5 A& G2 ^( U. E/ {, b# R8 z- N8 y
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
( `2 ]; i( }6 Z' s( [. o) t1 V- |+ q! g2 U+ e2 Q+ e( w8 ~9 Z
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。' R: x: `( g9 B8 x" s

7 ?! G, J3 S/ f- ?* L这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。, X  m5 u" N- `  M
7 ~! X: Y8 d$ T  d$ e
  SD_TypeDef   *Instance% H  c5 P* J3 b2 n/ p5 B+ s
这个参数是寄存器的例化,方便操作寄存器。0 {1 W$ y% t8 x/ b' h) A
" e4 w" g. D# l" R
  SD_InitTypeDef  Init5 @  s4 |" b1 B3 Y9 e" V
这个参数在本章节3.2小节已经进行了详细说明。9 y& q, g. e- i! {
2 g$ w$ O$ V# e9 w& \0 B
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c% e2 M0 J2 V% S- K/ l
此文件涉及到的函数较多,这里把几个常用的函数做个说明:( x7 ~# @( n8 o1 b! i7 ~
& Z' `9 a- P6 |+ ]
  HAL_SD_Init: n& L. |6 g+ E% r1 i: K. ~. h
  HAL_SD_DeInit
& Z" x- ?* p* w7 q- U  HAL_SD_ReadBlocks
8 N( i! G- [' U# o  HAL_SD_WriteBlocks
7 C6 k8 _/ o; S- N  HAL_SD_ReadBlocks_DMA4 e" l7 r, v, [3 m7 ?
  HAL_SD_WriteBlocks_DMA
  {7 c5 r3 G* t  HAL_SD_Erase1 _- r0 [: z+ X0 V. l
87.4.1 函数HAL_SD_Init) N" c) f! ?% f6 }( n" t
函数原型:5 y4 A+ s; Y# C2 m

3 C0 g/ i& T$ [" V% T. {! b6 |
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    ; n3 e/ B$ y) e! m2 s; B# z7 E
  2. {
    6 P( R$ T: \2 a9 O% e2 r
  3.   HAL_SD_CardStatusTypeDef CardStatus;1 O- J: |) K3 R6 p
  4.   uint32_t speedgrade, unitsize;
    6 F% x6 l6 I# L9 O
  5.   uint32_t tickstart;
    ; x4 v" x9 S# P1 k) V! A
  6. 2 a& W: U: A: u( H6 f4 e
  7.   /* 检查句柄是否有效 */" D! T% {7 @, h# B' k5 \+ O
  8.   if(hsd == NULL)
    ( O* U( M# e, W3 b
  9.   {$ a* ^- B/ u: r  V* u
  10.     return HAL_ERROR;
    % A1 ~* f1 t7 V( x) \. v- S
  11.   }
    0 j8 ~1 V4 H6 S/ R0 R

  12. 9 y: {' A( Z  O$ Z
  13.   /* 检查参数 *// u$ w; S' |# s8 r8 v
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    : _6 `3 Z/ E2 ]. e
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    ) m, L! ~; X/ P1 G4 I, A2 Y
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));* A5 F0 S) G* b8 C3 ?& M. n' A& [
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    ; Q# X% s4 N+ ^, p) c
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));8 c4 @9 g' X6 ?. O4 q
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    6 j( J* C  a  c! w2 D# \$ a
  20. , G6 @/ P8 P9 I5 [$ }4 e' o
  21.   if(hsd->State == HAL_SD_STATE_RESET): s0 f% @  Y7 @
  22.   {
    7 r: V0 S+ [+ u' l: q
  23.     /* 开锁 */
    " R+ r2 V  }0 V, R# Z5 e4 ?  \
  24.     hsd->Lock = HAL_UNLOCKED;2 H0 t$ x7 T" x9 R1 m$ ^

  25. ) x/ l9 f7 C: T$ L/ B. _5 e: h
  26. #if (USE_SD_TRANSCEIVER != 0U)
    , b- D3 I  n; ]# ?( G
  27.     /* 兼容 */5 u" ]7 W9 g$ Q( Y" Q' I" z
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)- G1 f8 v9 L1 P) R9 K, x
  29.     {
    6 j! @( z) y; f
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
    : {- L5 Q6 w+ O9 B
  31.     }- u- }4 {4 E2 J8 O2 `
  32. #endif
    5 |! f7 I; i. i& q4 X* G, {+ R! Z
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    2 G( z1 D6 A# A. t9 \/ v
  34.     /* 复位回调 */
    ' _2 }. L& I: h/ X
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;- O; \8 {- W( z# w
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;* B; ?0 x2 P) A% f
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;2 q( A) |8 W/ j/ a1 f; n
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    6 o) w6 Q5 U" H& M4 u7 W
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    1 `, h) y- q6 C# h
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;! z2 A$ a/ U* N7 t! M' @% b
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;) u7 s: k  W) d1 T) v4 p2 N& Z
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    0 @* d3 @5 Q1 o
  43. #if (USE_SD_TRANSCEIVER != 0U)$ I! d. I$ R% H" k& I
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)% r, k. ^: H9 K- L
  45.     {- s8 m3 S/ i9 _# N
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;8 Q: i/ n8 p6 n0 b
  47.     }8 ~4 D0 L0 V- M2 R0 o8 J& |5 B/ p  Q% k
  48. #endif 8 J, [, e' b: y3 U( l: S. _

  49. 1 M* z# |' R; _. z! U8 b" i. @) c* X
  50.     if(hsd->MspInitCallback == NULL)( ?0 T- C3 R3 L' E( \  T
  51.     {# j+ D( @: r, c
  52.       hsd->MspInitCallback = HAL_SD_MspInit;( t( I6 l/ X4 P
  53.     }+ ?( E; c8 G3 i! E; \

  54. 6 y7 z; M( F) z; U
  55.     /* 初始化底层 */
    4 F# G2 {) ]. W
  56.     hsd->MspInitCallback(hsd);% j# g- j8 B. j% N
  57. #else
    : |: s' @: v7 H$ @
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */& B) J; ?7 K, D* V9 G
  59.     HAL_SD_MspInit(hsd);
    * O. o8 Q' S  I) x
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */0 \) C2 Z/ c$ ^6 g. a( [
  61.   }& C2 _9 Y3 J2 r( l! l
  62. % g* c% F4 l1 f) J5 e8 I- F
  63.   hsd->State = HAL_SD_STATE_BUSY;; N9 e6 m2 F5 |$ }& {  Y
  64. 0 Q+ l# v3 Y9 s+ z
  65.   /* 初始化卡参数 */. A' x! y% m4 }% r, b) k1 T+ u
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    ! t/ J8 w/ _% S! Z; _
  67.   {2 T) C( Q! U! }) b
  68.     return HAL_ERROR;
    & h9 ~9 v4 ^% u
  69.   }5 [; Y  Q1 u; ?) C

  70. 4 \# ?3 l; w7 n/ \) r" y' E
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
    3 n& o" q7 O" t; v& F) L
  72.   {
    ) M$ z8 F1 E5 s- C
  73.     return HAL_ERROR;
    . a2 w' s) V5 ~8 r% s* K
  74.   }& ]  |' v5 ^  [! w  V0 _- h$ e( L
  75.   /* 获取卡速度等信息 */3 a5 u. m/ b7 z2 J7 s( ^- F; n
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    3 v, Y! _" d- u' j$ u+ V% Q; {
  77.   unitsize = CardStatus.UhsAllocationUnitSize;4 |; x# Z2 Q  m5 F& d* s0 U) f# I
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))3 D* l& c) @9 S& m, K
  79.   {
    , y4 ]5 e3 v3 `2 ?9 V1 j1 R
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    : ]- c" i0 @  m/ V" w
  81.   }! E0 o# o1 e2 N8 s4 ~
  82.   else
    & ^6 G$ d# N8 b4 j
  83.   {
    $ J1 I) c% F/ S3 @
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)4 f+ M# R& a; q. L7 a
  85.     {4 G6 i- r( t! P0 ]& ~1 M, x
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;/ c* k2 F/ m1 I4 c
  87.     }
    : H- |: C/ s  I
  88.     else
    & p( w1 s( t  n- _" b
  89.     {
      K' V9 G, |- J9 y6 b
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;
    , U& K& M. O5 F1 o8 n# [
  91.     }
    , Z" r8 Y( P3 i. t  ]
  92. 6 P, B' P3 }, b
  93.   }$ k. y8 U: P' s" P) Z  ~
  94.   /* 配置总线位宽 */
    3 k4 s" v- g6 }) D* o
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    + O) h% E5 e9 c7 A' [
  96.   {
    3 U  W0 H  `3 I
  97.     return HAL_ERROR;
    , G: w' f- M, f9 _
  98.   }( m% M! n" |) L3 X
  99. ' t/ f0 A7 Y) Z: d  _
  100.   /* 验证卡初始化后是否就绪 */& r: y6 f7 Y$ _; Y# B1 l8 D+ z! t7 B; H
  101.   tickstart = HAL_GetTick();
    , |* Z  ~  @4 _' Y0 h
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    + r* H8 D- `: I( q  j* q5 y
  103.   {1 V' X, R0 T0 D# t
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    / A! S% [8 M) p; x9 Q9 g, {
  105.     {
    ; `* i6 Y; A* z) i
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;- s$ n, X, S( g9 E! i
  107.       hsd->State= HAL_SD_STATE_READY;: h2 v& a/ R  E/ K( ?0 g1 [+ N" j
  108.       return HAL_TIMEOUT;; A4 J' d' k" ~0 c& F2 l& M' t
  109.     }! A% M4 Y, T' o3 u$ E
  110.   }3 w1 {) g. {$ c$ a% }

  111. ( g9 l3 d" W) g) C$ ]; Z6 a% P
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    8 _/ A2 F) I0 Q

  113. : R9 U( `- i8 g8 q  T5 T! T5 W
  114.   hsd->Context = SD_CONTEXT_NONE;8 f3 T( y0 b: ]! y

  115. 3 [% \8 {/ C7 i$ \
  116.   hsd->State = HAL_SD_STATE_READY;4 W; K% r6 z$ l2 M2 c. {

  117. * c  n6 C. _; C9 h
  118.   return HAL_OK;2 k% K* f% y  j) R
  119. }
复制代码
! t% z+ t3 d+ ^8 G6 }, R+ r1 Z& ~
函数描述:0 S; e6 H2 [$ r2 P( Z1 c, E
5 Z7 Q) h* v' U$ V2 }
此函数用于初始化SD卡。
/ B9 b7 ?" O2 m9 b" b2 l& L4 _9 |9 I/ V, j0 _' c! U
函数参数:$ F- Z9 l) W; Q- K% Q* n, R/ r
! Z. t- q5 b0 G% E0 N! h! P
  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
  o7 k: b9 p5 C: A* X& O4 p$ t1 d  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。: a/ ]" B+ G7 l+ z: ^7 M# X8 n4 A
注意事项:
; W- z/ a1 N* ^. P6 }
$ t6 G+ J, R) K5 q0 @/ C函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
$ K( f# E9 Q) Z0 H! B% F" U如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
' z% J* }# Y$ I; h' X对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
( f6 O5 p) P+ x0 J
2 w0 T/ N5 j7 I) o解决办法有三
1 ]# ~# {2 o+ M! k( ~0 U7 }+ Q. _! T1 z! M. R* _& r
方法1:用户自己初始化SD和涉及到的GPIO等。$ g" x4 d" t5 o/ a+ k: V( ^. t* I6 r

' Y; ^* h4 q* w5 w方法2:定义SD_HandleTypeDef SdHandle为全局变量。) r. z$ M6 k: T; d

7 g+ w/ s6 \7 G9 X1 a2 \) j- f方法3:下面的方法9 `: r: {1 G% e1 D3 z, V: k2 F

$ d5 @# y  k. M9 R6 E
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    ; E( x$ o, o* g/ U
  2. {
    8 q* j, @. C( w7 o
  3.     Error_Handler();
    / V6 _$ N6 L& g- q3 I1 k7 J+ k
  4. }  + Z; ~9 Y/ B$ [
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)% S0 L4 S! k  M. s6 d& b
  6. {( H8 M. a( w' ]: _, n( ^( W; c
  7.     Error_Handler();- u2 D/ S, z! k- r9 }! A* t
  8. }
复制代码
# H/ `5 M  g- J: g0 }6 F9 d
使用举例:& C1 G8 c5 N$ e7 ~0 o
  K) s9 K; R3 `4 \
  1. SD_HandleTypeDef uSdHandle;" y: }/ D# R/ R: P

  2. ( |6 t; [$ A- {; q7 b8 w- c
  3. uSdHandle.Instance = SDMMC1;
    $ m$ J- l  n2 n- O# k' E1 v& j

  4. : K! |8 y/ N4 P7 }/ F6 W
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    8 G% X1 B: R3 T+ k, g
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].
    ( j" `3 {3 I7 s( l+ s6 m
  7.      200MHz / (2*2) = 50MHz
    1 j  i" ^) k* V1 l5 k3 Q
  8. */4 [3 D2 ?8 E! `; P. O; G
  9. uSdHandle.Init.ClockDiv            = 2;
    2 z! z0 ?/ V) K: V) b, N7 p
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    " ]$ ]* B" `# J- N- ?
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    2 c9 j- P+ G" v- Y, E7 j& m
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;* _: z4 X* j4 `: p3 \) B
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;- {$ X# I* W% z' d5 a( F
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)% o& c( J, |+ c, P6 H
  15. {  x! c4 M; O, f% }. f! n
  16.    sd_state = MSD_ERROR;% J0 x# q* |, v3 `, k' B4 C
  17. }
复制代码

7 Q) w* ?- j- X87.4.2 函数HAL_SD_DeInit2 Q" T8 e% T7 [2 Z. u
函数原型:
" v# e: b: @2 K1 Q8 M2 f0 V4 h2 [+ i) I% O( |3 Q, m
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)' l0 ?2 P& K; B& [: {
  2. {
    * H/ s7 V0 I0 o% C  G
  3.   /* 检查SD卡句柄是否有效 *// b# Q1 d3 n9 h# n( G
  4.   if(hsd == NULL)
    8 V) A% i# i* g* ?( l: W
  5.   {# H! Z5 T4 D! b% m" z- S  C
  6.     return HAL_ERROR;
      ~7 g5 f3 n0 B
  7.   }5 P/ v1 @7 T, A3 e( f

  8. / k6 e5 ~& l, r1 L: ?( ?" l) V
  9.   /* 检查参数 */1 l# j+ X1 j. }7 Z; |: P& C- K
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));3 K. C8 j1 o* J( J$ q6 Z4 p

  11. . j$ O+ v0 G, t' z  v( o
  12.   hsd->State = HAL_SD_STATE_BUSY;
    % W  x( u  L8 k) I( M) m
  13. & I) f. {# l, M5 d
  14. #if (USE_SD_TRANSCEIVER != 0U)
    9 P+ u) H5 Q0 i
  15.   /* 关闭1.8V模式 */
    1 H1 U, m* S7 c6 f
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    3 C  j, |0 y4 Q+ {) O0 C3 B
  17.   {
    ! S& A. m/ E5 H/ \6 }
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U). k+ m4 e! W+ R! Y1 ~
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)
    1 L% e- q/ L* |
  20.     {
    5 X5 L. |: b$ D1 ?! F* k! z; x0 `
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    $ O0 G" p6 K3 v
  22.     }1 X5 c" |- ~) @( {. {
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);, m3 O, R* s7 {: I4 f/ S
  24. #else; e1 h! y- Z) y6 d. g
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);% M; @! Y: }0 S& d
  26. #endif + m; P& q2 f# {
  27.   }                                                                        
    % |6 k9 P6 {5 w6 u0 n. Q! G1 g
  28. #endif
    9 p/ R% R3 }/ @! y( f
  29. ! ]0 O! M# G& j
  30.   /* 关闭SD卡电源 */
    & a6 ?8 ^, S1 g8 t( \
  31.   SD_PowerOFF(hsd);
    0 b/ z" u9 a) h5 a

  32. 9 o' F9 C0 c' d  d
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    4 W! }7 D: K$ V+ U! D+ h/ U& k
  34.   if(hsd->MspDeInitCallback == NULL)! j) Z  r. O* D( b0 M
  35.   {
    1 O+ _  V0 ~% j  n% _) N" }- ^
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;4 w* i7 J/ Y- u: l2 d1 q
  37.   }
    ) L3 x" L0 ]$ O
  38. # ?; w6 L$ U/ d2 C* M0 k8 f9 Q
  39.   /* 复位底层硬件 */# M' O5 r4 c( D# T' N
  40.   hsd->MspDeInitCallback(hsd);
    ) X8 {7 y) \2 \. f$ w! v
  41. #else
    : Y/ y( i) F9 R$ G9 n. G3 C
  42.   /* 复位底层硬件 */% b% k% k$ X8 Y- \
  43.   HAL_SD_MspDeInit(hsd);  A- }. y9 x9 {$ M
  44. #endif - d! D$ s( A# ]
  45. 2 R) Y9 V& o6 T! W$ M: B1 F
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;: ]& K$ h% w/ x; F
  47.   hsd->State = HAL_SD_STATE_RESET;
    ) T- j# P- p$ M8 c7 `

  48. + `) B3 L! w$ }0 W. Z6 ], m( G, j; {
  49.   return HAL_OK;# D$ A- @$ |  o
  50. }
复制代码

7 B' U7 \2 j. B) M函数描述:1 b  }6 h" b' R7 A, S, l

. i0 D$ V8 l3 {+ f5 V$ v6 n! C! F用于复位SD总线初始化。5 t" h* S( N0 I/ Z
9 o( k" U/ W( B# {( b& L
函数参数:( a: |% _4 K5 W  h+ a- V

4 X6 M* Q" X  u 第1个参数是SD_HandleTypeDef类型结构体指针变量。
/ P* J  ^0 U* U; [1 X- S  G' F( H* p 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
! n$ G( m, s/ R& f0 \7 U! h1 B87.4.3 函数HAL_SD_ReadBlocks8 M9 n: X4 [2 R: w- b
函数原型:
+ Y( T- |- v. j' n* s% K1 ?: R. Z( b, W" b* I
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)6 v! E: H6 K: u# k5 K) T4 Z
  2. {
    3 H1 A. c1 _  r1 o  ~* Y" p
  3.   SDMMC_DataInitTypeDef config;) [& {  g* w# {7 i
  4.   uint32_t errorstate;
    0 s* l& F+ p. L+ h" I
  5.   uint32_t tickstart = HAL_GetTick();- o' X8 t. n1 K' X0 B/ @' K/ d
  6.   uint32_t count, data, dataremaining;) P* I8 Q5 l0 {% \0 e5 Z/ \
  7.   uint32_t add = BlockAdd;
    ( |# X* u& H6 m4 J% Q- b+ x/ ]$ G
  8.   uint8_t *tempbuff = pData;
    % }$ j4 `3 G! h
  9. ' h6 I/ F7 a) U  z3 H: N
  10.   if(NULL == pData)
      O# ^6 D4 _8 v- v) s3 q
  11.   {) D' @! G' ]. C: I
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;8 _+ S/ c) D+ X+ i+ }# U" c
  13.     return HAL_ERROR;
    9 P8 c) f) o  j2 o; p
  14.   }
    . X6 s4 F2 |7 N, x( s) {

  15. ' R) I+ t. u0 E6 \; e' t
  16.   if(hsd->State == HAL_SD_STATE_READY)2 B+ A, i, a6 L' A2 V5 }4 l
  17.   {
    0 Q  o2 A, B4 N6 d1 \* n
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    + V1 ?! R- F& H4 |% ?
  19. 7 C2 z) I5 l% O% m% c: H$ y
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    - N! o8 m1 r8 }' a& Q6 b; }" E& h0 `
  21.     {4 T0 o5 ~# X& c- H4 _- Q
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;+ K6 C  f9 y/ _! \7 Y
  23.       return HAL_ERROR;' ?7 G% @5 {5 W
  24.     }
    , I4 \/ r1 t0 t" N! B; U

  25. # `2 I9 Y8 B' I8 e- v
  26.     hsd->State = HAL_SD_STATE_BUSY;
    * c& _7 I& s$ ?+ W! b# ^
  27. " Y  Y3 M4 C. Q1 n7 z" P* |! ]# |
  28.     /* 初始化数据控制寄存器 */( r% o6 j9 z8 P" ~" o$ j' ]3 {+ T: W: P- h
  29.     hsd->Instance->DCTRL = 0U;7 P3 [, S( J9 Y. n, G9 M1 g: y" q
  30. ! d' v% b- ^, e. |# N" Y& u
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)6 `4 D& n& }, ~- v9 a) x4 Z
  32.     {
    # t( {+ J- f2 P2 {1 I" n. a
  33.       add *= 512U;* S# _5 ]5 r1 M. a! h6 ]. {
  34.     }3 {# ]2 J# I* G* e) T0 j

  35. 3 g5 D! u6 D! V6 O3 U* t2 {
  36.     /* 配置SD DPSM (Data Path State Machine) */0 r8 K+ y; i. ^
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;, `  m8 C, r2 j) M
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    2 m# u* z. ^1 }. ~: s3 E
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;& H( y' i: w! L( Y# ]  Y& |, P: g! h
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;- X+ d7 y% M* c+ H( N" Z" w2 w2 a2 a
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    + x( R! `) I( a* T
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;( h+ ?+ Q) D$ ]0 I
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);- }& j' e7 n/ O
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);# `4 j% O/ p& h/ P$ L2 Z3 }

  45. 6 ^% a# R' Y) b: L
  46.     /* 查询方式块读取 */* ?" s  |5 w. D: o1 ^& V  D
  47.     if(NumberOfBlocks > 1U)
    ' k( A- d; X! }0 G; i$ Q! b4 n* A
  48.     {" a7 V5 T  ~" g/ [1 a
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;& m; r5 D6 T$ ^
  50. ' v: z! `( r" W/ a$ M+ j: l# A
  51.       /* 多块读取命令 */
    9 G  S) V% O. Q9 u8 j9 ]
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    % L6 b1 e) l; F4 X- T. V# s
  53.     }* K8 P  @! j/ d0 Q% Y7 I" N
  54.     else
    ; L. H1 c3 D0 \+ C2 y4 o
  55.     {
    5 a% ]6 v. t) S) r" h5 ^: S
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;1 b) H3 j& B9 ~, s& u, Y

  57. ( U: K  Q; Q$ b4 L+ g; i2 t4 w
  58.       /* 单块读取命令 */
    7 o- A4 a( Q7 L: u- O6 A
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);4 D) M$ e8 ?- `% l7 e# H) x
  60.     }
      K% e* b& L8 Y# s% s; b6 _* I. y
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    * p) b, J7 I, a2 @- H
  62.     {' `& l; l2 G; U2 B1 x' Q5 U
  63.       /* 清除所有静态标志 */( B8 }) f/ P. N/ d4 v3 J$ Y
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ) X! g/ J. w+ |; z7 b
  65.       hsd->ErrorCode |= errorstate;5 t+ w: V' A/ Z( D5 ^2 G
  66.       hsd->State = HAL_SD_STATE_READY;, q" Y* z$ J4 e3 I) w6 D
  67.       hsd->Context = SD_CONTEXT_NONE;
    % g3 i  X* y* t9 J" Q) [
  68.       return HAL_ERROR;: v& H4 H/ [$ s4 V4 E
  69.     }0 J% {" z% \/ G3 E( X# w
  70. ; G9 t! M% x3 u( U) D2 R8 b! n3 s! \
  71.     /* 查询SDMMC标志 */
    - l; I1 ]2 I0 I$ n! [" k! C
  72.     dataremaining = config.DataLength;
    / T4 N: b2 Z  c' @- F' p
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))9 ~4 D5 c) H# L3 l+ h
  74.     {
    3 e& ^+ S. z2 x! i
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))6 @" u8 V$ N6 t' `2 J5 [
  76.       {
    % u! F: |! Q8 R* r; E: l# w5 b
  77.         /* 从SDMMC Rx FIFO读取数据 */9 a* L8 Z* s$ r  Y( M; y
  78.         for(count = 0U; count < 8U; count++)' n% G0 B0 x8 l
  79.         {
    5 k, M3 k# S+ o1 \6 ]$ i
  80.           data = SDMMC_ReadFIFO(hsd->Instance);% e& M* `# Z$ q( E( I$ @# l
  81.           *tempbuff = (uint8_t)(data & 0xFFU);2 I3 t1 N% t2 \4 u# f4 Y- V" j3 X
  82.           tempbuff++;
    ; \# U4 h3 B; s
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
      C' ~5 \9 G$ f' o$ n/ }/ \
  84.           tempbuff++;
    ) F8 h3 X# `4 X+ r
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    8 W& ^. Q' _- I3 v9 r% K
  86.           tempbuff++;. b% e) X3 N4 ]/ c( l+ q- O
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);% |) m, v8 D5 N% Z
  88.           tempbuff++;
    4 `4 j3 W- \- s! x/ {4 d0 e' |
  89.         }% x8 C6 P. z$ l4 j
  90.         dataremaining -= 32U;
    3 ?0 T; i, W" F
  91.       }
    : p! q( }, S' y& |

  92. 4 T7 R9 s# A, @% F
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))# w7 Y) w( A! J, L+ `
  94.       {
    - Q  f- V1 j0 z* S; N" f
  95.         /* 清除所有静态标志 */, {( l) p! v" D
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 o. P0 U( b3 B4 u* C) b3 `0 f# `. N
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;% i0 @9 D) F8 L1 B( o/ a
  98.         hsd->State= HAL_SD_STATE_READY;* K/ @; u5 c4 J) w+ e
  99.         hsd->Context = SD_CONTEXT_NONE;5 ~% s$ {. W1 k; W
  100.         return HAL_TIMEOUT;9 O; b9 V& \+ b  C; U% N
  101.       }5 i: Q0 n4 m4 t
  102.     }
      G# S* J9 Z: g
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);1 Q! I9 B4 }, [7 X' n! K& u6 B, z
  104.   u! z9 N5 i1 v" Q7 a) @  n
  105.     /* 多块读取发送停止传输命令 */
    7 j1 g+ |+ d& M. G  B% i/ M4 J
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    " V0 [9 z) v: w4 E* P
  107.     {
    / Q% z" m! B+ ]: _0 O+ ?
  108.       if(hsd->SdCard.CardType != CARD_SECURED)
    5 F+ ?4 D* C3 `9 p" h
  109.       {& y( \) x5 J* ]
  110.         /* 发送停止传输命令 */
    7 M( P2 c" h1 U( \6 [
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    3 U; O- _: v! U( R8 [% @
  112.         if(errorstate != HAL_SD_ERROR_NONE)5 R: G+ {! E# c$ H+ @; w( N
  113.         {# x% Z" q2 n% i! f$ p4 i# I9 P( {. w
  114.           /* 清除所有静态标志 */' S" l' [3 D2 c# w: I5 n
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);+ N+ H5 l" e( F
  116.           hsd->ErrorCode |= errorstate;. \- ?& o) g6 l  d# z) Z
  117.           hsd->State = HAL_SD_STATE_READY;& p- u" \( ^5 B: l0 N
  118.           hsd->Context = SD_CONTEXT_NONE;
    * `7 ~0 e: Y7 ~' K: r
  119.           return HAL_ERROR;
    " V& V# X" a* O& I1 J
  120.         }3 y& `* t3 K4 M! V8 M7 o0 L! i
  121.       }! A, m4 i" |6 w# c$ f+ v" _+ K
  122.     }+ T; U$ `, a6 l, k4 P
  123. 6 s: m3 Y3 w" M  n
  124.     /* 获取错误状态 */5 k0 n- ?' L% }3 ~7 A' x
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))2 r/ Z7 f3 L) S% g/ n  O/ e
  126.     {0 m4 Y2 \7 R- k6 j' T( @" v: Q# I- k
  127.       /* 清除所有静态标志 */
    * {, l" S2 C) @: q! e8 \
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    $ N' N% n7 v4 o( C  b. h# H! p2 J; L
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    3 f/ {; i9 p1 v1 d
  130.       hsd->State = HAL_SD_STATE_READY;
    $ T' ~0 M7 x4 q+ @% c3 @' R7 X  Y
  131.       hsd->Context = SD_CONTEXT_NONE;3 s2 X3 g/ x  q$ K
  132.       return HAL_ERROR;7 w9 F* j+ y6 C9 a; K( Z
  133.     }
    ; `1 K- E6 U5 v
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    + y5 m7 G, D% ~5 m1 @9 b. H
  135.     {
    - s! p1 j* ?  a0 u' t
  136.       /* 清除所有静态标志 */
    6 Y; p) W& _, D# Y' h/ X1 U
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);; x: V/ `$ V1 \5 d1 I$ C' d
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    % @4 W3 H" z0 Q' p! ^- U# a: p/ a1 ?9 i
  139.       hsd->State = HAL_SD_STATE_READY;
    / n" w6 e% Z: j$ R: ]0 d6 w* {" `
  140.       hsd->Context = SD_CONTEXT_NONE;
    ' O% }% H5 r; M, u
  141.       return HAL_ERROR;
    : W- ^5 v4 r# \! N9 F. L5 G
  142.     }
    3 c0 S1 B1 \  g; F
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))1 }: P0 G% A3 B. K
  144.     {1 N6 i3 w& [3 Z5 s- D1 I# h: [
  145.       /* 清除所有静态标志 */1 G- g$ k8 h% [# E
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 I" F' ?2 P6 Z* I
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
    8 n+ f# O+ D" g. i/ z) v
  148.       hsd->State = HAL_SD_STATE_READY;' ^5 M" R/ |  l! Y/ [- L, k4 ^
  149.       hsd->Context = SD_CONTEXT_NONE;! h7 S' n0 L0 A8 S& f+ e
  150.       return HAL_ERROR;
    * s  |( S+ S6 {
  151.     }; g0 Q! @, {1 H4 m
  152.     else" F3 z/ L# `. `
  153.     {+ p& X5 `, P2 m3 }
  154.       /* 什么都不做 */
    - u( Z$ ^2 Z3 Y, W: ?
  155.     }
    $ B; D9 R" o5 a2 c2 `3 P) x9 V- }
  156. 0 X* t( \1 b- \
  157.     /* 清除所有静态标志 */
    % y' Q2 c7 ]/ v/ a# k
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);) g* z+ m5 `5 ~* `# N2 S
  159. 7 z6 W1 J7 O7 @# q
  160.     hsd->State = HAL_SD_STATE_READY;
    3 a5 |4 C/ j4 c7 @/ L) G6 Y' O0 {
  161. 5 j5 x- t* w: @
  162.     return HAL_OK;
    , @2 C$ D* O7 l5 F# N
  163.   }+ P- D3 B/ s! s' P, Y9 c/ ^* i
  164.   else0 d" l7 w6 ]: Z9 k/ k
  165.   {
    3 I$ O. R7 s3 l3 e; j! n3 |! B
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    , Y! n1 S1 n. J$ c* s+ J. p
  167.     return HAL_ERROR;9 [. O& Y0 y2 N0 w1 S+ x
  168.   }9 z4 d7 Y4 o; q7 F
  169. }
复制代码
7 @, R' B4 ]8 ~4 `* y5 B
函数描述:3 y! i( f2 m1 T7 Z( H% s7 Z
$ d+ t9 U% o) A# ?1 q
此函数主要用于SD卡数据读取。$ U5 \6 l0 R2 k1 h
# P- x8 k3 f+ x
函数参数:. m2 P/ P  h% S/ z, M5 {' {
3 j0 p7 e3 \, `. ^% m
  第1个参数是SD_HandleTypeDef类型结构体指针变量。' V8 n/ G1 T- \) G0 @. D  E8 s7 m) d
  第2个参数是接收数据的缓冲地址。
' z8 |) g+ x/ r  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。; u$ l9 B/ J/ k- X
  第4个参数是读取的扇区数。# g4 x3 R) o0 B& z
  第5个参数是传输过程的溢出时间,单位ms。
5 L) r  B, a) y  q0 [; N7 ^/ T, c  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 ]" u# d% b; q. s2 e" {
使用举例:5 X6 W8 U. U7 v

1 T- c4 a, D+ z3 y% t" z
  1. /**
    5 q5 c8 n8 g) Q/ h2 R7 }* W
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
    1 p5 Z; w, m* O. k
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit9 k. K# q/ f0 i) J
  4.   * @param  ReadAddr: Address from where data is to be read
    5 q" \1 I6 _+ o& f' G% x* s9 o; l9 t
  5.   * @param  NumOfBlocks: Number of SD blocks to read7 M8 Y0 s3 n  Z
  6.   * @param  Timeout: Timeout for read operation$ H# ~2 o0 I2 k5 m  R/ I
  7.   * @retval SD status
    + F* z# R* D, F2 Y0 z/ ], g; g
  8.   */
    $ {, G" w  Q) V2 z( K: K
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    ( Z. G$ z1 |) f# H* W. X# Q
  10. {
    / D' W7 q) B  M& P0 t0 D

  11. ! b$ m5 u0 r3 ?, ^  ], E' z+ z1 n
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    6 Q. |' X, U4 n0 y' A
  13.   {+ G1 H2 e! k4 `
  14.     return MSD_OK;: N' F" i' a. {: [# B$ M" y% {
  15.   }
    ! l5 Q. B) n# f& ?9 g* Z
  16.   else
    , l. ]$ a* s$ y! n, m
  17.   {
    ! E# O0 c1 A0 X$ k$ t% N! Q
  18.     return MSD_ERROR;- @! a9 A+ j' d* V% r
  19.   }+ R( r0 E' v+ E$ B$ P* B

  20. ; {% o$ @3 o9 G7 G; G1 U/ P
  21. }
复制代码
6 n$ L# V0 C6 Z7 W
87.4.4 函数HAL_SD_WriteBlocks
) w: h# W. N/ K函数原型:
0 u% N$ V, L- p# t' P: \# K! @2 s* q
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)2 V  c3 m; B1 F% r. F
  2. {$ S* }/ R( @2 d' k' E
  3.   SDMMC_DataInitTypeDef config;7 O+ L8 d& s/ {% Q- g
  4.   uint32_t errorstate;( n  u0 c) J  H
  5.   uint32_t tickstart = HAL_GetTick();, Z8 \. H' v+ `' o2 j
  6.   uint32_t count, data, dataremaining;
    ) F& Z8 D0 R* N) r9 k' e5 b6 \
  7.   uint32_t add = BlockAdd;' \& |( j% X2 a5 y/ w, M, a
  8.   uint8_t *tempbuff = pData;
    - Y! }% @& N/ k2 ~
  9. 4 o' a+ ]9 z' M/ ~( I' Q+ z
  10.   if(NULL == pData)1 l$ f, @* O+ X% U# L+ e! t, f- V+ K
  11.   {# S) b3 U1 R$ h9 B# S) c2 p" ?
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;5 Z  G2 z$ ?4 w( k, C
  13.     return HAL_ERROR;
    : O3 o4 O" P3 z5 R) }6 m. b8 O
  14.   }, T9 I# y- a7 c( O

  15. # g* r/ w/ |' x( F; j, W1 W2 w
  16.   if(hsd->State == HAL_SD_STATE_READY)
    + Q) B- D% O/ G4 s; R! U
  17.   {
    7 b5 a1 X1 s" O( q4 H9 c
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ' W' b2 S5 C5 n; Y8 E6 q
  19. ) V: L$ J8 X# P' Z* z' E& Z
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))/ l- h+ o) [$ H( L& J# K, F
  21.     {# G/ h3 `4 j& k  d
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;0 C8 R# i3 c- s, T+ ^
  23.       return HAL_ERROR;
    ) p5 l( j$ ~8 g
  24.     }' n; }4 C# }6 j6 ~

  25. : d' r1 V6 [. x. r" c* V5 \
  26.     hsd->State = HAL_SD_STATE_BUSY;
    ! A5 U$ U1 g/ h& Z+ Q

  27. 1 k4 W6 g9 c) L
  28.     /* 初始化数据控制寄存器 */$ ?9 q( J/ X2 N0 i8 O1 _+ \- }
  29.     hsd->Instance->DCTRL = 0U;
    # W2 W2 R2 C$ ]" o, m6 x' r
  30. # \8 s5 e% Q1 f# c, Z; e' m* W  y
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ' ?" ~! Y' f% \3 {( ~
  32.     {
    & I! S  x0 D+ C+ B% z
  33.       add *= 512U;
    * K  C" Q0 p! j! j& a
  34.     }
    % W( O7 u- e# q$ y! w7 h8 y* a

  35. 5 b- M0 |: P( L! @8 Z
  36.     /* 配置SD DPSM */
    + v, X: O2 n4 {: d; z" t; v/ a! I
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    1 l8 U& k/ l. N4 I4 l% P  q, m
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;$ \4 F3 n* l! E* Q  J; \& e
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;  }; h$ s3 S/ |
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;/ h2 r5 a  J$ B6 n
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    , I4 k. y8 x/ q4 R7 Y2 {1 q% b
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    4 O2 {% w& Q3 ~, \+ {
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);; V( v2 |% q( a7 C% a* a) j
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);6 N2 _- b4 a! T1 v/ t
  45. , _9 _7 J/ V2 o: G* g
  46.     /* 查询方式块写操作 */
    * Y  \) x3 ?: ^9 w
  47.     if(NumberOfBlocks > 1U)
    . A6 J+ B) v0 I4 H
  48.     {
    3 |- Y$ S2 P  P
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;4 I! |$ W1 x1 f7 x

  50. ) V  P  N  ]% U% e- o
  51.       /* 写多块命令 */
    * E) I' a* c1 ^
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);/ S* @9 O( Q4 O. W; T% w0 C, K1 G
  53.     }' R9 [- ?, b2 V6 ?; r. {
  54.     else7 S( k. z. d  w. Y: b( a
  55.     {9 I; B* N, [) D- X8 z
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    1 {2 G$ r: V5 k) X8 `

  57. # N, M% A% K& v
  58.       /* 写单块命令 */
    9 ~9 A7 k& s; @, m9 U
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);3 [; b0 d# e9 T4 ?% w$ {+ Z; a; b
  60.     }! V! x& D! p4 v/ M: H% @6 ?, {
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    # O. O; L+ B8 g% u" t
  62.     {
    * F$ p1 _: j0 m. u- d1 C6 _+ i1 ~6 O) j
  63.       /* 清除所有静态命令 */
    % X+ K% o- ?9 h6 k; L" x4 a- g
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);9 G3 M- ^3 [3 E! j9 X
  65.       hsd->ErrorCode |= errorstate;
    & p" d, l9 G+ R
  66.       hsd->State = HAL_SD_STATE_READY;# f& m+ P  [: w3 g
  67.       hsd->Context = SD_CONTEXT_NONE;
    % ^# x5 _2 _$ Q
  68.       return HAL_ERROR;
    . }& i7 m2 q1 N; F2 `2 @
  69.     }
    5 B# |( N! }) `: R8 s$ X1 q0 G4 X
  70. , L# w2 w7 i- \& Q+ A
  71.     /* 查询方式块写操作 */: E' v. a; i! w7 D5 e* ^
  72.     dataremaining = config.DataLength;/ ?# a2 S! h- w$ |: C
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))# K7 A% S0 V. h( g( y% A
  74.     {
    + c- b3 s; I. n
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))* v% c4 K+ a3 ^" x0 z
  76.       {4 k1 i3 Q, t6 Y8 U$ J
  77.         /* 写数据到SDMMC Tx FIFO */
    8 h% v' }4 m; S
  78.         for(count = 0U; count < 8U; count++)
    , ?# }  y7 U! |
  79.         {, L+ u5 P; ^+ }) Y
  80.           data = (uint32_t)(*tempbuff);
    % Z$ |2 o! o" D1 P
  81.           tempbuff++;- ~7 G0 p; X9 F' e9 j5 p3 a% ~
  82.           data |= ((uint32_t)(*tempbuff) << 8U);
    * @7 Y5 D5 C2 a% [: a1 O! K
  83.           tempbuff++;) H! T$ h3 w# P
  84.           data |= ((uint32_t)(*tempbuff) << 16U);+ y6 A! |/ K: W1 f" {8 w& `
  85.           tempbuff++;& G* y- z% K0 G+ M, w' l- X, z
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    % j6 [5 ~, ?; L
  87.           tempbuff++;7 q, L3 m( z5 {
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);
    ! I/ J5 F/ P' I& U" o% g
  89.         }
    ! {1 A, h7 x- T' a) S
  90.         dataremaining -= 32U;
    2 p4 M1 z7 v: d' l, J' W: g. Q1 p
  91.       }6 ?: M8 ^/ _  K: ]% W5 q: l
  92. . G; w5 s7 k* n8 y1 _1 c' l0 O
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))$ u/ A+ h! |) y; @* O
  94.       {# k* }4 x# e$ |# N
  95.         /* 清除所有静态标志 */2 W" J+ ^! c3 B. s: ~, R) L
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    / [: M) v1 O8 {: x( p0 M+ l3 J: e, \
  97.         hsd->ErrorCode |= errorstate;
    0 s9 |2 R3 x5 @8 {
  98.         hsd->State = HAL_SD_STATE_READY;- E% W9 M+ A# v) o& e
  99.         hsd->Context = SD_CONTEXT_NONE;
      D# E0 E, b) @+ K$ z
  100.         return HAL_TIMEOUT;
    & w$ w4 B$ L! K- \
  101.       }
    3 m" W6 G5 F4 j
  102.     }" q$ O  B8 F+ ~% d
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);5 n3 N1 J9 n* w7 u7 [9 S, c( C

  104. 9 i6 A$ V2 S5 \
  105.     /* 多块写操作,发送停止传输命令 */
    , A$ l% V) n& m: {" c
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    ; g. S- T* @9 S% v% s+ a2 j' I/ s1 {
  107.     {
    7 F" w5 r; Z  d) Z* A
  108.       if(hsd->SdCard.CardType != CARD_SECURED)* B" g9 E* ^$ h. e1 `6 v, B6 ~" J
  109.       {: Z& e6 M# _- m5 r- l3 ]
  110.         /* 发送停止传输命令 */! S/ z* j) W4 |% @
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    / H9 R- E" {5 g0 C+ n( G
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    ; F' K% u' A) R- l" {  r
  113.         {
    6 }& b& _+ J2 ~, Y; S8 b
  114.           /* 清除所有静态传输标志 */) _+ \$ k1 }* ]+ M; L: @
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);. y. t% l8 y. R* K
  116.           hsd->ErrorCode |= errorstate;$ D  U& J# z5 q. d9 B1 o% q
  117.           hsd->State = HAL_SD_STATE_READY;
    & l5 ]2 |4 P. q  C' m) ^
  118.           hsd->Context = SD_CONTEXT_NONE;
    ' O0 A. E2 I6 O9 D6 _
  119.           return HAL_ERROR;& u6 D5 }% Z8 S  `
  120.         }0 c/ C/ r! L# r; i5 F% C
  121.       }
    4 C0 g7 @0 c- c* _* E/ i6 p
  122.     }! L4 @. w% D/ @

  123. $ g8 M! B: l7 p- q
  124.     /* Get error state */1 k3 l; N. E" a, A# Y* d
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    1 m3 R0 t3 I+ c2 O. t7 J; g
  126.     {6 y: u0 Z" d! ~0 N' L- f
  127.       /* 清除所有静态传输标志 */- {+ V( {# w5 _9 \9 E
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    " J/ k8 C& g; I. A) D* n3 ]& e
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    1 Q1 w* q4 c7 }9 I3 G6 D2 ?1 ^
  130.       hsd->State = HAL_SD_STATE_READY;5 q& X: Y  N( h. A" s9 t- ?1 y
  131.       hsd->Context = SD_CONTEXT_NONE;4 d' z4 u& s1 |9 W
  132.       return HAL_ERROR;# Q- J# a. d& M; f7 `, p$ ~4 ?- b
  133.     }
    3 w/ W: F: `8 W  e7 l$ v
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    4 c$ m3 W6 U0 A, Q6 o0 [
  135.     {1 w) @: P; u% I. F( p
  136.       /* 清除所有静态传输标志 */" Q8 J( F7 S  e+ k6 x2 `
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    4 e) p( J2 c( n) S
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;) d" _" M* i+ N9 S, J& H
  139.       hsd->State = HAL_SD_STATE_READY;, \9 h6 ?% P  P( U0 e! z, p7 h) s
  140.       hsd->Context = SD_CONTEXT_NONE;
    ! g  \, S% h5 V2 j& }' ^
  141.       return HAL_ERROR;2 V; N# `( `" ]
  142.     }
    ' x# k, {# o, Q! `+ E4 q8 y
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))# K! w2 g1 [+ d/ F5 q. Q/ }
  144.     {5 D6 d! F8 l" k0 u
  145.       /* 清除所有静态传输标志 */
    # ]* c& ~1 Z2 x
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);& K* a* o( U2 O' o+ g
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;4 b4 {; j! C- v( }; g0 g1 b
  148.       hsd->State = HAL_SD_STATE_READY;
    . }9 W$ a, d8 j$ p
  149.       hsd->Context = SD_CONTEXT_NONE;# Z: p; F/ q' t- H' s( @
  150.       return HAL_ERROR;9 i# b- i, j: a1 C1 k
  151.     }
    6 U1 q3 q- Q& K7 T3 ^. e
  152.     else
    6 R/ h# D: C8 d; M7 S9 B( u
  153.     {& }5 q! K7 m# C9 v% L
  154.       /* 什么都不做 */
    # q: P% Z4 P( c" j+ g6 g; G
  155.     }
    # W* C& h; u, u; v' r+ D
  156. - w4 \; @* V, }, ]4 z# i- M/ w
  157.       /* 清除所有静态传输标志 */+ j% z% q( h3 ~/ H. L8 d
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);9 m, I- x% N+ C( j5 G3 n- Y6 f

  159. 6 a) S1 D+ P* f) c8 Y( G
  160.     hsd->State = HAL_SD_STATE_READY;9 s! X/ G) b+ R. e. A) A
  161. ! r3 G% m5 H; F. C3 q, M: K
  162.     return HAL_OK;4 F4 ^2 \1 x3 a% I% Z7 ?
  163.   }3 T) c+ P/ k- y6 O; }
  164.   else3 B/ ?  e8 e0 [7 H' s3 d: T
  165.   {
    . E8 P, L5 H4 d
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    & H. z1 \1 l/ j% S/ V6 `
  167.     return HAL_ERROR;+ X" R! J9 \" R2 T0 X
  168.   }
    ( [- y6 R6 \0 E# w0 Q
  169. }
复制代码

2 r, t! C  U' j# ?' m函数描述:3 W5 t4 D6 S" e! z5 p

+ b9 [) Z4 b4 S此函数主要用于向SD卡写入数据。0 [, G# H+ d! N% o4 D
( a* i, h, t$ F, ?* q/ `$ E) M7 I
函数参数:% u! x0 V, k. w3 o2 T
9 R4 l7 v$ w5 y! O9 K7 G
  第1个参数是SD_HandleTypeDef类型结构体指针变量。, [: l7 j4 k4 M0 o2 B! ]
  第2个参数是要写入到SD卡的数据缓冲地址。1 N, `5 e, V, {' g& P* L
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。/ t5 |  |4 j9 _6 b! ?: E4 k
  第4个参数是读取的扇区数。9 b4 C' Y6 L0 m0 m* \  ]
  第5个参数是传输过程的溢出时间,单位ms。
- ~$ l$ b2 ^; L  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。# I: a5 W+ t$ D" K7 }; _
使用举例:
4 c  U. w- A) a6 r' u
4 r7 K5 Y+ p' ]$ X
  1. /**
    5 i+ `% H8 ~+ c. t
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.0 l" q7 e2 ]& F
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    8 N" Y# C# Y( G0 [  L
  4.   * @param  WriteAddr: Address from where data is to be written
    6 T, q$ k" h$ z; e8 H% `( ?
  5.   * @param  NumOfBlocks: Number of SD blocks to write- g( j8 q( j2 D' E' U2 P/ L" `  s
  6.   * @param  Timeout: Timeout for write operation1 p. P) \1 g; s
  7.   * @retval SD status
    ' Y8 y3 H0 ]4 t
  8.   */
    1 C2 }" `: w0 V0 Y9 S4 J
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)8 v3 W: f5 h% B- a4 l0 {
  10. {
    7 ?0 y6 d& s5 H2 J/ t
  11. : \* K! G1 @- Y$ z  ]6 v
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)0 F8 C; x8 o( q, l9 D( V8 g  j
  13.   {4 p3 D9 Y# q+ f& J" F
  14.     return MSD_OK;8 {# _# I& r3 U+ A/ {4 e8 P" d
  15.   }: ^" l* B" S. k) M0 f
  16.   else- `3 S+ t  `* s$ D+ G# E3 ^3 O2 r
  17.   {
    4 c, q, f& H, P6 q# U6 w
  18.     return MSD_ERROR;
    . k  x* {5 j+ \, e) C8 r& Q. ]. C
  19.   }/ ?) o' d: A) x1 [' X7 `
  20. }
复制代码
& K2 u9 [0 o4 K( l0 z" x+ N
87.4.5 函数HAL_SD_ReadBlocks_DMA
4 {& u# M  D( n- L+ e: C函数原型:
# W# C5 Q2 \" f- X* N% f, B8 [( v# U4 W" G9 [2 b
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)+ a/ o+ f  \/ X2 _/ i
  2. {/ S. p: d# Y0 j- R
  3.   SDMMC_DataInitTypeDef config;
    # _1 Z# F& o, D
  4.   uint32_t errorstate;
    ' l9 m' ~1 n) B4 T/ C" d
  5.   uint32_t add = BlockAdd;! E5 o9 k/ \8 E2 i# R* _

  6. + \( O* s% }# ~; h# e0 W
  7.   if(NULL == pData)* ~0 P6 t+ S3 g5 P9 I1 D$ q
  8.   {
    ; W& [- ?% ]7 a7 R9 s* Y: W0 i
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    & X" U5 B  G" k: S+ r. C
  10.     return HAL_ERROR;
    1 ?) k# G: |( w5 p
  11.   }% d! b! Q/ k* t0 D+ D

  12. 8 R$ a! S* u+ I) o4 f
  13.   if(hsd->State == HAL_SD_STATE_READY)
    6 N5 O- m5 M, _: T7 J& i
  14.   {0 A1 o6 ?. |+ L* h2 b% Z$ x0 Z
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;2 p* G' z5 `% O* l8 w0 ^0 u# i

  16. : I+ {+ v8 b7 F7 H8 A+ O2 K
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    * {* W+ l) J* c4 Y' E) ~7 I6 e
  18.     {) H& c# }6 W' N9 w$ L0 P' @8 ~& F
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    " T% o, D/ a# j% u$ I
  20.       return HAL_ERROR;
    , b) Q8 h2 r( Y* T: _
  21.     }3 c0 T; @9 Z. c
  22. . g' Z) J( i! h; e: C& N0 ?
  23.     hsd->State = HAL_SD_STATE_BUSY;
    ) n  b; b0 p8 t5 Z. ~7 x' N
  24. ; P: W" }. H4 u+ ?- E2 H
  25.   /* 初始化数据控制寄存器 */
    2 u" v: m2 r4 m1 Z( u; I
  26.     hsd->Instance->DCTRL = 0U;' F0 j+ a" \6 f

  27. 2 m# C7 z7 f, g/ G. h9 }0 o: l& _' e
  28.     hsd->pRxBuffPtr = pData;
    1 t0 @8 q- a* K6 n
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
      {( Z& Q* p5 D! t9 m

  30. * |) k7 z* B7 ?" W2 f
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    : Y6 q  ]4 x) ]) ^9 k
  32.     {
    2 B3 v( u5 X' E: J8 W: d3 Q
  33.       add *= 512U;
    " V4 H/ R$ N: u2 B; @/ m8 L
  34.     }
    2 @; R; f- P. d& ^

  35. 4 O+ s# ^+ d) m8 G- I5 `
  36.   /* 配置SD DPSM (Data Path State Machine) */& a: N- |, j/ x% B6 k
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;. @% T, U5 D1 ]8 V( r  f. B+ }2 _
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;# \0 Y) @( B6 N$ A2 G, P) C1 B
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    8 }9 f- ~- C4 F
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    2 C9 w! e0 r: h3 W' b0 B
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    " z4 c$ ~. T. P6 M( S
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    4 r* h3 l- _8 |3 S. Q
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);# A% ]. k2 L+ t. P$ X# s9 o
  44. 0 m8 v5 I, t6 ]' e  J1 C7 ^& d, f
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);- V! b; V- @6 k& ?4 z
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;6 U) C( U2 ~6 a
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;- u/ }! K$ f$ N: A) g

  48. + {+ t) X& Q! [6 G/ m. h1 i' P7 @
  49.   /* DMA方式读取多个块 */5 H! O# W' z: s( v$ h/ J- F
  50.     if(NumberOfBlocks > 1U)  n9 A4 h% J  d) r: g1 P
  51.     {) A1 N, r* w( r9 L
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    # e6 j( ]( g! a8 H* ~

  53.   H' @+ Y( z9 g3 f7 K" o/ j. W+ v
  54.    /* DMA方式读取多块命令 */8 N2 U8 g5 x8 S) e9 o
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);6 |, B6 E7 ^3 l
  56.     }
    / q  T7 U& O; L% z4 C: A0 o# x
  57.     else4 s6 p! P& k) w. n8 u2 o
  58.     {$ p8 I! N7 J' r% t+ \
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);/ G, u* m& E, o% X3 L

  60. ( d, Y4 S% Q9 ]. n6 r
  61.    /* 读取单块命令 */% N3 [/ b' b9 S4 l- y
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    ; d5 F2 \: u! R4 U  `
  63.     }
      l  f4 T$ a+ t1 M( \1 b& o
  64.     if(errorstate != HAL_SD_ERROR_NONE)* I, X2 t- u, E
  65.     {
    1 W9 h, Q' r+ ]# z* _# ?: G
  66.    /* 清除所有静态标志 */# a" T4 ^8 M, H% H1 L8 e. b3 _) S
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);1 F8 V- D. f) \* g
  68.       hsd->ErrorCode |= errorstate;8 S1 o( k" F* O& [' I9 \7 G
  69.       hsd->State = HAL_SD_STATE_READY;
    ' L3 D, L' P! n6 k# C! m
  70.       hsd->Context = SD_CONTEXT_NONE;
    1 x$ R- d, t- n* d9 j; f
  71.       return HAL_ERROR;- ^2 t, ~- V9 E- P0 p% B3 S  z8 s
  72.     }
    0 D/ {" E3 e* }( H# D0 U
  73. " N) E3 i" n! L* w/ O7 C% d' _
  74.   /* 使能传输中断 */
    * x7 G( h$ U, p( q0 n7 ]
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));# G0 a) X3 g. G% k& p+ R8 P

  76. 3 \* J" I/ X" \" b3 y2 M

  77. $ o9 s  Y; ?  t2 m) G1 r' p
  78.     return HAL_OK;
    ' j) @) O0 h. G9 N7 t  K% H8 u
  79.   }
    " g, E' ]; l/ S" B; q* x
  80.   else. G$ B, B+ _0 E% r; P/ F6 I
  81.   {0 h3 Q- [- F0 k" g2 [3 {
  82.     return HAL_BUSY;3 u5 e) c7 F& K7 d
  83.   }
    7 R9 ]" n% M  T, ^/ Z9 S6 j9 P* h
  84. }
复制代码
2 t2 L) R7 c, d/ ^) n3 l7 v7 G3 V
函数描述:; ]/ W; \( x- h. G9 W, e

) l* w# m. Z4 \$ t% }- c! A1 O, [此函数主要用于SD卡数据读取,DMA方式。
3 }( a" r; V" E% p+ q9 y5 G3 I/ b: \' R7 p% \  Q! B5 A
函数参数:
. C& k. z$ u/ i) V2 ^. q: o% V
5 y, ~6 n; r" W  W1 d$ }8 G  第1个参数是SD_HandleTypeDef类型结构体指针变量。
! A1 M& ~4 ]' y7 U; |  第2个参数是接收数据的缓冲地址。9 ~& P0 W5 J* ]6 k  |$ D. n; B0 L% W
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。5 d5 W# L) d8 K; q
  第4个参数是读取的扇区数。" c2 M. s1 @3 _) D
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。7 L. G7 J* H8 E1 l6 {
使用举例:
" R) Y- @8 `7 s
1 H& N3 N! {& c5 h! j  b
  1. /**4 |, g; W4 @/ l" m" D0 W1 G5 z
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    : Q+ J3 ^( p4 i
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit( Q; a( ?( P. b2 [7 A! v5 A
  4. * @param  ReadAddr: Address from where data is to be read# m" V2 r6 E3 \+ u0 u0 A- x( b
  5. * @param  NumOfBlocks: Number of SD blocks to read
      @% Q" s* Z1 U: _# ~  ?
  6. * @retval SD status
    - I+ D+ s0 C1 z( b4 G
  7. */9 `3 D' l; k3 J# ~" e* c
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)( o% r! W- G' A3 F
  9. {# |) @' w6 N, M' x& L
  10. , ?7 a* ?# W+ ?
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)7 j& i9 E5 K) ^
  12.   {
    $ o+ _4 Q4 {6 D% m
  13.     return MSD_OK;2 I9 m1 d1 z4 `
  14.   }' k  ?; r3 l+ }/ J
  15.   else
    * F# _! i& n* ~6 u6 e
  16.   {, {4 I. j9 [/ p, x1 G
  17.     return MSD_ERROR;
    ) J+ H& n% o2 |: e# u
  18.   }) `4 S8 Q* u: X0 L
  19. }
复制代码

, P2 h  R# v2 [  w/ d6 F87.4.6 函数HAL_SD_WriteBlocks_DMA+ z' x6 ^4 T8 f- F
函数原型:3 G# k; e; s/ S$ p$ q- B
& x7 `0 |3 g6 Y/ S7 z8 u" Y% {# @
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)  b. {) n! J8 ?- f( H) V% }
  2. {
    / P$ z5 y3 E9 ~) Z# E4 }
  3.   SDMMC_DataInitTypeDef config;  h6 |6 h; p# q. n: U: T0 c
  4.   uint32_t errorstate;, e. |* [4 \1 l# y( f* ?
  5.   uint32_t add = BlockAdd;
    0 a8 |* \5 _8 R  n" ?4 P( H! i
  6. $ X2 y: J$ |6 a4 U
  7.   if(NULL == pData)
    , a0 ^7 L: z, t6 k) A# P+ f
  8.   {* Y& {0 k5 o$ N& K% S% y
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    8 Q" O. Q, l& T4 F5 t
  10.     return HAL_ERROR;
    9 r- K* G/ B2 X0 N+ I6 E* z# O/ @) Q% ?
  11.   }
    + [4 f1 e% P+ L1 `- D: s' a' k
  12. ! S+ ]5 T  |/ Q, ?* z
  13.   if(hsd->State == HAL_SD_STATE_READY)$ ~6 t% Y  x, L6 S
  14.   {% R+ J& Z: o2 W9 R
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    5 `* i7 V9 Q) ?, Z7 K/ ^

  16. 9 @5 t: I) {4 [; J- B: `# ]
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))5 Q3 ?. B4 z" [' C9 \2 G
  18.     {) ?6 T8 ]8 H( |2 ^$ y
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;! H+ P  n+ a0 _" K, s
  20.       return HAL_ERROR;
    3 ~! T/ k) X% U3 l( R! S
  21.     }8 O" C3 ], C/ `3 z; x- r

  22. , e8 O' u3 C7 q- c
  23.     hsd->State = HAL_SD_STATE_BUSY;5 p) P3 N2 x+ r! C1 d
  24. 0 A1 n  ~* n1 u0 N
  25.   /* 初始化数据控制寄存器 */( [# l' M7 d7 }# l$ n
  26.     hsd->Instance->DCTRL = 0U;
    2 k' T3 K. h) r6 u1 Q/ f
  27. . w  b+ ~$ t; E& K5 F/ {6 y0 x) c' l. H
  28.     hsd->pTxBuffPtr = pData;
    , Q7 I$ t. q% S/ g, M
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;: y9 k- r! w8 I1 F0 j+ [3 _2 D) X
  30. 1 K: J$ h# \0 v$ X+ W$ e9 E$ r
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)0 P/ {8 |1 L; @5 t4 ^/ |8 Q* x
  32.     {( r  x! L, A3 G* p
  33.       add *= 512U;3 N; y7 T) T. Z: @& G+ i6 D
  34.     }1 ~; r0 j5 U: _8 X  ?& y

  35. ! V$ A9 _; V# |) I- Z$ x4 ^3 ]
  36.   /* 配置SD DPSM (Data Path State Machine) */
    7 k, X# s$ D5 }7 A% W5 Z& n2 w
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;- v9 m4 s2 V9 Q2 P$ W
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;: Z- p9 V; W8 \) _' U+ i  l
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    . \! l# r7 o7 J0 w! j
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;/ ?" H: m- n4 s: ?: O* \: S
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    , r7 T6 t5 @7 a+ L& ^7 x" G
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    + z* `& r; K* z) j
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);# R$ Z' L3 }' _- W- u

  44. . c+ J2 {: g! W# B
  45. 0 h) Q! F0 [7 m4 [
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    ( I" @' u( L9 M, M

  47. 0 ?7 Z/ [; q  s5 j3 z
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;+ @' H6 |0 u# t2 E2 a1 ], B
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;) m/ S" _# b% T/ L8 u2 ]
  50.   H/ v* t, o) ^3 \2 ?. r
  51.   /* 查询模式写块 */" x( k/ L' J/ H5 s6 G' p
  52.     if(NumberOfBlocks > 1U)9 Q$ |; c! a8 ~
  53.     {
    ; @  |3 p3 L4 g, l
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);. V5 w1 h6 Z, y5 L) M% L

  55. 6 J8 K/ p, M' c+ _' W
  56.     /* 多块写命令 */2 o& Y& A3 \4 ^
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);) n7 s3 K0 o) q
  58.     }
    * j6 ~8 x1 A! @
  59.     else2 O+ u4 _" ^7 V. h4 B8 E. {! L# c
  60.     {7 L1 ~, Y9 ~% V+ S4 @/ Y- @
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);* @* B4 C" W8 R# D! \
  62. * P; d& F& }1 x: D% q1 b
  63.     /* 单块写命令 */9 Y9 X) @% A9 H6 U( c! {
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    9 s7 G# v' I6 e
  65.     }; A4 \' P/ ^9 n; q$ o4 Q0 ~
  66.     if(errorstate != HAL_SD_ERROR_NONE)
    5 @; A5 A8 g9 e$ ^/ }3 r
  67.     {
    7 W$ C4 o: H6 R8 s
  68.     /* 清除静态标志 *// R. Q/ C. o  E; m0 E: |2 }  Z( R
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' w% X- m& T% _: h4 C- _
  70.       hsd->ErrorCode |= errorstate;0 S- C" ^" _, _- l' u9 y" @
  71.       hsd->State = HAL_SD_STATE_READY;0 j1 ?+ m+ C; }) @" S8 ~& G) o
  72.       hsd->Context = SD_CONTEXT_NONE;
    1 `9 h1 \- ~5 p) E# |. `
  73.       return HAL_ERROR;5 a8 q/ {( n0 t& L" w+ O! d
  74.     }+ F7 v3 h& I$ L( |

  75. 0 S5 n& Q4 _3 N; z3 A4 M  E
  76.   /* 使能传输中断 Enable */! i9 b  n. D% d8 \) a) @
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));' c4 l5 ~* q8 c( P5 t; q/ `  a

  78. ' u1 H$ S0 T6 c3 ?& B. T. i
  79.     return HAL_OK;
    , _1 P3 j6 o6 a. ^+ B
  80.   }
    ; T( S1 A$ J# H& N- {9 P
  81.   else
    ' t- V+ c# x. l5 {- J% A* w( y
  82.   {+ T" I) q# w% j  x
  83.     return HAL_BUSY;$ J$ f2 b7 M  b9 X
  84.   }
    2 W" b4 ^9 I* Q7 R6 \% a7 y
  85. }
复制代码
5 p% G5 [# u( P9 `* u7 p& [+ B  u
函数描述:
" S: S1 Q& z7 X6 w% k! A* d. \! V5 U1 \) G6 {
此函数主要用于向SD卡写入数据,DMA方式。  Z+ D: A; V% C+ t+ o# A

) N7 |& r% o1 D1 ~函数参数:
8 K; H) Q9 O; f( ]4 H
/ ]$ z6 {' C2 t( g. \5 C9 X) H  第1个参数是SD_HandleTypeDef类型结构体指针变量。; r  ], V9 Q5 F/ ]! B- d
  第2个参数是要写入到SD卡的数据缓冲地址。
, u/ Q4 S: ~1 _0 ^+ I+ B  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。2 w6 S7 |  C6 g" s! v
  第4个参数是读取的扇区数。
. [4 j/ l5 b  ~  W: ~  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。# c" s. x- O- N1 ^. x+ O" X6 s1 e
使用举例:1 ]: R9 t: u' z8 ^9 J
% A# j# Y5 Q4 q$ \: f% J
  1. /**8 c" e8 A9 @8 o) }' a" F( z
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.) e2 j$ t! o! i
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    , d( q" B+ F" F; G  a( L
  4. * @param  WriteAddr: Address from where data is to be written
    : \" m! K6 Z- {( t' p
  5. * @param  NumOfBlocks: Number of SD blocks to write
    ; Q* p* J) T1 L7 S
  6. * @retval SD status- L* D: `0 R% y* `. m0 ~" A
  7. */" {, Y, V( m% `& X( P, K8 \* G& o
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)4 z2 A$ N8 t6 O$ x
  9. {
    ; A) ?: `1 k% `3 W8 |$ [# a2 F
  10. : q. ]: c  t& ?* n
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    0 `; l- ^+ E8 U9 Q6 v
  12.   {. b8 N6 ~, ?9 Q$ B
  13.     return MSD_OK;
    1 _/ H$ |# e$ T& X$ l+ s
  14.   }3 K% n, E* m% `( c2 m& a( R( }2 f/ G
  15.   else
    + z( ?7 q" ?) G; R
  16.   {& C1 [# H& B6 \( j. T, N$ M
  17.     return MSD_ERROR;9 E  p( i! V4 N! z0 i& {
  18.   }
    0 \7 }* W2 w. ^/ y
  19. }
复制代码
' z( r# N( \, O, B7 Y' Q) U
87.4.7 函数HAL_SD_Erase: p7 o" y) n/ n
函数原型:
+ @8 R; D, q6 ~- @* j( V- w% m0 g7 p! _! n
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd); [8 f$ H7 {! a: Y8 B; _# y- _
  2. {
    8 y( _! }5 n. o" m3 H
  3.   uint32_t errorstate;
    $ t* Q7 u! W# f0 G* _& n9 P
  4.   uint32_t start_add = BlockStartAdd;
    # `  w# B8 N7 p
  5.   uint32_t end_add = BlockEndAdd;
    ; P" ]" v9 D$ h/ p) i% X; w7 p

  6. . A  J, Z' S( i0 y
  7.   if(hsd->State == HAL_SD_STATE_READY)
    6 J/ U8 _8 u0 g" J
  8.   {9 Q5 h, [1 o$ l0 o, M- p5 @
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ; ]- X! v& A8 I
  10. 2 C: \* H: E0 o
  11.     if(end_add < start_add), ?2 h8 |0 i0 D* z9 G3 c
  12.     {2 {, |7 d) B+ Z' l& O0 [
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    + A& |# U3 {$ R( s/ k& w
  14.       return HAL_ERROR;
    3 A9 \1 }, u* W; x
  15.     }9 d8 N1 c5 ?  n( g
  16. 0 i2 h- |( D2 }' ?, b' F, L
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))0 g4 x5 Z4 {3 ]1 O. H; L+ j0 q& v
  18.     {
    + U: m1 G# c! r. A6 G& M$ @
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    # T9 y' o: G0 o9 R8 T( ~
  20.       return HAL_ERROR;
    7 u& W8 B( X' r1 P& s
  21.     }+ C& h( W' K9 E& ~" e6 j7 @( r

  22. 8 d9 V9 E, y- I) E1 t8 Q+ ^
  23.     hsd->State = HAL_SD_STATE_BUSY;
    9 R) r6 n$ }3 W; q( y" [! b

  24. 4 C. |9 Y. d& G5 z+ h" {! v: G
  25.   /* 检测是否支持擦除命令 */
    % W1 m: m; R  U2 r
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    4 ~" ], j$ }7 c& x. {+ ?) ^7 {
  27.     {
    4 l( x4 f5 h/ |, H9 u
  28.       /* 清除所有静态标志 */
    / z+ \3 ~5 Y* `! i  o3 l
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);% ~  `7 y' ]8 {
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
    0 {1 G" f; n& D, i) U
  31.       hsd->State = HAL_SD_STATE_READY;4 P* U6 f: Q9 {; Q+ W+ k
  32.       return HAL_ERROR;" P4 J7 N* h, d+ h, v
  33.     }
    ) ^2 M9 s) A2 y& n" }" y6 I! V

  34. ! e% X) w( H: |4 h9 |2 K; {$ e& C
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)' H2 n) ]& R6 G% @" Q' X- w
  36.     {
    : t! O! J" ^; \- a) |1 D$ `
  37.     /* 清除所有静态标志 */
    - u& D8 U9 I+ M" Y: g
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);  `* d& a$ I6 m0 c' n& f% C
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;. [) ^8 r) B. C4 [% z& x
  40.       hsd->State = HAL_SD_STATE_READY;# D1 ?% B) c+ y/ ?9 W6 U
  41.       return HAL_ERROR;
    . K- S0 B& B$ C  N5 x3 w6 L
  42.     }& r/ d, V1 A* s' v) S

  43. / u1 I0 @5 G: d3 ^6 _
  44.   /* 对于高容量卡,获取起始块和结束块 */7 A- E% I% L6 A5 L. W2 z/ G% J
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ; q' [8 M$ R6 v3 B
  46.     {) j6 b8 H! }, p
  47.       start_add *= 512U;
    : s% |2 |, c- s; [5 ^" |
  48.       end_add   *= 512U;
    & p1 Q! ~( Q2 A0 p/ w/ Y3 l. v
  49.     }
    ) A2 ^4 D7 \' c' B

  50. ' X& r, i; b( a3 T' h3 O: L
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    ( V1 _" R! V) I$ b
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    / r4 O, D# B$ ?. [/ p  M+ f0 \- d
  53.     {$ \$ F  v. }0 x6 l% {
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */; p9 }7 J- _6 d: s8 V1 p5 l
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    ( O( g! u1 t% o& g1 U3 c1 Z
  56.       if(errorstate != HAL_SD_ERROR_NONE)$ Z, x: ?: b& `4 R, ~
  57.       {
    6 C9 Z# d0 p$ {( r# z9 \# z
  58.         /* 清除所有静态标志 */
      b$ O( ^% z. t4 _, K/ m+ D3 T
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    4 c! F; ~7 e1 j; O2 B
  60.         hsd->ErrorCode |= errorstate;  M1 k& s+ D8 H$ u3 f  U( @
  61.         hsd->State = HAL_SD_STATE_READY;* r9 p9 b1 w/ {. Y/ n
  62.         return HAL_ERROR;
    2 [: \# F+ R) Y6 F2 E$ O7 [  q3 w
  63.       }' ~/ {4 v, O* N

  64. 8 T+ R* C. ]- g
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */# |' n+ Y6 p2 O- [, ^. Z5 [) x
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);# b, q4 d& c% y* k6 f( ~, @. \
  67.       if(errorstate != HAL_SD_ERROR_NONE)
    ; t. e  L# M- V5 V# U& O
  68.       {0 f. j: X. c4 T3 J1 A4 a
  69.         /* 清除所有静态标志 */) L/ }) `2 X, o
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 V$ m2 c$ F) e) n" Q6 i
  71.         hsd->ErrorCode |= errorstate;
    ) a; _: ]6 r8 A
  72.         hsd->State = HAL_SD_STATE_READY;: |. j' s- U2 f- k- ?4 n
  73.         return HAL_ERROR;
    1 {- _+ B5 x- b$ n# ?1 F
  74.       }( ^- G2 _, g' w- o
  75.     }6 ?! W0 p0 u5 B: {+ H$ }

  76. 9 ?6 w: {1 s9 Y+ S* Y8 P1 q
  77.     /* 发送CMD38 ERASE命令 */9 p) ^  L4 q/ E: ]
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    0 n0 b; F& D% z4 i8 o1 N* E
  79.     if(errorstate != HAL_SD_ERROR_NONE): ^% w" w  A) n5 X
  80.     {. Y& F0 p. M9 L& e1 u. P
  81.       /* 清除所有静态标志 */  x& D: Z' Q0 w; w4 f
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 g: i$ [- |& t& I6 T9 Y- h6 t
  83.       hsd->ErrorCode |= errorstate;
    ( k' v  [. s# \+ I* K  |9 F
  84.       hsd->State = HAL_SD_STATE_READY;
    , a* v, I. Q* l3 u+ b* U, L
  85.       return HAL_ERROR;
    3 ?( ]1 w+ S4 K3 y2 o/ n) f4 C7 u$ m
  86.     }  Z& N1 Y% k( L* ?

  87. " I+ Q# N" X' D8 E& T; N
  88.     hsd->State = HAL_SD_STATE_READY;
    2 @8 d7 Y! w" M+ j- y  B' `( e
  89. ' z# U. |, T6 V, a* A
  90.     return HAL_OK;5 ~% a- e+ `6 Y) {1 ?* ]. t
  91.   }( G7 ~; J# m$ F( ^
  92.   else
    # P: q) {* ?  I: j* `# l
  93.   {& ~8 c% G2 T# {; \1 E6 M
  94.     return HAL_BUSY;, H  K/ F1 e3 G
  95.   }
    ' m8 Z" B% e8 F  M' W
  96. }
复制代码

1 A) t8 ^' p/ r函数描述:
! y& F7 J, q& t; `& Z- @. q
- B  h' g: K% j" U* J- r5 w+ r此函数主要用于SD卡擦除。
! e2 l  |8 I+ K6 \1 L" _; J
1 e6 p: O+ W3 k+ |1 B函数参数:5 w) [2 Y) o6 r+ P5 q
3 p5 |7 o& E# j, `$ y
  第1个参数是SD_HandleTypeDef类型结构体指针变量。( B2 \: C+ Y: I' q/ h7 E5 i/ Q! r
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
! G8 z  m, T8 q: B" z$ X  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
+ Y! S! ?, \- r4 G9 @  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
7 a  O& M% b3 q6 M4 ]& A8 c使用举例:
, T/ J7 A/ S) a- a
; T- r  ]' H* t. w5 s
  1. /**
    4 _& _% l2 t% f2 c
  2. * @brief  Erases the specified memory area of the given SD card.( L! g$ v9 W9 e8 a  ?/ M
  3. * @param  StartAddr: Start byte address
    # s1 {! x  m( L
  4. * @param  EndAddr: End byte address
    - @" s) N, q$ C: N4 Z: a& N' U) w9 o
  5. * @retval SD status+ n0 }9 y2 T; H7 Z, B. Z
  6. */
    3 ?6 H; [4 |8 A8 |1 v6 R1 M
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)# @# _) X$ d! b5 v
  8. {* @# [3 {  Z6 U
  9. 0 t0 {4 ]3 V. y4 g" Y0 X7 Q
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)% E& V8 d% s" D0 M! [
  11.   {" k/ o( |! C! Z- T3 ]# ?
  12.     return MSD_OK;
    / `& m2 C5 a$ I: Z7 ]& g' h3 N
  13.   }4 B5 t/ T' O: U( q" m
  14.   else2 R1 \0 ^* i, X
  15.   {
    & c* g# x# Q' Z6 r6 }0 c: _
  16.     return MSD_ERROR;
    $ |6 |3 D& I3 x4 [5 e+ A: B& W
  17.   }
    % O2 a5 C# }$ K) [% r" b0 d: X
  18. }
复制代码

2 M) A0 q* L3 L; W; K% J" s3 Y4 H87.5 总结
5 ^' e# f  P! }- e/ @; c本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。4 e! c5 R4 u  J2 ]+ ~: c& X# W

- p6 t+ n; r2 U& j. `
( G: l: ]& ?8 h: x$ H% D+ E" A% j' o2 s
收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答

所属标签

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