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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示1 O( P  Y3 I  T& s4 v" V
  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
% j) c. o% K2 h5 I* Z$ e! ^, D& S5 M  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。+ m( I/ ]9 q- ~7 K5 W9 }
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。
3 Y3 [% T7 F+ |& t  SDMMC驱动SD卡支持1线和4线模式。: Q5 S" i" Q; w/ ~# F5 l. N  ^
  STM32H7的SDMMC也支持eMMC:$ N  X. i+ F8 q. j* G7 i
  . P& Y$ p7 O1 a" @. F9 `7 {
87.2 SDMMC总线基础知识
/ N& i: _" B$ d) z6 L87.2.1 SDMMC总线的硬件框图
! E" M& {7 w: L1 N- `认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。! W0 N+ n, s. J$ B

. _, I6 `0 |; [* K6 O! J$ @
6eea62abe623396815a50adc87205b83.png
- Q& m0 a: H0 @( O' Z0 D1 p
9 n# m( c8 {+ `6 Z
通过这个框图,我们可以得到如下信息:
0 E! t  V' g, @6 t. b
7 D9 d; a: b, E2 s8 t; q- y sdmmc_ker_ck输入
. H: W: |. |2 c7 C2 `SDMMC内核时钟。/ v$ k, `, s6 Z5 d* ?1 Z, [
, h/ ~! X. O/ D" o8 D- w0 n& r, C
  sdmmc_hclk输入
. I. \6 y1 ^( c8 ^+ [4 M8 U  dAHB时钟。
# J; Z5 X' `; n) N6 H
. C, v, i/ C& K& J4 m. m7 q) d' Y  sdmmc_it输出
" h) _: s9 d9 PSDMMC全局中断。
- J, L% w/ F+ B2 ?5 q& ~  [+ v; ^7 Z
  sdmmc_dataend_trg输出
- ~& l6 H  [0 l5 P( V3 j4 u5 WMDMA的SDMMC数据接收触发信号。
, w9 k0 v. t2 r  n9 r0 @. H" X; `
  SDMMC_CMD+ p( f1 v+ t* F. z8 s$ V
SD/SDIO/MMC卡双向/响应信号。* a, k; e8 A' I* m% {
) o8 J- D8 V$ j2 K) q/ S5 }( ]; A# q
  SDMMC_D[7:0]6 m7 f- |+ Q; a, H0 N  ~, E9 Q
SD/SDIO/MMC卡双向数据线。( k5 r0 m  H, X
% e7 f" q5 |! S0 G
  SDMMC_CKIN
2 }$ ^0 x* ~0 W5 q来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。: u' {4 m- v! K' O, M2 c4 @8 N2 I
( s1 F( v7 }$ l$ W2 N1 D
  SDMMC_CK
. I' e$ E# {# {SD/SDIO/MMC卡的时钟。
* Y- p& C2 i) O8 F% u" g4 }& E" Q* l; R% I1 v
  SDMMC_CDIR5 }' v3 R- p# J) W
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。8 \. x8 ~5 c: ~" m& {( x

) V* R6 C% G  K+ F! o# V$ v  SDMMC_D123DIR
$ T+ W1 Z2 \3 y3 USDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。4 X9 c* f, J$ `& T* A8 e

% `+ i3 Z' D- Q4 ~8 P& I" X  SDMMC_D0DIR
" I! h% P) m  T4 H) N7 b; i9 dSDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
# A; g( H& k& C9 m( E: l  D
* r3 ~3 Q2 a5 m4 h6 Y" S" uSTM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。! u( b( [! g3 ~# _6 u' p5 D
) `" _6 U; e$ U2 _
87.2.2 SDMMC时钟
, c. }; s& m% y1 [: Q4 D! lSDMMC控制器的时钟来源:. N: \; u7 R( L  W) r! W
- }3 g0 N8 k% @5 C9 J: s% e. H
676ec31792fcb80bee640ed979d48084.png
7 f! B9 j* @5 Y. h

3 ?! K3 _$ [6 O) z& T/ Y. `4 pSDMMC1和SDMMC2时钟源是一样的:
5 C$ p2 {* ]" d3 M  m% u
) Z2 R8 i2 g: m' q
79b1c69986d1ee5bc090bf1676f396fd.png

" l. }! c$ `: i. ~7 C
8 A) X- [  M, f* @8 n87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
' G5 P0 T6 x3 R注:大家应用时要特别注意这个问题。1 ~0 e" g/ K3 p' s; l

" \. C2 [& b" m4 P4 {" v7 {使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的5 L3 P( |! M; y  w% A
9 N% u! g: q( P& h' x1 L; e
6a5491d2f4a8740d838af58d034b7597.png
3 r: R! M3 B! k% y' j

5 W4 Z7 d2 f& C* \# i8 I87.2.4 SDMMC支持的速度/ n( P5 J. f% i" r# E. c
驱动SD卡支持的最大总线速度:! U3 Y5 G& h) p, B9 m) m, b" a
- H) _9 s& E. o8 w/ p
b70ce31107b38ea820dbc28c3caec38e.png

9 b# H. N4 i2 f) a
9 h9 m- P7 x* m) f. z% m, o; N驱动eMMC支持的最大总线速度:
  R0 {& z* g" m4 w+ M  q1 R/ h+ M; s. {! Z* q) w/ t5 f
843bf7a054944ba7d5d137ca84e1d4ed.png
: ~% u# N  }# c1 j

5 \$ ^5 T0 M+ S' n8 j3 d4 E关于这两个数据表,注意以下几点:( _7 u) K5 D; w9 i9 x# ?. f
3 K# L4 p5 G, j  _8 E" @
  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
* Z2 @# [8 u8 I8 Y' T6 Q3 B  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
, ]9 B9 H' m  w4 f) R  l9 y) ]& e6 p  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。+ s5 n0 j/ c$ X8 {5 I4 A
87.2.5 SDMMC支持UHS-I模式2 @$ h6 C& I; B3 D" p# g4 t/ M
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:  Z: {/ f7 h% c/ [
$ U3 ^5 A; H! s: `6 z
2b8e4430b8a60dc5a1b342d7c7f75f52.png

6 l$ g: i% D4 n" c$ N) O
7 G1 A" @  d8 R* N8 }7 `. m5 U
85f975745619c9afc64f8889289dad58.png
9 ^* m& i- C7 c" b

/ d& p* _7 X3 i; D( m87.2.6 SDMMC自带的DMA控制器IDMA
* ?/ E2 ?8 Q: x& H" K; sSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
* J! \6 k: W/ |1 e# C, _1 o4 [  Q
! z$ v7 J, s* P8 L; x7 E6 o87.3 SDMMC总线的HAL库用法/ p6 L3 u$ u3 d' v# h# m! R
87.3.1 SDMMC总线结构体SD_TypeDef3 _+ M/ S6 ]& ^" }3 n% }+ ~
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
2 K  u6 }/ o$ q/ L* K. E, r& u6 _1 A
  1. #define SD_TypeDef          SDMMC_TypeDef& g6 x& G! j/ ~! X  p- c+ ~( S
  2. typedef struct; J# V' s4 H' \) l2 v
  3. {
    % m7 G2 y4 O! ~3 ^
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    ( Z: l6 e0 U# |& X9 Z. Q) {
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    1 `0 i  H" z7 V. u4 s
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */
    . t6 @: T9 g* A% }
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    + [8 T9 O& f$ w! N
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    7 h7 \! H& F, k5 {- a
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */' h# e  J; u0 i& z8 `
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */* e9 o, g. G6 T* m. `
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    1 g+ e& ^9 `: O8 `6 {- i
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */5 _8 h( D- G$ _, }% Y
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
    ( i% g6 F1 f# i, S$ A9 p  K8 e5 s' p- w
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */: D( r. H3 `" S9 x9 k2 K8 E* E2 E
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  *// t; T4 D' {+ x& O5 U* E! u
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    8 M/ Y) E. C% C
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */# n$ }* A9 v3 c+ k9 w7 j0 [+ b/ e
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */3 e3 Z4 w& y" H. u, q% z. |& Q: u* s
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */) s% Q% u* r" \
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */0 \( e+ R1 z7 g  t" }$ `$ ?
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */
    1 Q% [- x# q# a
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    , V. N3 |8 w8 s1 e  Z4 _( ?1 h4 S
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    + A# Y7 J0 Q. ~1 t5 q0 }7 t9 o( k
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */
    , Y  g% `; h5 j% S! o
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */
    * }# l6 X  D! i" j' ^
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    - v) d7 O# [7 X: E  V
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    6 [- U$ M, r6 ?/ e5 k/ k
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */# I6 D. T1 `9 J
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC *// c- l7 K1 B& L4 z  c! a
  30. } SDMMC_TypeDef;
复制代码

2 o% z& x+ q) D2 Q这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
$ b9 H) ]3 B7 J; Y1 f5 n% C. F/ \2 k" e
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
6 h: N1 N9 X* P6 ^0 Y$ Q; ?) h4 ]9 q, o/ q- i2 _  S- h
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    , O) U( P5 X. o9 X2 O2 Z
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
% j% b: L  P5 Z
下面我们看下SDMMC的定义,在stm32h743xx.h文件。
2 ]. ?; p9 i( b* G+ x
; g. e  j& b) q7 j' i* k8 U2 u$ Z
  1. #define PERIPH_BASE           (0x40000000UL)
    / s7 C+ ~( C4 B4 S% c
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)8 p5 S( a- G- m8 F5 D2 E4 j
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)
    ' x; A' x; I; u4 I7 k* ~. m! v$ d) X
  4.   X9 a* c% j: s% `3 _
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    ; ~4 T' h' e% Z3 v$ c
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)' h$ x7 j( n. Q$ l

  7. $ x  _: a: t. ~) q* O
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    ! G; \1 z8 y5 \  L. _/ e; s
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

* V5 y  {& K  i6 A& A7 S我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。
+ Q' B/ ~9 x; F" V9 e% x& m( {2 ~
0 D& f" w' z; x1 w+ Y87.3.2 SDMMC总线初始化结构体SD_InitTypeDef+ S- c# E* c: b4 b9 L
下面是SDMMC总线的初始化结构体:( t2 o* L7 k# L5 N4 ~
- `9 T' D8 x- X0 ?, l
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    ( f5 L6 B9 T  a% [6 G% ]
  2. typedef struct
    ; x; O& s# N) n% w" v2 L8 |4 I
  3. {& t  {" v( N' {- N$ l
  4.   uint32_t ClockEdge;            ! W' l. G$ i9 h; C
  5.   uint32_t ClockPowerSave;      
    ; J8 f; w" L0 X
  6.   uint32_t BusWide;             2 `- I5 z+ M- k8 V. L' b4 A: A
  7.   uint32_t HardwareFlowControl;  5 a1 s1 f# {; T9 h' i" m
  8.   uint32_t ClockDiv;             % w  s6 V9 C: P2 J" B9 y
  9. #if (USE_SD_TRANSCEIVER != 0U)
    , H- r- {: c/ K# n* m( T' g, {
  10.   uint32_t TranceiverPresent;   
    , i7 Y% [* N% `- V! K
  11. #endif ( ^* H; D% S3 L1 ?
  12. }SDMMC_InitTypeDef;
复制代码
& l- p  B0 `/ t6 J5 L* X9 E* ?
下面将结构体成员逐一做个说明:- }8 v( W. x4 A( h1 }+ G
$ G# l0 ]2 @) q
  ClockEdge0 V/ f- ]6 a3 ]9 @  p
用于设置SDMMC的数据或者命令变化的时钟沿。: V3 r$ l/ y. }$ E( d& B) ^
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)
    5 _! r9 L- H& {  E' a% u9 A6 W
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

! Y0 \0 C. V  u" v3 V/ r  ClockPowerSave
# x! E5 x: L  {1 Y9 L用于设置空闲状态,是否输出时钟。
! w% M3 b2 g, ~% w& n3 [. w. N% o
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)3 ]& w0 t  N! p
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
/ H4 Z; ~$ E3 R5 z$ D# Q/ y
  BusWide
5 J; z. y6 u7 F# t& \0 O用于设置SDMMC总线位宽。  L3 ?  r  E. O+ K
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    1 ]: o4 ^" ?: J% C) N9 B
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0: G- }, W8 ?- ]8 P
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

9 |  g+ X, ^* j6 ~* M  HardwareFlowControl* h& ~/ T; h( [" X2 Y& ^) v
用于设置时候使能硬件流控制。: W' G3 h, c7 |
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)
    " m! ~* O- y5 |& j7 r
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

6 D9 ~/ X+ q" K8 l! p# U  ClockDiv
6 n* A3 W: S# Q6 U; G# y3 f7 C; A用于设置SDMMC时钟分频,参数范围0到1023。
( Y; Z. q1 g4 @/ a2 r) g6 H7 p1 S
1 z3 e2 z4 p2 \6 k; x  B! S  TranceiverPresent
8 q, i: b  }1 s. U- V8 R用于设置是否带1.8V收发器。
" T. x4 {- v# t' _) K4 W
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    % ?/ V; s7 t) c1 b' N
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)
    5 C6 ^; F! e+ A1 k
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
& J- J3 }2 U( y; w
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef! ^, E; M9 ?( A6 g
下面是SDMMC总线的卡信息结构体:: p8 U& C+ O' A5 n9 ]
  1. typedef struct9 q2 H; _; Y7 ^& J& G% o$ [4 T
  2. {' A/ c. f. G( N+ o) I0 b
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */% m9 G" L+ E0 t
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
    # S0 e% }7 Z4 c0 V  F7 y
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */
    9 U( l$ F7 g, R. O# y# l
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    0 y: E" u# s! C$ s+ S6 G8 z
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    % n( v( u( k' l- I! ~0 f  c. v8 Z
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    0 K; W6 T; c) V! ^; W- l3 P. E
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    1 Q8 m5 v5 S. Y- x0 }
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
      Z" I! F4 q0 {! f
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        *// c* q( q) `! C
  12. }HAL_SD_CardInfoTypeDef;
复制代码
. E3 I  f2 Z& ~0 r2 d6 H
下面将结构体成员逐一做个说明:
& P, l+ a0 p' F, @+ r5 Z  h, q7 J$ q/ }: E
CardType
! {- v& n, Z8 A卡类型。
; A- ?- M& Z' |# t
  1. /*!< SD Standard Capacity <2Go                        */3 l  m9 X; B8 B* V# L
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U)
    ! u5 ?( y  _' z  X3 C5 B# F& K
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */7 k/ j; [. \, l- o5 `% ?% E  e
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    8 c* W% D% Z" O0 \0 W
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

6 x; z, Y4 h0 Z# T+ F; H# ]5 u  CardVersion# f) F9 I, d0 H! O- S! O
卡版本。) f2 }& W+ v0 s7 N) e, a
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    6 e! T+ l! P5 H; c' q( B; }$ `
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

  o9 H) n* R% w& x) K. f' s, q  Class
: k- W) x' h9 Q+ @卡类型。
; F0 c4 S& z- p7 P; F
6 }9 ~5 r( v4 M  RelCardAdd2 p' m, R/ D" y* `: R1 ^
卡相对地址。
1 y7 q! |4 ?& ]0 R% `0 I6 e- L& W% ]6 D3 M+ Y* H$ \* L
  BlockNbr
8 u  q( e0 Z  M3 U整个卡的块数。% o! s/ p: G. r" H" S. v
$ T6 B1 e( O9 P
  BlockSize' _1 ?* W4 a6 J/ [  L
每个块的字节数。; j, b0 ]- }0 t
- r9 M3 }7 X# ?! r) T  L& U: C
  LogBlockNbr6 g( U6 B( k1 e5 v+ `7 @! w
整个卡的逻辑块数。
% u1 U+ Z  L2 i2 Y1 V1 x- m5 e5 c# R  S9 `3 ]0 Z4 V% h; s
  LogBlockSize5 Y2 ?' Y7 F7 b* A0 L2 ?
逻辑块大小4 J/ z5 T5 b5 o+ N9 I( m
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)6 L1 K+ ^6 Y  _
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码
) ^. A+ `2 \/ X) U  u) X) l
CardSpeed! M5 w  e  Y& b( C
用于设置是否使能SPI总线的TI模式。$ l4 }  M+ o. ?  d
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */
    1 X! {+ U8 V3 m- }) z# g: E* ~1 }1 a
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  
    ( W7 p( S) ?) ~5 {& j, ]! u
  3. " O% T4 v) A% n- f/ C
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    ' v  P# D0 S3 N4 W! y3 W# n. p
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    * C: [) X- |4 o6 @1 x

  6. 5 y! @( R' V& Q
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards- z$ H4 W1 P7 ^6 t4 Z; Q
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    # u/ h4 y7 [8 q5 p
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码
$ a7 p2 r0 H" s, h, x0 e/ E4 Z
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
2 _' b: F/ D. ]7 A; f+ m" O- t5 j  N下面是SDMMC句柄结构体:
. R4 ]2 s! o/ d% Y" v6 l+ [' {5 G
- z; v% E0 ~* K7 c. `' V% g
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U), d: Z' m" ^4 v; @
  2. typedef struct __SD_HandleTypeDef
    % A$ \* H  a  @! ]( H
  3. #else2 x6 o- n- E+ T, \6 G5 f: l
  4. typedef struct
    4 Z2 T: ?, _+ a  j9 r
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */7 j* K8 r2 C) G. d( ?: Z, ^
  6. {2 ^! C0 A& L+ J
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */: T! s6 z( F9 n+ p/ b
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */' {7 x/ [6 @9 z7 k3 {6 S2 T
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */
    ! I# E5 Z8 u# l
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */
      _3 f+ x% m/ K* S; S
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */
    8 O5 R$ h$ e" ?7 s" c! b0 k! A
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    *// i; v* ~! J2 L% i- a* c
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    % a/ w$ X. p: ?: C$ S7 y
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */7 e, u" Z3 l  T  U; g3 r' A7 _! ^
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */: j- v! ?, S% r3 e2 X& k4 _/ L
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */7 V5 _5 m* Z' ]4 v% T/ a
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */' r9 G) F6 h, f3 W/ g' s
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */
    ; R7 N$ W* K9 V# Q0 u% _
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */. x6 w: J$ H& K1 c' |; W4 N

  20. # H% `! e- B! G* H
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    0 x- ~9 S' D- @% \
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);: l( L3 K# c3 ^
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    9 d1 f: b3 F5 I0 K. S5 l
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);
    ! _& _0 @; b! }1 O  B
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);: S. f: C% B+ L; }* E
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    5 i& Y3 h2 r* x; }! P
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    ( q" O( l- @& \
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);+ c; ]% G& j) c0 y3 _- c* ]/ Y1 F  D
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    ; ~- N  p7 J3 Z2 I' t
  30. #if (USE_SD_TRANSCEIVER != 0U)& I; i* W: u# ]2 z0 R# F. [% A
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);5 L# A* i: j- w
  32. #endif /* USE_SD_TRANSCEIVER */
    ! x7 c& E  V, w; Z8 K! b4 i
  33. " [8 l% @: |2 g; ^9 I* [/ c
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    # o# g' G$ F4 T) v, R, L
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);) F& J% _% y2 ]4 ^! r; ]
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    $ w4 d# |7 }* v# P% ], V
  37. }SD_HandleTypeDef;
复制代码
9 r8 z. s/ R5 S7 x" Q
注意事项:1 x# C% c5 r. j: C" J4 Z

0 T+ ~  U) }+ k8 V7 k% D- |3 n条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
4 e3 |' l, L9 W5 x! D& {2 q6 _! v4 w) _
  #define   USE_HAL_SD_REGISTER_CALLBACKS   16 m2 \9 U$ d- o9 k8 i

. v" p% [* \4 ~8 U6 \通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
+ B* e7 z! }8 a. R3 G5 i
8 t$ Y! f2 M8 e4 y6 B这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
- u" W1 X0 a8 ~7 V$ ]0 a+ k$ D; N% B5 E8 c: l+ M* F7 B
  SD_TypeDef   *Instance
6 i: z& R0 g3 v9 U这个参数是寄存器的例化,方便操作寄存器。
4 W( q* Q2 F$ F* q$ G% |/ e2 a4 g4 A5 y' r6 L
  SD_InitTypeDef  Init* r/ `0 e& B3 e! i! R; [. x
这个参数在本章节3.2小节已经进行了详细说明。! t, |) {  F* b9 d

3 t, }4 i* t' c' Q! T87.4 SDMMC总线源文件stm32h7xx_hal_sd.c
( ^* d9 b0 F2 p2 @- K. B此文件涉及到的函数较多,这里把几个常用的函数做个说明:
% K& u( h/ G9 R5 y+ A( G+ p+ ?) p  s/ b% u, Q1 |
  HAL_SD_Init
, ^* ?2 E* f; N1 b3 g" i: G! `  HAL_SD_DeInit
5 b# c9 j; g8 V  HAL_SD_ReadBlocks) ?3 K* \& _/ X4 Z# ~' v2 h5 H: l/ I5 |' t. U
  HAL_SD_WriteBlocks
8 o: G, `$ i* T* p% B) \  HAL_SD_ReadBlocks_DMA
9 }  ^5 Z+ V( e  HAL_SD_WriteBlocks_DMA3 k4 ]+ K, M* T# F/ t/ w
  HAL_SD_Erase
6 O' D# d9 W' H) _! M87.4.1 函数HAL_SD_Init
4 T# }9 y  j9 n8 f函数原型:
% J+ Y0 Z( r% e5 R( m# h# N5 D, m  }: }% Z8 i3 |( A) @7 l
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    - p* e7 `9 H8 j  ~! u' Z
  2. {
    / f" T0 Y: a/ I: P- M- W/ a0 t
  3.   HAL_SD_CardStatusTypeDef CardStatus;7 w& g' W6 U1 c5 V8 U; ~
  4.   uint32_t speedgrade, unitsize;
    % q2 V8 V. n$ A+ l5 i1 S/ q
  5.   uint32_t tickstart;$ R, h+ N/ W! m  V. Q* B
  6. 9 H2 L9 W$ e0 f/ k7 y
  7.   /* 检查句柄是否有效 */5 i" C* h. K& A$ R
  8.   if(hsd == NULL)
    ; ~. y  l+ p; U) m- X+ B5 e/ U) \
  9.   {
    ' ^8 l) P" y" ?0 P
  10.     return HAL_ERROR;
    ' B# S/ l9 ^) n
  11.   }
    + ^' A- [" v0 ^) E5 [! D# e4 \

  12. ! L( O( H, _# K! W) c
  13.   /* 检查参数 */8 p* b" r0 [- D) C" C, x' g
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));) `0 k1 o' X8 d& h. b0 y
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
    3 E0 p& {5 s3 M+ j. f! J8 W
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
      Z) Y' [! y0 R$ q5 G
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    3 k) r* ^6 ^# l
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));5 G) Z/ l7 l! v
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
    . P, B- h0 }: e4 J0 I/ \0 [5 ~0 c

  20. 2 D: R1 v  h& E* u) L# m: Z8 x
  21.   if(hsd->State == HAL_SD_STATE_RESET)
    + t7 C3 Y7 r  C
  22.   {' O5 q8 i4 z4 J% H9 M
  23.     /* 开锁 */
    ' C2 i1 A2 K- G( P. w
  24.     hsd->Lock = HAL_UNLOCKED;) {1 U: t5 O2 h+ U( R
  25. 1 y1 O  K0 P3 t1 l4 c
  26. #if (USE_SD_TRANSCEIVER != 0U)% U# O, O+ C5 |, g
  27.     /* 兼容 */
    6 _+ n) `6 I- {9 H
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
    $ T8 }* J5 |) x4 y9 I: ]
  29.     {- c* b  o  P' I3 |8 y( B
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
    + C+ u4 |( ?2 t# L2 C
  31.     }8 e+ v  ]  n$ {" Q  B
  32. #endif
    ' s7 u- D0 y4 g6 Z2 }/ ~- Y$ B
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)- y  ^. t9 D( U! b% L( i' L  B8 j
  34.     /* 复位回调 */
    & C( x, H, g7 b& U
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;% X) M) v% Q4 D5 V9 N
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;, q2 z+ b/ W; A# y+ z
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;* M0 \: k, ?6 D- [
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    ) M7 |5 G3 l% n6 F+ [
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    + H1 V! b- d8 ?* v1 ?1 q
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;+ a2 r( O" ^- [5 G$ W: T
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    " f0 p- `" o- H* R# a
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    7 K2 B$ H3 M( b# N# r
  43. #if (USE_SD_TRANSCEIVER != 0U)
    7 L% ^+ W% v% e, @; M/ h, k
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)4 ], J- k3 Y1 w  w
  45.     {
    $ k1 X/ C# Q' n! m+ Y3 ^/ l' O
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    ; m' W, f" }7 b, w1 R$ X3 ?, h0 [4 g
  47.     }
    1 l8 n  q/ Q+ T" z3 F
  48. #endif 4 N; F2 |) c+ U/ N2 `6 Z7 g
  49. 8 |+ ~* y4 G2 q' G- l
  50.     if(hsd->MspInitCallback == NULL)7 l# C6 K* c3 ?7 L  e, k9 ^* \
  51.     {
    / E+ o7 ~! p- A$ @4 ?1 M. m
  52.       hsd->MspInitCallback = HAL_SD_MspInit;) Z+ y0 h5 L# t; X5 W" _, o
  53.     }
    / D" A* ], \# v" K! I- ~
  54. 9 f4 Y4 l7 q6 g7 }
  55.     /* 初始化底层 */- M# \6 b1 i* j3 w* a
  56.     hsd->MspInitCallback(hsd);
    4 L2 P" H5 O) E2 S( O
  57. #else
    * P, d2 U! b$ a9 K1 U
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */
    ; g( Y. O: X* ^7 d1 ^. u* }
  59.     HAL_SD_MspInit(hsd);
    - P$ K. v+ Q9 ~7 E
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    , L7 C, c' E2 v, y6 u! u
  61.   }+ E6 Z' A8 [4 Q

  62. ! p% n/ Z8 f9 b9 p0 p4 Z
  63.   hsd->State = HAL_SD_STATE_BUSY;
    5 v; l& T! f# E+ A
  64. " y" `+ f& r2 w
  65.   /* 初始化卡参数 */
    ' }+ T. l" B' ^' R+ i
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK). y$ H- h7 ^$ M. N3 J! F
  67.   {
    ) ]" c. M+ w' \. O! r. ?
  68.     return HAL_ERROR;+ n5 g) e% d, Q6 o8 U$ Y6 \5 R
  69.   }
    9 o& T; p. _6 R; Z$ i! `/ N/ ?( u* s1 _
  70. ( Q) O1 \: F9 w3 u) n4 x
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)) }) |- V# C& _2 v2 |& I: A
  72.   {( W9 U5 k& ?: L2 R
  73.     return HAL_ERROR;
    ) O) i+ n% \8 {; p0 R5 _$ [0 k" }
  74.   }0 Y* \; J' M# e0 x$ F# Q& n
  75.   /* 获取卡速度等信息 */6 a  Y3 ?8 T( T9 _  |
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    , ]- r5 q+ E. B  E; \8 p
  77.   unitsize = CardStatus.UhsAllocationUnitSize;( N1 w$ e# R" h7 v4 q; D
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    9 g3 a! ?' {* d( G+ Z
  79.   {, g5 a5 u( ?7 B4 O! H. Y1 C
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;8 f: D" T: G0 p$ ?. d( Q  ^9 n
  81.   }
    3 F- }; Z. L8 T  B' A5 k
  82.   else
    8 Q( v- A+ Z' X
  83.   {9 X8 o& [/ x% n5 `1 T4 B7 D- ^
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
    6 o  A3 p4 @+ Y* @
  85.     {1 X+ _* A/ n$ J% L- h2 r
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;% C# I+ O5 n: p- Z1 ^2 z
  87.     }
    : T+ K4 P8 u' P; E( a" F/ ~3 U5 t
  88.     else+ H" w8 U( M7 M( C6 e$ e
  89.     {) Y  A/ n9 @9 c
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;
    2 h4 {/ d9 A' k; Z# y
  91.     }
    + N  X3 a. s5 ~

  92. / h5 G5 x- F' W) D
  93.   }& f6 r' ?: G' c- A
  94.   /* 配置总线位宽 */6 N: s4 `9 f* y$ r& G% t' u
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    + t8 S# S! T( N# X7 q1 M4 E
  96.   {
    & n) o) I0 u  n, Y% ]
  97.     return HAL_ERROR;0 N  H9 L' x& B) }. Z8 _- q
  98.   }
    ! N9 [/ ^( E5 V

  99. / u3 w7 ?, E: B
  100.   /* 验证卡初始化后是否就绪 */+ @$ O( v6 J5 }
  101.   tickstart = HAL_GetTick();* B/ s8 h+ L3 M3 P2 x2 f
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))6 P; ^& V4 ~8 s; Y* ^" J0 T/ ^" P
  103.   {8 \$ z5 K; ^% S; |8 _
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    4 S8 `  ~6 e5 X
  105.     {
    2 ~9 M6 `- `4 ]2 X' w
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;; O# g3 Q" b& T
  107.       hsd->State= HAL_SD_STATE_READY;
    8 \9 u5 N  D' S; W. K" Q% A
  108.       return HAL_TIMEOUT;4 D/ a7 N' u8 o/ l' ?5 H. Q' A
  109.     }
    ) O5 ~! b" i6 t2 r7 w" n" j
  110.   }! c) Q) n( k& w' }% B+ l& o( o

  111. 8 E/ ?% _- T5 [# H: K
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;/ k, R! \( s% x( Z: W  T

  113. 8 R# j( r6 @# K( S& y4 ^
  114.   hsd->Context = SD_CONTEXT_NONE;
    ! M# C! v5 r9 o

  115. / E/ F% u! \6 V: F
  116.   hsd->State = HAL_SD_STATE_READY;4 \. m; K! q4 O
  117. / M4 n" G0 O) ]6 T
  118.   return HAL_OK;
    8 u  u. E- t# U
  119. }
复制代码

5 M* s3 T4 K- [$ p% U, ~函数描述:
1 v+ Y# K& B& z% O1 X
* i, @& r& f0 c6 v% I! ^3 {; N7 _2 b此函数用于初始化SD卡。% x2 t! Z' Z" E7 Z( j& j3 u3 N
! j' ]0 ~- k, Y/ x0 a' q6 X
函数参数:
, g) M! x& S" t, D0 E& G/ H: P* t7 v) N1 @
  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。$ f8 x8 {. J3 e6 V
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
5 [: o0 R1 l& \" A+ u$ W) B注意事项:) W) s) O+ ^% T/ a' l. b9 k
) W9 u: w: f5 {" f8 F+ o, S. p+ g
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。9 n3 P9 r1 Z, }  x# ^4 A
如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
4 ]9 p- d- X- f+ F' x+ I7 v对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。1 ~/ f3 P( x; R7 D% ?  ~' X. f# `1 t3 X7 l
$ a( ^$ N! y# _& o; G
解决办法有三
7 j" x! i2 h$ U1 S8 Q7 v8 h5 a+ _9 T) g5 n1 C- c
方法1:用户自己初始化SD和涉及到的GPIO等。
( k; t* \! E/ A  Q+ Q& G! B
- g' d  K. z/ P0 E方法2:定义SD_HandleTypeDef SdHandle为全局变量。
) f8 s% ]$ H* F# N, p7 f4 \1 M" j9 L; k; y; ]3 I; I5 ^
方法3:下面的方法& c9 b2 Z0 e6 j4 A4 M/ M
1 z+ o1 ~/ \6 G' j6 b8 J6 [) W
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    3 s5 `- g( ?0 G( e
  2. {
    ' o3 ^3 H+ n* }3 \3 y
  3.     Error_Handler();# p- }$ C5 Y, D0 e: R0 [6 @/ ^
  4. }  ! R' Y* @5 f: Z/ I3 m. J3 U
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    1 [9 E" s! M' M
  6. {1 g% W  f: S* }" E, p4 ?. R0 r* q
  7.     Error_Handler();9 G! {* r! U& L/ |9 n: T! T
  8. }
复制代码
0 P9 `- H; t0 ?% O; K( l# Z( K6 s( H
使用举例:
: R- {1 Z$ k1 B$ z' w6 z1 \- {$ }5 ^( I1 ], U( n
  1. SD_HandleTypeDef uSdHandle;
    & r+ y8 v/ d! h0 G; Q
  2. 9 Q2 X4 D9 U7 g2 W- R& T% b  z
  3. uSdHandle.Instance = SDMMC1;, L9 v9 T! v7 \. Z/ o. h

  4. 2 k7 p/ @) ~; ]4 z. ^
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    , p3 G" Z  k/ _9 c- u
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].
    & \# r% y* F: h& G' W- j, V! j
  7.      200MHz / (2*2) = 50MHz( ~$ ~8 F& |: n9 e& b' @: Q
  8. */
    & c$ C: ^! y4 }* v- I8 D5 \
  9. uSdHandle.Init.ClockDiv            = 2; 5 R1 z4 q! o* S
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    1 h0 z& S& O. }+ ]
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    9 g+ P$ _8 E, P+ H; |3 |7 x
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;, O  S, y  I1 C+ k
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;( C4 N. e4 O; Q
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)0 m/ ~! e1 _! [+ f' {/ _9 \
  15. {2 O5 {* ?8 V& h* I# c: C( B7 Z* w  M: @
  16.    sd_state = MSD_ERROR;
    ' ?8 ]! K* D' I& d8 f) G
  17. }
复制代码
4 x$ [0 _+ V( @6 a) ^+ E$ p
87.4.2 函数HAL_SD_DeInit
; \" Z& I& a/ I函数原型:) b! F( U1 s0 i+ V% }  O6 X! O

8 x9 h5 B3 s5 d
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    9 N* |+ u) y" }7 V, h) s3 H' A$ H
  2. {& J  J1 w+ c) u* t, X: c
  3.   /* 检查SD卡句柄是否有效 */
    * \+ k8 L- Q: S0 k/ f0 h1 L- H
  4.   if(hsd == NULL)  |3 e& T  Z' P( H( W
  5.   {
    3 T2 y# Y4 [4 j
  6.     return HAL_ERROR;3 i3 |/ t8 C5 {! u# j( g& `
  7.   }9 K6 O- P7 u4 o, [
  8. , `6 G$ M9 w% E0 {9 k* I2 X* o
  9.   /* 检查参数 */
    ' ?  z+ D0 i  K" i4 H( |
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));  p2 Y3 m: Q" v; \- b. z5 F
  11. ! t3 D$ d$ P( n$ j6 Z
  12.   hsd->State = HAL_SD_STATE_BUSY;: e/ Y- Y: @% ?5 K. a/ `
  13. 1 w( q$ i5 f* X/ k
  14. #if (USE_SD_TRANSCEIVER != 0U)
    # e* b3 o7 T% _5 S
  15.   /* 关闭1.8V模式 *// B3 q" d; p. F) {; a' L0 g
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)( K( y9 n! w2 ~; q3 S/ z
  17.   {
    ) K' H9 y2 T' S. s, e
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)9 F0 g2 C, I; U9 ]
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)
    ; }7 o7 g# a: ?$ _7 y9 c& J
  20.     {
    - {  M; C" |# ]
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    * j& T. |9 |' Y" Z9 @0 h
  22.     }. V4 Q" d' ?, a+ C* o! `
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);
    7 _5 A. S1 t; Z; R/ f
  24. #else5 G6 ~6 _7 V  W! _
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
    " d8 V# M& A, U  [9 N0 R
  26. #endif
    0 z2 H! f. g) |% o0 U* H
  27.   }                                                                         ! \! B9 E& B: `& y$ w3 [, Z0 h3 w5 `
  28. #endif" I4 x8 l' B2 m  V( |* a( w
  29. % B9 f2 M! R" X# \& w5 d
  30.   /* 关闭SD卡电源 */
    ' ?) @# j8 x- S" {" ~' u
  31.   SD_PowerOFF(hsd);
    8 e# Q% H& @1 f
  32. , K1 E/ g2 l$ U5 x( P
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)$ @9 a# r* S' I: |/ ^, G
  34.   if(hsd->MspDeInitCallback == NULL)7 l9 Q" c( l. D( s$ i( P
  35.   {
    5 K/ h7 H5 c$ b# a
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;
    ; |1 D, m# d, L  d9 K! `- f
  37.   }
    ' ]# r( P6 E. g! T6 k: h
  38. ; d4 U6 H( C& W0 w
  39.   /* 复位底层硬件 */
    . y$ ]0 K7 s" t" n
  40.   hsd->MspDeInitCallback(hsd);
    % R& `+ R- U- a: R# }
  41. #else
    8 }- B% @0 V6 `% g# D% O
  42.   /* 复位底层硬件 */5 p7 @. l  j4 h
  43.   HAL_SD_MspDeInit(hsd);
      L7 o1 X4 c9 O. Y! a
  44. #endif
    / a4 q- {  x& k! |- w. ~, A

  45. 6 S2 t8 k1 m" e; M
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;6 S/ Q6 Y8 u) g" j
  47.   hsd->State = HAL_SD_STATE_RESET;
    . B6 [$ i% Z- g2 G: d8 a
  48. " }: {/ L7 {7 o5 z  W. m. W
  49.   return HAL_OK;
    ) Q& N9 e! b1 k
  50. }
复制代码
/ m0 h1 A+ O+ C  C- |
函数描述:* G6 P* C3 _2 ]! v7 \/ o6 A
5 j* N' Y' D! B3 I
用于复位SD总线初始化。
. ^  [  V! s0 K. v. \
- T/ E& T* w9 e函数参数:+ p2 s, x3 X& t; G- r
$ ^# D: _# i3 W: y
第1个参数是SD_HandleTypeDef类型结构体指针变量。6 F- x( o- Q& x4 j; y
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
0 Q& M: }7 ]* D% \87.4.3 函数HAL_SD_ReadBlocks
) o* V' T: B  w- E0 }8 a函数原型:! E3 f5 R" C0 U) q' ], Q
7 c, l, g+ B& n% Q
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    ) ^7 ?. v! n5 c5 S) S' z
  2. {$ ^4 _6 M8 j& g8 C! r" [
  3.   SDMMC_DataInitTypeDef config;* a7 `3 \$ B3 K- }8 v
  4.   uint32_t errorstate;
    ! ~/ Q3 L; M; l1 u1 k
  5.   uint32_t tickstart = HAL_GetTick();
    9 i% {& \9 J0 S3 x$ Q8 r! Y
  6.   uint32_t count, data, dataremaining;: {1 k3 f5 o* U3 R: p
  7.   uint32_t add = BlockAdd;
    / z+ o/ s7 x! Z4 y! e9 i8 p) f
  8.   uint8_t *tempbuff = pData;0 B3 y! @3 v8 G2 Q7 I

  9.   N# U6 T. ?" e* B6 y
  10.   if(NULL == pData), H# x2 V4 O4 g# i+ e3 z
  11.   {8 q; f1 Q. J% ?2 F
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;; B0 |. ^1 c9 T" P' H" P4 X* l& u
  13.     return HAL_ERROR;
    ; n/ {# u6 m) y. q( `; E! D' |5 J
  14.   }
    4 V' y* C& H* |# d9 F8 d$ Z8 r

  15. 8 l- j+ D, u4 r
  16.   if(hsd->State == HAL_SD_STATE_READY)  y) e  y6 b: w) t8 ]% {* p4 @3 ~
  17.   {/ ^1 @) N+ E  U2 t6 l2 A
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;+ v' m, @+ u: `7 k
  19. 3 h1 V5 \9 b" A3 W4 x5 L
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))6 r- X6 d3 c# V! j
  21.     {' H7 c3 v0 S/ |2 I* m7 J2 a: F- z
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    7 N' `9 W+ `- S2 k
  23.       return HAL_ERROR;2 o4 r) ?% w9 a
  24.     }
    - q+ m% `/ Y6 {" U+ K3 ]$ @/ V

  25. 9 F' f% ~) [# O! i5 @
  26.     hsd->State = HAL_SD_STATE_BUSY;8 X: L7 M& A  F/ h6 W

  27. ) P2 y$ h) ]5 N& u6 m
  28.     /* 初始化数据控制寄存器 */- {$ e' t7 G- B# v, Z# \# t$ V( W
  29.     hsd->Instance->DCTRL = 0U;/ k9 ~* R% |( z9 p8 o
  30. 0 M  V7 t# K* e  _% d$ K. Z. R
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    * q& h% R$ B% p% s) U
  32.     {' V) X9 Z: j- y4 m# i8 M' Z1 b! d
  33.       add *= 512U;. a* k! L9 ~# C; \- f
  34.     }0 v% u8 ?+ X& S1 e8 e/ \& g

  35. ! T* \8 S+ M+ ?9 u0 X: y2 z
  36.     /* 配置SD DPSM (Data Path State Machine) */
    * Q5 |9 P, I" }
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;! [- |# f9 E- p) A. T- }0 y
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;+ q* ]7 Z$ g, h
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;: ^1 H5 }6 O2 P) k
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    & j7 ]  Y6 Z/ V; X( B
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;! {1 {, V0 p6 Z+ g2 I9 K+ M  l1 d2 i2 s
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;8 G0 A* Y' z& U/ \
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    6 [; a6 ?; P: Y/ p' b( S6 l% b
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);/ e5 ]: b9 v& h1 V! e5 ^7 J* ?* T

  45. 4 e- w$ r) [1 k: w0 `0 q+ w
  46.     /* 查询方式块读取 */( G9 Z. B' V. ]3 a9 v5 K- T8 a+ v/ D
  47.     if(NumberOfBlocks > 1U)  p# p- ?. C# L; C0 t2 I/ i- G  N
  48.     {
    ' X0 B! N* i5 d4 x
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;: v9 |. `, K) N% C: \; \/ j& s

  50. # d" b6 o% T+ p) i$ _4 o
  51.       /* 多块读取命令 */5 _* R6 ?9 D; y/ s% \7 Q& E4 n9 k
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);6 m( ~+ O8 k; Q7 F. u+ i! e
  53.     }9 r2 @' j& l' L& S5 B8 z+ c
  54.     else
    ( C1 b" {& Z" @, y  D) [4 O) p  Q
  55.     {3 I2 g+ ?" v3 M; o% p0 _
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;7 f( h& t; O  J* k3 P( C; z/ t

  57. ) ?8 i8 I# U  ?$ J. p* n( `3 R! b
  58.       /* 单块读取命令 */
    # m2 x5 v, ?( A  Y3 z" N
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    * \# S, E6 w( \
  60.     }
    ) ], R0 {7 L* K9 l
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    $ L2 k1 ]* g; r8 F/ C9 A6 J. R6 T
  62.     {
    5 x% k' x/ |8 T  o& L; w
  63.       /* 清除所有静态标志 */
    2 Q' l( T) I9 L8 H  G
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);. Z) @$ _  \: v4 D1 Q% Q
  65.       hsd->ErrorCode |= errorstate;
    - n' B" [. u5 a' a4 f
  66.       hsd->State = HAL_SD_STATE_READY;* Q( t. K+ b* `+ }5 M
  67.       hsd->Context = SD_CONTEXT_NONE;  n0 K6 S1 V7 p: Q" b* s: m0 i
  68.       return HAL_ERROR;
    0 ^7 e+ k' h7 N8 T6 W" D
  69.     }6 x' U% d+ o5 B$ H% b

  70. * A* o( J+ S- v  f. D
  71.     /* 查询SDMMC标志 */
    : S) G7 F& y( K; A8 f) A/ E
  72.     dataremaining = config.DataLength;& N6 e$ L. t# O* d7 F9 ?4 v
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))" y6 J0 {$ U, s( l+ O
  74.     {) _: f: q; f' j. ^" L
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))3 G4 g" ^5 A+ w% w
  76.       {
    8 b/ c' f; ^- o8 L
  77.         /* 从SDMMC Rx FIFO读取数据 */
    . E$ R" u9 [# Y& A
  78.         for(count = 0U; count < 8U; count++)
    8 N6 `5 E! ?  w5 l- I& E
  79.         {
      k3 J! T  G5 N* e
  80.           data = SDMMC_ReadFIFO(hsd->Instance);' j% V  K2 u  y/ k
  81.           *tempbuff = (uint8_t)(data & 0xFFU);; |/ y4 x/ v- L0 L; A
  82.           tempbuff++;
    ; ~2 ?: v+ w# x% U4 s7 W7 ]
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
    9 n% {- l0 k- T
  84.           tempbuff++;
    . A" I/ B* C! F0 O  J0 ]
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);! b$ G5 T# x1 B# Y
  86.           tempbuff++;
    * l- S- @) a% A. c' [
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
    / D, J' v+ Z5 x* |. h+ U. I
  88.           tempbuff++;
    ! A" v: I4 G# u( @2 N
  89.         }
    6 f' I: J9 f& e  T( f3 R
  90.         dataremaining -= 32U;
    . q6 Y! X% M: M! q* I" Y
  91.       }! s0 J. H9 Q+ r7 o# a: k

  92. 7 a; ?4 s; Y) m2 m( C( A6 F% c
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    8 {: F8 b, y7 h% k$ f7 }% V
  94.       {
    , j: Y7 \- F( K$ }
  95.         /* 清除所有静态标志 */
    7 `) ~# l" ^1 s$ W
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ) t% b5 w. B& D8 x
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    . ~3 R9 k( }  c) y7 _5 `/ T
  98.         hsd->State= HAL_SD_STATE_READY;
    4 w' h: M/ K+ K1 G8 z
  99.         hsd->Context = SD_CONTEXT_NONE;0 x! j4 f/ E( W+ J( b( P$ k
  100.         return HAL_TIMEOUT;
    . [- ]1 d4 |5 U' Z. l) Z# Q- G" ~
  101.       }0 u& y$ [! d/ L/ r& O
  102.     }' w& H4 W$ D$ h7 b. P: B7 O" k% {: [
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);1 F: g+ `* M' Y& T5 o/ Q2 o$ J
  104. + |' S. o$ K' J3 Z: @. V5 o
  105.     /* 多块读取发送停止传输命令 */
    . D2 N8 v+ R, u3 ?
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    1 s* c0 N# t+ M8 N7 S  a5 u5 t3 S
  107.     {/ A$ B7 R+ J. D2 w* V! Y  `8 _
  108.       if(hsd->SdCard.CardType != CARD_SECURED)- e. P* J# n+ f2 o
  109.       {8 I0 @( K& \. v2 y
  110.         /* 发送停止传输命令 */
    9 A$ Z; X$ f  S; C5 I, B
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    & M0 u/ A7 h9 I7 _+ \
  112.         if(errorstate != HAL_SD_ERROR_NONE)- y) E& T' {2 E6 X
  113.         {5 n% G( r" Q" H$ a- Q# L% d# {
  114.           /* 清除所有静态标志 */
    % h0 ?( S1 B' s& n
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);3 i' v4 `$ |; Q# B
  116.           hsd->ErrorCode |= errorstate;$ c. U* @3 X. W' t4 {# Y$ B
  117.           hsd->State = HAL_SD_STATE_READY;
    9 t3 i, Y& ~4 _* ~' s4 S
  118.           hsd->Context = SD_CONTEXT_NONE;
    % x# G+ c- Y% H' _# P3 G
  119.           return HAL_ERROR;5 a9 O  v2 N1 N( G0 x
  120.         }
    4 F7 _; r  D4 L; F0 e: V9 `
  121.       }, h( i; U; v# E
  122.     }  i  r$ s% F9 w, n0 o2 a0 b$ E8 L

  123. 3 Z& W) ]  }! w( j
  124.     /* 获取错误状态 */
    ' F  E4 L+ `8 k" ~( s0 ?! a- Q7 x
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))' v+ y" C1 X8 b3 {$ @) t9 ~
  126.     {
    ! V! D, ^3 D( [4 o# }
  127.       /* 清除所有静态标志 */" Z" g5 f$ p# n$ D; w( ~4 o
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);& ?; u6 t* ?* u* f+ ^+ Q
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;5 ]' a. ?/ w8 K
  130.       hsd->State = HAL_SD_STATE_READY;/ {: G- I6 Y; U+ c; X
  131.       hsd->Context = SD_CONTEXT_NONE;
    4 q0 `8 z2 B! _6 I' k! ]% G
  132.       return HAL_ERROR;
    ( n3 S; ?! K$ ]
  133.     }9 f  c- d" y% X  b% g: M
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))$ P" i3 p2 P; B
  135.     {/ u9 F& X, _9 R9 a5 `
  136.       /* 清除所有静态标志 */  Y) z7 j& l& m2 K5 @  L  m
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);) y/ J0 O/ M3 T( ?
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    9 s3 {& \4 p8 y. k1 x8 E" P* H
  139.       hsd->State = HAL_SD_STATE_READY;: X5 v, [7 f. ?9 d1 ?* S7 }. {4 e
  140.       hsd->Context = SD_CONTEXT_NONE;3 q- p) x, C3 F- W5 ~3 _  p  K0 w
  141.       return HAL_ERROR;
    + z4 ^8 ]& X# Q6 f  }
  142.     }9 y6 n. x9 H: m. I5 v! t
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    3 N8 o- y- E& {$ r/ g* ^
  144.     {
    . r4 q$ R4 ]  r* H. z
  145.       /* 清除所有静态标志 */
    # C$ i. \/ o3 I6 v$ J: ?: K
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 m5 {) L( }7 g; q; E! S
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;* k& l$ m5 j4 c/ ^7 M1 J
  148.       hsd->State = HAL_SD_STATE_READY;
    5 n& f7 _! Y' f( R7 Z5 L' ^
  149.       hsd->Context = SD_CONTEXT_NONE;
    & p5 H3 |1 k* L7 E+ J
  150.       return HAL_ERROR;
    ) @) i# ]) v8 ?+ a! F9 Z; Y
  151.     }
    ' `" c5 l. ]  V: C! X$ [& W
  152.     else
    & |. v, h! ?; X) p( S/ j' {3 B6 z
  153.     {
    + s* p4 Z& Y/ Y/ Z: _  V# j' b
  154.       /* 什么都不做 */0 m. [0 j4 x# F! c3 W" |6 U9 [
  155.     }& d) N1 B" k9 ~! i2 a3 ^1 @! x
  156. 0 l1 V2 ~* L: H" G! r
  157.     /* 清除所有静态标志 */
    # r/ s/ x% v$ G6 j/ Y
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);0 T: R3 A7 W1 V+ D* X, g+ {1 L

  159. 7 ^3 T  A% m6 H: S$ |2 T! O2 h
  160.     hsd->State = HAL_SD_STATE_READY;
    ; o* \& I7 q+ s8 O7 f( [
  161. / i/ V* ]; T6 }+ }" H
  162.     return HAL_OK;
    1 G! c+ a) b+ }9 }
  163.   }/ S9 I" G+ @9 b6 Q
  164.   else
    2 y. ]/ {: ]8 m3 z
  165.   {- ?3 A4 I+ `7 [8 T* h; f  g& _
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    0 k( y9 K3 q4 V5 k4 q/ R/ E
  167.     return HAL_ERROR;
    : r: T& i3 G2 ^& ?/ J9 w
  168.   }0 `8 Z1 o; _& q5 G' A4 t
  169. }
复制代码

7 b* e5 m9 C" n7 r函数描述:" ~% p* E* O7 [1 D$ ^* f7 |
/ n: I/ ^- L# {$ i: T1 B
此函数主要用于SD卡数据读取。
! I# I( P! k/ ?7 }) i& j( G5 N* E0 O/ P) i
函数参数:, P6 o0 r  Q" m" A/ J; M: M

# `7 T$ B/ f7 `: v6 G; W  第1个参数是SD_HandleTypeDef类型结构体指针变量。
" {* C$ L' d' ]  r9 z  第2个参数是接收数据的缓冲地址。+ f; E, {$ I2 \# i' ]+ }" i. x
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。( r8 ?- `" e1 w4 E3 ?% Z" h% y
  第4个参数是读取的扇区数。
0 t, W. t. C" @1 Y( l8 u2 _: B  第5个参数是传输过程的溢出时间,单位ms。
+ ]7 g! T9 y  N' D  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
( s: |. _- ]3 t使用举例:
) U3 J" u1 S5 M* A( A3 l+ n! f0 H. R0 }( C! V+ P
  1. /**+ C1 j" ~) B6 {' p1 }
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
    ) d* h. |$ Y% J# @; F
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit1 b( a; I# ?* K+ W, e
  4.   * @param  ReadAddr: Address from where data is to be read
    8 V6 I7 j  W; k" o
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    " _7 ]: D8 q5 l. v; A
  6.   * @param  Timeout: Timeout for read operation
    2 z& f  R( {+ w' ]
  7.   * @retval SD status
    1 p+ z4 k6 x# t- B
  8.   */
    ' x5 j. r5 y" \1 }+ W- R  J
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    - q* |+ \. \' @5 l  g+ D
  10. {
    / y4 n* d6 d+ z, k# ?% S- G
  11. 3 ~, t1 @; `) Y) @
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    - w' Z# M( j; c# R
  13.   {. u6 j: s. z4 q7 W3 R
  14.     return MSD_OK;" J/ E  n+ t7 s* k" k9 w; r$ \
  15.   }
    * f: w' l8 R8 U, u& H
  16.   else
      i2 O8 @4 v0 c8 N+ p* s
  17.   {+ c* H: d7 ], Z5 b/ c
  18.     return MSD_ERROR;
    " p5 x5 m# E. f& j; F- H7 ^( f
  19.   }" w- X4 x7 i  B( H8 P1 J
  20.   C( [! y2 ]' i4 Z5 `
  21. }
复制代码
" @' _) y6 F8 ?3 [, Q6 {. o: `
87.4.4 函数HAL_SD_WriteBlocks
9 ^1 M' i0 x% m$ O: c) R" _( Q函数原型:
% T; j& m) B! t
7 F% s( Z# w& y- l+ ^* j# Z+ L
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    ( o  y) t3 a9 @2 n" O. v$ E# }8 {
  2. {
    . }4 P7 J) N- w1 _0 k
  3.   SDMMC_DataInitTypeDef config;& N% r% i+ t: D" M) q
  4.   uint32_t errorstate;
    ! E/ Q) @* ]* a  V  [2 ?6 C7 m# q% Y! o7 M
  5.   uint32_t tickstart = HAL_GetTick();" p  L* s: j" s+ ^7 d( k3 J6 n
  6.   uint32_t count, data, dataremaining;7 t  o: d1 ^( H, ~" O5 d& R
  7.   uint32_t add = BlockAdd;1 \- m$ b6 f$ l
  8.   uint8_t *tempbuff = pData;6 A4 B8 k! K# O) ?0 {  Y: R
  9. : s7 N; w; f  Q  V0 U$ i7 Z0 J
  10.   if(NULL == pData)
    ! }0 C5 s9 T4 O0 ?, d
  11.   {
    ) h0 S! C" ~- u7 x
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    6 s. n5 I, ?6 `  s+ {5 J8 c- }
  13.     return HAL_ERROR;
    6 I* J) s0 W. B: Q
  14.   }. C2 V" d1 `5 G# S5 K6 z( S; V; j
  15. $ h4 F- I/ q8 k% R3 G
  16.   if(hsd->State == HAL_SD_STATE_READY), [  R; u# H& m% m) K( d# r' F
  17.   {
    ) d2 h/ B: M* m2 t& j
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;. |8 R) G7 h- }2 S

  19. " c7 S( W+ j7 L
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    3 j# x! o; l, g
  21.     {4 c3 P2 ^# Q+ ^
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;( Y5 ]; y1 Y8 j) b7 `
  23.       return HAL_ERROR;$ M& K" s% @" _6 W4 X
  24.     }
    4 e; s0 X, ~/ b7 H& |- B

  25. 6 u3 ?5 `# ]% h. j
  26.     hsd->State = HAL_SD_STATE_BUSY;+ T! S# Z; v! K: N
  27. ' \% q4 D$ o3 g+ U: L; u
  28.     /* 初始化数据控制寄存器 */
    # f* m2 n. i+ |* V- u2 }
  29.     hsd->Instance->DCTRL = 0U;- `- _0 m& h/ ]. F" V
  30. $ e% M. I2 D* t$ a4 s* |
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)" o. G  _; l$ X" q' m6 E0 n
  32.     {
    # h' l# Z2 }, B( _5 `- z
  33.       add *= 512U;
    ; K0 S2 A4 M9 J/ A
  34.     }! U; w$ }" e- S1 |

  35. 8 c+ b3 z0 O( V& `, X( ]
  36.     /* 配置SD DPSM */
    7 Q* O6 G, \& L  f3 k3 [( [% r* _
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    4 N( x4 q2 |( |' R) S5 c! ]& _
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;4 \1 i4 @9 ]8 x, u* R; t7 t) `* m
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;  A# t/ C6 e% F- L9 U+ v( ]
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;2 _6 M4 d1 _5 X
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    $ x# @/ p, o, c  z
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    + A5 ]8 j2 N* C
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    ' J' y  Y1 P0 O% T
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    + ]) |" G* w! W" {+ X
  45. $ ]9 f/ R0 U+ G/ y: f
  46.     /* 查询方式块写操作 */2 _; E/ I3 Z$ N% ?$ ^3 X) _8 D
  47.     if(NumberOfBlocks > 1U), r1 X  J  }4 T
  48.     {
    3 N/ m- w% c* v- H2 S
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    7 E7 ?$ A. O/ e, N
  50. 3 U9 B' `0 `9 t3 g
  51.       /* 写多块命令 */6 t2 `  i- j& h  `! G5 j" y0 K
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);# m, k4 x! t" z6 ~$ }2 d$ z
  53.     }
    5 K- `, m& f4 X- i
  54.     else
    # U* k! @( ~% O! [1 e/ g6 h
  55.     {
    ( B# E4 z& q' W6 }- C. H
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;& `2 @. I" e. j2 O8 E. M& v
  57. # Y9 I; p) {; `, I
  58.       /* 写单块命令 */( t: d9 D8 l  @6 C1 e
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);) T; P9 v( N$ F& v6 f& |) Q
  60.     }
    - S% ^& V+ U9 ^5 k" v
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    ; C9 ]( }: ^7 P# [! j& c- r! B- C
  62.     {. @+ D9 C  q$ n, P3 u' w4 `
  63.       /* 清除所有静态命令 */3 P3 P9 E9 C1 Z. Q$ X
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    5 G' M- O1 J' H& w$ {7 r) Q: W
  65.       hsd->ErrorCode |= errorstate;& P. H# `7 X. `# I+ ~' ?. K
  66.       hsd->State = HAL_SD_STATE_READY;' G) [# @% E3 d  o/ [+ o
  67.       hsd->Context = SD_CONTEXT_NONE;$ t7 {' F3 M" O9 Y" `* z0 g
  68.       return HAL_ERROR;
    5 v  ?7 d( _' H: r: ^
  69.     }, r/ q4 l  T, N4 y$ q- i. h

  70. # V. U: G  V! @4 v
  71.     /* 查询方式块写操作 */: E$ }" j' E; q" l
  72.     dataremaining = config.DataLength;4 `# j* v- l0 l1 i
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))! O5 g; A* z0 H! m; Q' l4 a% ~
  74.     {
    / ?: Z4 Q: {* Z3 t, K3 Z
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))3 U6 Q+ v2 o7 H8 ?4 \2 x) X- Q/ D
  76.       {
    ! P' Z( k9 G) b- [4 v9 u
  77.         /* 写数据到SDMMC Tx FIFO */- P, z& j# Q% {' T8 Z( v- i
  78.         for(count = 0U; count < 8U; count++)1 {" t! E2 Q. ?7 d- T2 H
  79.         {3 w- J- K7 \3 @
  80.           data = (uint32_t)(*tempbuff);+ S2 T/ O2 `# m  A
  81.           tempbuff++;
    1 Y2 p; `, X2 X/ v/ J% @
  82.           data |= ((uint32_t)(*tempbuff) << 8U);; ]' e; ^3 K% P! r1 |$ Y9 M
  83.           tempbuff++;- \8 d! C2 s( v3 E, n
  84.           data |= ((uint32_t)(*tempbuff) << 16U);9 m8 u% D. u0 p0 p
  85.           tempbuff++;
    % z+ N: X( @; t# s2 c/ ?1 p# n$ x6 Y
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    8 ^5 i7 R7 `+ g; D7 s) V' R
  87.           tempbuff++;
    & D" i' g1 d9 W* [) b9 K( t
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);" u% }/ m7 c1 @
  89.         }
    ( F9 b. v4 w+ n3 t9 L" Z- u9 ]
  90.         dataremaining -= 32U;+ d" g8 G/ i# G
  91.       }
    0 D8 r  O7 V  f5 \+ Q

  92. ( |% {3 F$ ~, ]* p$ j
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
      K5 O% r% t7 p' z; G0 n
  94.       {* p7 V# ^2 z) @. U* _9 Z
  95.         /* 清除所有静态标志 */5 B5 H3 J5 A1 b) n7 q: _& Z
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ! I. z2 ~# Y; q6 M8 A/ N$ Z
  97.         hsd->ErrorCode |= errorstate;  S4 T3 a( S) e  P8 P: I$ V6 q
  98.         hsd->State = HAL_SD_STATE_READY;' o, L8 j, G* K- @$ d& Y
  99.         hsd->Context = SD_CONTEXT_NONE;
    0 i! C3 \7 n, W  G" j9 R1 t' z
  100.         return HAL_TIMEOUT;7 w; @( R: w, A; r" E1 f# D
  101.       }% z, _8 e2 W. @* p8 }* T
  102.     }
    2 `" m$ s0 z' F* m7 s
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);7 n; Q; d- J* X8 \
  104. 9 V% d% ~% N( i7 T) B! f& @/ i( u. k
  105.     /* 多块写操作,发送停止传输命令 */
    , G) A; ^  ~4 E
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    ) W( F3 h5 p4 o8 S8 @4 _2 N1 f
  107.     {) m3 G4 x7 M2 R# ^0 m
  108.       if(hsd->SdCard.CardType != CARD_SECURED)+ j" T* x( `9 m* s3 {3 X' X
  109.       {
    & j9 b4 F2 {8 J! \* I
  110.         /* 发送停止传输命令 */
      |0 e) Y1 L2 P9 r0 G" r
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    , J! J4 M8 \$ x$ @
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    ; t. i& t8 U! }" f
  113.         {! f) E" [6 [* }1 M
  114.           /* 清除所有静态传输标志 */4 E. o4 o- G* ]) S5 l& n
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    8 r5 Q4 e- F# s4 l
  116.           hsd->ErrorCode |= errorstate;. }- [! k! l7 B" H9 r
  117.           hsd->State = HAL_SD_STATE_READY;
    7 O4 e6 ^, e9 `7 g5 }
  118.           hsd->Context = SD_CONTEXT_NONE;
    - j) n4 l2 t" L2 o: d' c
  119.           return HAL_ERROR;9 [  i2 k0 O( P  O4 M
  120.         }# e9 V& i$ J/ }  o, d. Z$ Y
  121.       }
    ) b0 F" s7 W, h
  122.     }2 I( A4 ], b0 @3 z1 J

  123. 9 S* X9 G5 e. u6 Y0 H' N
  124.     /* Get error state */7 @+ j$ U1 i8 ?9 d
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    7 K: k. x' n2 A# m/ C
  126.     {* u9 O0 x, T4 h$ b$ d6 |- S8 X
  127.       /* 清除所有静态传输标志 */
    : w+ S- F/ E6 n
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);) F. q( v" \, C# s' h( w7 N2 B) `
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;) _% v9 p/ V/ {; i# \3 S
  130.       hsd->State = HAL_SD_STATE_READY;
    . B& i& b: Z& W( n# U; a
  131.       hsd->Context = SD_CONTEXT_NONE;
    : ~( z  i) m& a- d) H
  132.       return HAL_ERROR;
    ' |4 S; U2 ]1 l; D- n( K1 Q
  133.     }
    # |1 I+ S6 C/ R- |
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    0 _$ P5 [8 B) l2 Q) v7 U7 E
  135.     {+ S: j# {4 K! }5 a+ g
  136.       /* 清除所有静态传输标志 */
    4 i( x) o: m- f
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    % k% O# U7 R3 O9 m' z6 H$ m( I7 n
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    9 k" {5 I$ G/ p8 q% ]
  139.       hsd->State = HAL_SD_STATE_READY;
    ; S( K4 D) e) ^; }9 b
  140.       hsd->Context = SD_CONTEXT_NONE;" w% E- H9 x# A2 x- I7 G
  141.       return HAL_ERROR;9 v9 m1 @0 Q8 N4 z- c$ t
  142.     }
    3 [9 ~% A9 F7 P6 v
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    7 I* Y+ H  f' g, J& z: P
  144.     {
    , t+ P0 m% o# ~& f' G7 ]/ L
  145.       /* 清除所有静态传输标志 */
    ( Q* f# [' B2 [  }7 A
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);2 S, M6 g/ [" r( r' l3 v' l$ o
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;* P5 @( y$ q4 F( |
  148.       hsd->State = HAL_SD_STATE_READY;( N; a5 Y! }  g* C
  149.       hsd->Context = SD_CONTEXT_NONE;
    , s, t# J0 k) W" M5 ?
  150.       return HAL_ERROR;
    3 ]2 g; z( V$ [6 H! X' b5 ]
  151.     }
    * C/ W  ]7 e/ G. J
  152.     else
    9 A9 D* R$ `; ^  w) W# U$ W% f
  153.     {0 c' x! o' }) @$ N4 E
  154.       /* 什么都不做 */
    . \1 H% K3 y7 S6 e4 B; i
  155.     }# O7 {1 u' z$ C9 V- `
  156. * F: y4 I3 n9 O2 c5 J/ b
  157.       /* 清除所有静态传输标志 */
    % K. Y& @. e) M5 Y5 X
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);( a. K" `  p; }' q! U- k3 s! O  Q

  159.   {* r0 O7 N; n' g7 q: ^
  160.     hsd->State = HAL_SD_STATE_READY;
    ! l- m, E  P) B; j( F2 }" Q2 ]
  161. ) N% ~! X0 y' i7 K
  162.     return HAL_OK;
    # \2 E+ x% L: }
  163.   }" D3 e6 k- [- F! S2 g7 J6 ]2 }: x
  164.   else+ |4 s3 P* b/ K: m
  165.   {3 e+ n5 o7 V3 N  K1 p! M
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    9 I3 G: ?+ j0 E1 x: g
  167.     return HAL_ERROR;* o2 P, C( @7 @' M1 I
  168.   }
    * j2 R7 n1 m0 X6 R& y4 e( F
  169. }
复制代码
" j& A, ]2 N, M- P9 l6 X- E8 j6 W
函数描述:6 @5 K  V7 s( ~% b" f5 J
9 U* o2 V' E% s4 j4 j! V
此函数主要用于向SD卡写入数据。2 f* G2 P% k" C
+ U) d7 M& o' R: H% t. ]
函数参数:6 y  b4 C5 q1 t1 ?

+ o1 Q3 w- Q# w, P2 n# g" P  第1个参数是SD_HandleTypeDef类型结构体指针变量。
" L0 X5 E; E6 f. ^) M  第2个参数是要写入到SD卡的数据缓冲地址。
0 k* R; w8 V6 j  F' [; p  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。4 K2 V# I# C' P9 H1 V+ F
  第4个参数是读取的扇区数。
9 e6 q- d; ?: w) j2 O. O7 c5 l7 z! X  第5个参数是传输过程的溢出时间,单位ms。
& ]7 L; w" D6 H, q6 g  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
2 L! [4 w4 p4 v$ K+ t+ D使用举例:
7 Y0 O8 E8 H' F' z/ I, K4 q6 G/ l1 F" i! U) d6 |5 P
  1. /**6 r/ j9 A, Z0 R7 D/ L
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.# T. b2 c2 x9 \/ X0 L* E- F
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    - I9 F- n: d% C: Y3 @3 d
  4.   * @param  WriteAddr: Address from where data is to be written/ J. P: S9 B! y8 H# K
  5.   * @param  NumOfBlocks: Number of SD blocks to write
    " z( a. k* N+ E# X0 G) V
  6.   * @param  Timeout: Timeout for write operation
    : Z1 w4 ]6 v4 g& u5 r
  7.   * @retval SD status
    - P% t6 B& T, Z
  8.   */4 S' S2 z9 T4 O
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)) v/ P8 L1 i2 z% H% C8 d
  10. {
    7 t! E/ D, h# w) \# P  F8 ^/ v
  11. ; u8 b& W3 ~! k- ~% T' P' G
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)) \3 N& b3 x+ |  K4 A4 Y
  13.   {
    ; [- s3 c8 j0 c. M
  14.     return MSD_OK;
    ( I* H2 @2 Q& K; k
  15.   }. E5 z$ L# O4 _
  16.   else  X& `) j+ n- E3 b1 |
  17.   {) [, ]; X9 P! J8 m+ v5 B( d5 u+ Y' L
  18.     return MSD_ERROR;: G2 S; |# W3 \: v
  19.   }; B' v. i. Y) Y1 l* I) o
  20. }
复制代码

" E: n2 ]/ U( F- `87.4.5 函数HAL_SD_ReadBlocks_DMA
  ?# B+ _% T8 [函数原型:
/ A  B! p7 E# y- H& [
& [; W8 B; n# u: \7 y  X8 r$ f
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    % X) Z8 c9 ]+ _3 k- M0 W3 g4 r
  2. {
    " x4 V* g) H5 ?% ?
  3.   SDMMC_DataInitTypeDef config;! c; ^4 J, n3 A5 @9 ?
  4.   uint32_t errorstate;* ]7 ?/ H8 H" `# s0 h5 C
  5.   uint32_t add = BlockAdd;
    ( o" j: r0 Q9 Q7 C! l( ]4 _
  6. . J& J0 `$ N" J3 e
  7.   if(NULL == pData)# B) F- \: R( Q$ Z
  8.   {
    - f& Z/ a) c3 D) o! l( O
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;- \6 |+ D8 l3 w( g6 o
  10.     return HAL_ERROR;
    # l) @, R: T. X. {% u  e: O; ^
  11.   }( `/ ~: v8 H' q9 E, M" H& g% [

  12. 8 E4 ?4 E. Q! V$ c" p% T
  13.   if(hsd->State == HAL_SD_STATE_READY)7 b$ M8 ~0 J% z* T9 W* j
  14.   {; ~9 C0 w, r* J1 @3 V, |4 z$ U
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    & i3 a: P0 m$ X" z4 ]: q- s
  16. * P; ]. T; C- d% w& r" a( i/ z1 N% @
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    1 t* h/ |# ^/ ^# v
  18.     {  D5 v; W$ @& ?' ^
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;9 d/ i& {& d( |$ ]3 h
  20.       return HAL_ERROR;* N5 ?7 e% `* }' w) ^
  21.     }
    + o$ e, n4 A2 W5 V7 y

  22. ( {& b  g  K2 e5 G0 `6 c. M: A7 ?
  23.     hsd->State = HAL_SD_STATE_BUSY;  r( E/ A' Q) _- j* `) k7 ~
  24. 2 @4 a9 ^) q2 n- R  [6 h
  25.   /* 初始化数据控制寄存器 */
    : R. ^/ ?7 T. `/ p9 n4 Q
  26.     hsd->Instance->DCTRL = 0U;
    ) X# f- x' j; _3 D! z) z( k2 E
  27. , K& U0 C* _* s* M( N& S
  28.     hsd->pRxBuffPtr = pData;1 f7 x8 ]$ b! x" X  w
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    + l# C& R8 u+ U0 o

  30. / c# J3 H! n' c" E  I
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    3 x- s3 `9 V0 f  J2 j
  32.     {7 ]( z$ u/ a6 J9 Z0 {& n/ X+ _# K
  33.       add *= 512U;% w2 K/ k: f# L7 E% B
  34.     }
    % C+ z  Q4 ^( _5 I- f
  35. 2 o  ?1 N. h5 g* q
  36.   /* 配置SD DPSM (Data Path State Machine) */$ ~6 D' |, J# d0 b8 W  D/ u
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;" k. H- {" A+ z7 Q
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    * F) K5 k* r5 I4 z4 T# x6 k
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;% p* y- r2 ?6 V: K1 W9 }
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;1 x' i# {% N; d( P; Q! |9 u1 l
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;, y& Q6 z% |' W3 j/ l  H5 f4 X
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    ' S6 K/ f1 J5 d- S
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);/ |( N  V8 j) a

  44. 4 J6 L- y/ T0 A4 ~! B
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    / X$ @! {$ G1 \& U
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;! F" F; }9 W1 D% A7 K, \# I& Z
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    4 e% Q3 m) ]$ y& ]+ V# G

  48. 4 \4 A7 y9 P3 ^* w& }( L
  49.   /* DMA方式读取多个块 */
    4 H; t% S" t) ?1 M' v9 C( A
  50.     if(NumberOfBlocks > 1U)/ V- ^8 V$ S) ?) w
  51.     {
    $ p1 O( y3 L- ?; F7 t
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);) y5 f' W8 Q. H! f% K

  53. - G' b) z! L% ^+ X7 m
  54.    /* DMA方式读取多块命令 */  Z) U$ I, r7 ?: y
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);) [: {: Y8 j& Y
  56.     }
    ! ~/ d- ^' |+ M7 |" [& O! h7 M2 |9 N" K
  57.     else
    3 F+ x- m& Q, X$ H. D, T* N3 j
  58.     {8 u, _6 j7 Y4 g6 m1 ^7 h7 O
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);; G/ ]8 I  n, m: z3 M) E& C
  60. ; g% Q+ R$ |9 h- ?1 b
  61.    /* 读取单块命令 */
    : L7 j. {1 F$ P" ]" F* i
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);6 z) \  J5 w+ x# R  l
  63.     }
    3 e9 B6 c# A7 F% ^6 Z' F7 Y
  64.     if(errorstate != HAL_SD_ERROR_NONE)3 r' I  `/ P7 u9 i/ v4 l  q( t
  65.     {
    4 V6 O0 k. K& F5 b9 c/ ?0 F
  66.    /* 清除所有静态标志 */
    - D0 ?' y" g. G) j; l# L
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    9 r2 ]4 v# F) t$ J
  68.       hsd->ErrorCode |= errorstate;
    * f  p* N; t% i' A+ X& A
  69.       hsd->State = HAL_SD_STATE_READY;
    * A4 c4 n- m; L0 \) `
  70.       hsd->Context = SD_CONTEXT_NONE;. [9 f/ {0 h) b6 e- H
  71.       return HAL_ERROR;
    - i5 e: U3 \- C9 N5 B
  72.     }2 M& F9 o1 K+ p) t! l
  73. 9 o( _6 w6 s) N5 n
  74.   /* 使能传输中断 */
      Q- U! G4 L+ @- A2 \) B7 W8 ]
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));  e6 {1 N, t# w0 q# q$ O0 m

  76. ) ]# G$ W) a7 Y6 I
  77. 3 P- z. @5 G, W9 ]( V7 W& Z
  78.     return HAL_OK;
    5 D" ~6 }1 j: j, ~5 Z
  79.   }7 {2 @8 w, S' `9 o" ?
  80.   else
    , |; F& k% T, h, |5 x; ~+ A$ N
  81.   {# Y0 g$ Z3 v2 G* F5 _
  82.     return HAL_BUSY;
    0 R5 Z- }/ u* u; Y
  83.   }. S8 h, i+ J; n+ D  J8 H/ _5 R
  84. }
复制代码

! c2 g/ h4 k2 O$ R9 ~, u# b0 r函数描述:0 N8 j; g& Z; j
" P5 D. x" Y) W" d3 l# m5 I  U' N
此函数主要用于SD卡数据读取,DMA方式。
5 f; D  f. ^  l' w* v7 z
$ w, U7 d5 Z; h# ?函数参数:
9 E( k. t* [. ]3 D1 b, ]) v2 \7 m! _: E0 n. w! M% t& D8 b
  第1个参数是SD_HandleTypeDef类型结构体指针变量。3 I0 |7 O9 ~& {( [! u. Z: Z6 U; W* J+ a9 t
  第2个参数是接收数据的缓冲地址。
% |$ _, _7 p6 {  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
/ c4 ^5 O- F3 b9 h/ k  U  第4个参数是读取的扇区数。
. J- m, t6 ]3 v0 x; A1 L  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 S* D; ]8 e2 |% M4 \8 M0 @
使用举例:, E+ t( c3 `3 [, F
( S4 r. v+ A  C% }) Y
  1. /**
    $ a: |+ V5 l4 X* W; \8 w
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    ' u4 T  k' k1 n. L% k
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit$ Q6 S8 c: o! N5 b
  4. * @param  ReadAddr: Address from where data is to be read4 I& h$ B# g6 _  j) M- k' c
  5. * @param  NumOfBlocks: Number of SD blocks to read
    & r. ^7 u% ?5 W, W& u- {% V# n4 N
  6. * @retval SD status
    & N4 c+ t* _& c9 o+ B
  7. */
    - f2 ]- L" b, Z6 |7 r+ t! }
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)# ~2 o0 T2 d8 W" g: c
  9. {* r: e9 C+ {! I& h& |4 e6 u* n
  10. " o: O6 C2 T$ E: e& D
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
    ) ?* O; R3 ?& r3 k6 W4 p+ z  t3 t
  12.   {3 v% P1 Z& O- f2 B
  13.     return MSD_OK;" j! c( {$ M2 n4 M
  14.   }1 \! l3 E+ i6 l" \! g9 J- |% H; H
  15.   else6 A$ i. N% M& I  D( T! R7 ]
  16.   {- r! B5 [, F2 t
  17.     return MSD_ERROR;, x  y4 c! V$ B
  18.   }
    9 u7 S6 `# m  k% z5 `
  19. }
复制代码
" a1 g5 r' e* d0 `3 h9 x- f
87.4.6 函数HAL_SD_WriteBlocks_DMA
: W; K6 L7 E4 _7 h5 c2 H函数原型:% \, {* K- ]0 j! |, C2 g
& l8 p, y2 [& J) s
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    8 \( v! z% X# ?; k8 @$ Y
  2. {' _/ R$ }& {( w1 u  C( R
  3.   SDMMC_DataInitTypeDef config;
    3 M6 C3 o* I: m8 @
  4.   uint32_t errorstate;
    $ e0 L$ d# R& u2 m! `4 ~$ [# m3 d
  5.   uint32_t add = BlockAdd;/ Z- g% f5 K& u0 R
  6. 1 c: s. E/ g* N  R6 j2 k
  7.   if(NULL == pData)
    , H8 [' c6 ]0 T% }3 ~
  8.   {
    ; s& }+ z0 E$ g$ ?
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;) \& o% Z  ?5 C7 e# n
  10.     return HAL_ERROR;; E& R  X: T5 {1 H% l
  11.   }- n6 `$ Z4 l( F) n; K

  12. : e: S1 ]* e$ s$ M/ J7 ?
  13.   if(hsd->State == HAL_SD_STATE_READY)
    ; h. b3 A$ X/ N! _, ?* [
  14.   {/ A) e# Y4 N' ]/ a
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;5 S: m  K- C5 }+ M7 P6 ^' ^
  16. , p. [* \2 b1 p& [
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    1 j  ~- K+ K" y( k' t0 j  Q
  18.     {+ d8 e4 x' F) u3 m2 D1 Z! l
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    * I3 ^1 ~$ t* W
  20.       return HAL_ERROR;
    4 k% [; U* i. J1 z2 j
  21.     }
    6 p* E+ v7 R4 W& {; a

  22. ' C( x9 d; E7 W
  23.     hsd->State = HAL_SD_STATE_BUSY;
    : D9 O4 O! J% ~( _& i$ ^
  24. $ z$ ~6 g+ G; S( v; S' P
  25.   /* 初始化数据控制寄存器 */9 ~5 ~4 f( A$ C
  26.     hsd->Instance->DCTRL = 0U;: h/ Q) o" N1 B. T, F+ r- ?
  27. 3 j; r' `3 J4 P, q1 F4 e6 y
  28.     hsd->pTxBuffPtr = pData;
    : T: o9 l1 c1 c- w7 P7 ]
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
    ( l& W3 H6 o  b2 e% s
  30. : t( d/ ?8 t8 e2 P7 U
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    , j; f3 A( g9 Y. X& m9 t0 ^
  32.     {( m9 R7 M$ W9 r$ P" F* s
  33.       add *= 512U;
    2 [+ ^) j5 f3 V. I! _  S0 X
  34.     }
    & c* _1 F( j  ]% x

  35. & k; V' `! \$ ^/ N
  36.   /* 配置SD DPSM (Data Path State Machine) */8 x# X; i0 c8 T" H0 \
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;2 E8 c1 o1 I. Z) p( G$ H: ]' N
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;& Y; [3 q# d' O9 Q
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;% ]/ `8 k1 r5 P) Q* ^  l  b, }
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    . t9 b. P, d5 z* z
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;" {8 I; R. u& }
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;3 F/ R3 M! m) ^  X& ~
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);! g) l8 M  X  z5 O
  44. & {- S( |) `0 ^9 a) G/ u

  45. 1 ~+ ^+ e* H, E4 G2 ~- L9 T' y
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);8 D. t  f3 @3 g

  47. 9 |: T& a4 u  _* ^8 E6 h
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;  ?7 @7 j9 v  ?+ ?. F
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;9 I, O: |& N7 k, X  {" |

  50. " K. ]7 K) j& K  O9 I
  51.   /* 查询模式写块 */# Q0 W  s5 k5 S! |7 `5 a# z
  52.     if(NumberOfBlocks > 1U)9 z7 X3 ]& d$ b
  53.     {. N  G. E" r) I
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);; t7 U  q8 X1 Z; l: q* ]( A

  55. 5 r) m& K" U, V' t5 s+ a# ^1 j# C
  56.     /* 多块写命令 */
    # k+ ]4 f. s; K% F7 g( N; G
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);7 ]  v2 J/ H7 T
  58.     }
    * _4 [& z% [1 V( Y
  59.     else/ i0 n4 X7 }' H9 u; Y
  60.     {7 |* L' o& Z; v/ x; n( \0 ^( K
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);$ q6 c  \9 d! w
  62. % ~# c4 o) G5 A/ x
  63.     /* 单块写命令 */
    0 A% n2 b# ?: q  t; q: r" n$ n
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    1 ~7 {/ w4 _, ^: @: j/ N
  65.     }
    & ^* y( d! G2 \) [/ ~
  66.     if(errorstate != HAL_SD_ERROR_NONE). v0 D: d3 `% g7 _! e9 m: `( W; o
  67.     {
    7 H' T, w8 a3 K" z9 [2 p
  68.     /* 清除静态标志 */
    2 i4 p: d* q  c' I, V
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: {3 V6 o9 v6 Y3 j+ [. ?$ l
  70.       hsd->ErrorCode |= errorstate;2 h# v# w8 H7 v0 ^& k
  71.       hsd->State = HAL_SD_STATE_READY;
    4 z0 s- n/ l5 N; J
  72.       hsd->Context = SD_CONTEXT_NONE;1 T3 R% |9 P9 F& e" f+ i
  73.       return HAL_ERROR;% P9 p! F) a0 ]" G* ]  X2 n& v9 a
  74.     }& W( |2 g# Y3 l
  75. 0 {/ {* ~9 u7 c$ |& }! ~. t
  76.   /* 使能传输中断 Enable */
      i+ s" e; g. z4 v5 Z# W
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
    " y% T9 d/ F$ |4 j8 ?+ `
  78. ; s8 h9 ~) |$ m5 ]  _
  79.     return HAL_OK;
    % ?/ k- c8 q: ?3 o) M  e' v
  80.   }. A4 `) T) @) i8 D9 E% R, V
  81.   else$ S% D+ E* Z( i, q$ Z
  82.   {" r8 J4 s. Z1 q4 X4 h, @$ m
  83.     return HAL_BUSY;* I, B1 A; V" P  G3 a  ^
  84.   }; P* t# ]! O; L; U% x/ c9 K
  85. }
复制代码
1 u. R3 R) e9 _9 l5 O
函数描述:
  K, D& _1 z/ e. f
6 K) |3 ^3 C2 f0 @* A( {5 R7 c) X此函数主要用于向SD卡写入数据,DMA方式。! u  S: T4 U( h1 [# A3 i! v1 C$ y
5 m' Q4 S4 i* N) G2 D
函数参数:
& U( V/ t- z8 u' c, v6 m; Y; ~  D- u! \- \
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
( U! X, x' _9 e" B  第2个参数是要写入到SD卡的数据缓冲地址。
6 D% R6 l* P0 R" R6 D. {  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。% x$ r4 q( S! A$ D; J/ ]9 q# Y- `
  第4个参数是读取的扇区数。
' E& {; S/ w6 B3 l) i  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。) J! S, u& ]. O/ s/ I2 c+ q6 D) P
使用举例:
- C7 u: o1 r$ N5 I: K0 P
5 m. g6 X( J6 ]5 ?4 e6 _  N3 H4 g3 `
  1. /**
    + ]9 }+ j" \) o/ J  N8 f
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.2 L3 X+ [; S) e4 i' A. x! }
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit' {  i# O$ Z& v2 `; R
  4. * @param  WriteAddr: Address from where data is to be written
    ) f- y% X: E- g( I* o& e/ l2 w6 q
  5. * @param  NumOfBlocks: Number of SD blocks to write7 {2 i! C6 i5 J9 X5 X* b! @
  6. * @retval SD status& }* w' J8 A9 b; R7 w2 Z0 e+ B: C
  7. */
    3 E, X* ^' O: _( s3 A
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)( E1 F3 P- l2 \1 n( E! Y, O
  9. {6 y+ x) \9 }4 d. C, N
  10. ; y/ v5 q6 n( T$ @" S5 D
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)8 {/ N. R4 D/ ~" O. G: w" L
  12.   {& |& J2 g% k8 y5 G3 }5 T
  13.     return MSD_OK;
    % d) k! Y- z0 N  ~, i# E
  14.   }! M$ i  |' @7 L# R
  15.   else
    2 D% |2 y% G, W4 a* U
  16.   {6 b" ]$ A& a" S  h5 d$ q$ J
  17.     return MSD_ERROR;
    % P( K- K4 R, G2 D, d3 w, B  S
  18.   }
    $ E! L6 r+ R8 D: o) U
  19. }
复制代码

+ a7 Q0 n$ \3 t0 U5 S" A87.4.7 函数HAL_SD_Erase; e. S# u, ?2 Z. x( K
函数原型:
- W. C- [- {: I% ~: a" {
) W3 l! Q; u; z8 [& Y! J$ v
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd): F( z1 L. x2 G
  2. {9 w1 I* c0 b( _% e  u- w
  3.   uint32_t errorstate;
    1 b. b0 t, K% P8 D5 ~. |  b
  4.   uint32_t start_add = BlockStartAdd;# p" y9 p7 T. K# ]. _9 R
  5.   uint32_t end_add = BlockEndAdd;5 i2 A* q. Z/ _& D

  6. ' ?' y+ ^7 e  R  ^
  7.   if(hsd->State == HAL_SD_STATE_READY)
      P. f6 E) m7 l  W3 O1 u
  8.   {: M; ~; g* K# g
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;7 G# D% _4 _  s' r

  10. & e, T7 w8 M8 ?1 j, m4 b' q2 @
  11.     if(end_add < start_add)2 A! x/ ?1 v" O6 Y( X8 ?/ x
  12.     {
    $ x6 c4 n5 n8 F* ]4 B/ D4 Z
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;: C- E) M  M4 K( s7 M3 s; t* q
  14.       return HAL_ERROR;5 m' p7 K1 j; p/ _* f' ?" b9 m
  15.     }" Q  X( t; {8 y: w7 u/ R

  16. " \$ Z' D4 O/ q0 |9 m
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))8 X, N) R6 i$ x7 s
  18.     {
    : q  f0 |+ q" q/ g
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    9 _8 g, \. ~( t0 o
  20.       return HAL_ERROR;1 A  j5 M8 O& r# o+ m/ A2 G
  21.     }
    + L0 C9 F: X/ M" y* m
  22. . @+ {7 T6 {! _. z
  23.     hsd->State = HAL_SD_STATE_BUSY;7 m5 J4 Y% U& Q$ y; R; K
  24. 5 a* v& z8 x7 T9 v+ r. V( c$ e
  25.   /* 检测是否支持擦除命令 */' h  u0 {4 g3 i, r/ U8 b
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    8 d8 g1 a4 [; q) E4 x" a( `3 j
  27.     {7 M; t- w: P/ a
  28.       /* 清除所有静态标志 */, H( M; x0 L! ~, b4 z
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' ~1 e5 z. Y$ _2 B- W
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;/ ~6 X8 m$ V( U- @9 N3 D
  31.       hsd->State = HAL_SD_STATE_READY;6 K" t+ s$ ]0 B1 C: Z1 o/ W, ]
  32.       return HAL_ERROR;$ Z' n. M4 \. d& @# [2 y; F6 Y
  33.     }& Q  n# h* e8 L
  34. ) w# M% M$ \- {$ B7 P# M
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)+ A; `! Y2 I" C1 h: E. C  m5 w
  36.     {( X- Y2 y, l$ b+ |5 J
  37.     /* 清除所有静态标志 */
    - F, K+ A# G2 E4 F$ M% m7 |- ^: `& D
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    5 m3 Y( }/ }% [& |8 h8 C
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;4 ~  V, o( v1 M
  40.       hsd->State = HAL_SD_STATE_READY;' W! J9 M3 y# g: D, T
  41.       return HAL_ERROR;6 `) \, k: t  a# d/ j8 T
  42.     }/ U4 f& u7 d& x1 H
  43. 9 g) H; X  v5 i
  44.   /* 对于高容量卡,获取起始块和结束块 */6 b, U* O) z+ ]- I' d% e
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    * C* p! ]7 X  @) [" q( V
  46.     {
    + s% V; S+ ~+ \/ Z+ C' S/ V0 ~
  47.       start_add *= 512U;% d6 m2 I- ~5 T
  48.       end_add   *= 512U;8 `; o( p* I6 ~- `6 m
  49.     }
    5 d, r- J) \. j- w

  50. # n8 X$ I% E3 b5 ]
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */0 P+ n% D, M) z; l- V
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    $ b7 p5 @' M/ F+ Y; F4 d
  53.     {
    # [/ @* l0 L! n- F
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */+ y  U, g7 W- F% G" _9 C
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    ! u5 F1 U- r* {9 s  |
  56.       if(errorstate != HAL_SD_ERROR_NONE)7 f  [" A1 \0 l/ s
  57.       {# }8 ^5 r5 ]9 P3 r  B: i+ f/ f+ h( Z
  58.         /* 清除所有静态标志 */8 X9 y, D# _: c- H# B
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);( D* q" n, n3 I0 e! x
  60.         hsd->ErrorCode |= errorstate;+ A  e7 ~; R* W7 h1 T5 j. Y
  61.         hsd->State = HAL_SD_STATE_READY;. j2 V% [% `1 ]
  62.         return HAL_ERROR;1 p4 \$ D8 E9 e2 J7 l
  63.       }5 x/ u; K9 H# [* @$ m* a4 g* r9 n& b

  64. , |1 M$ a% t; ?- h$ u3 M) I1 o$ j8 d+ i
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    ; l) g  D* |5 B7 l3 v$ w; x! N
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);2 }8 v" O; {$ ]7 Z
  67.       if(errorstate != HAL_SD_ERROR_NONE)
    * _3 U8 X+ O' {4 P  Y
  68.       {
    ' h* _& S9 H8 Z0 Y! t  \' d
  69.         /* 清除所有静态标志 */1 i0 g4 U) A$ R" @) X  x$ U' j/ ^
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);- t4 p2 E  G  K! v+ x- A
  71.         hsd->ErrorCode |= errorstate;7 x/ I2 q3 j% D% p, n6 Y
  72.         hsd->State = HAL_SD_STATE_READY;
      V0 q- J* T" L  i3 h: k# z+ Z, Y; ~
  73.         return HAL_ERROR;
    ' [2 E6 ?0 i) `6 ~
  74.       }$ ^0 M, C6 S) O
  75.     }
    , n" O* X8 U3 O' g
  76. : F' `2 Q% A# C5 b$ ]
  77.     /* 发送CMD38 ERASE命令 */
    # O  f( Z* {$ w. _; B! q0 o
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    3 |& J# h1 F9 t) w( t/ P/ i
  79.     if(errorstate != HAL_SD_ERROR_NONE)6 D+ Q- O' h. n
  80.     {
    " F+ ^9 g+ ?: z: F7 U0 o- c- i
  81.       /* 清除所有静态标志 */
    # O1 Z2 @& m2 J' J
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);$ e! h3 N2 h5 r/ q. J& `
  83.       hsd->ErrorCode |= errorstate;
    % r' X, g/ {# X) z7 F: \& r
  84.       hsd->State = HAL_SD_STATE_READY;
    ! M9 i- x% A6 a
  85.       return HAL_ERROR;7 y2 l$ j$ ^7 Z/ F' _" M$ G/ U& q
  86.     }7 L0 y1 \* y- U6 A9 ~  [4 L

  87. " w0 a8 X' x% i1 k3 [4 ]4 z
  88.     hsd->State = HAL_SD_STATE_READY;
      E. I; F1 ~% x# j  R6 u8 z$ C; S
  89. / Q! ^$ v/ Y1 [1 k/ I1 ]& Z- ]- g' b
  90.     return HAL_OK;
      h& u' S1 o3 ?5 k
  91.   }
    ! n, q2 X9 E$ L# C( Y( z# {4 y  M
  92.   else2 {/ y. o) Y& e4 a: m1 _1 O$ O
  93.   {
    ; c: L( s$ h) }7 j) F
  94.     return HAL_BUSY;
    & L, H. I" c0 x" C
  95.   }
    ) z: s( D$ T/ e* _, k# m
  96. }
复制代码
- M/ \. o0 S( U# l/ c% {' i' ^
函数描述:! k* u2 `; J7 O7 r+ `0 D0 Y

7 c( |+ V# ^  Y4 b, i此函数主要用于SD卡擦除。) S3 K9 O! P% I$ x' q
  a6 V% [  A: U. [
函数参数:7 q: @/ n+ ^1 ?4 d$ r

6 Z" a. ~+ E1 a' O  G& U  第1个参数是SD_HandleTypeDef类型结构体指针变量。0 U; Y7 d) W' h5 E0 p
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
! v+ H. {1 e) a( K' Z, c/ x  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。7 ]) R/ y& A1 r# p3 d, H
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。/ x8 Z) ?5 O& x
使用举例:
" d( j; G" C4 J& \" c+ w
4 p& E+ a! p9 i7 J' \6 T
  1. /**7 n: ^$ _2 K8 d- O  a
  2. * @brief  Erases the specified memory area of the given SD card.
    * v: P- ~1 n8 ?& B% Z( e8 n# [
  3. * @param  StartAddr: Start byte address; o: D2 {3 E* Y) X( R) ~
  4. * @param  EndAddr: End byte address
    4 ?; }" C) j1 I
  5. * @retval SD status
    % H; Y( ^' d2 ]  X3 r
  6. */
    4 Y% q2 Y, l- ~* h+ J" Z
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)  y$ K! T# v" O6 d1 p' g: r" K
  8. {0 I) r" G5 ]: N5 ~

  9. % \1 m) D1 Y: \; Y' C9 [# G
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    0 n, R2 J2 z2 m+ b
  11.   {
    ( R0 i; A+ u7 \: k! s
  12.     return MSD_OK;1 `7 d) }- v, `6 `
  13.   }
    . T' l* J3 Q" g+ S1 F
  14.   else
    + u+ D0 n2 v2 ^( V5 a3 B. }1 B
  15.   {
    0 T  [7 Z+ ~; n" P, H
  16.     return MSD_ERROR;
    ' E/ |0 h. [" y0 g8 F
  17.   }1 V# O$ n: [( @4 U0 {
  18. }
复制代码
+ W# Z8 z2 h/ l. q. l
87.5 总结
# f( P# u7 ^5 J8 C& V3 s- I本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。# p  o( o& P1 p# }. B) N/ ?
( y5 ~# P7 R$ `4 J$ d) t2 `8 m

' Y5 p/ a" s& |% E- P
收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答

所属标签

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