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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示+ O( w, N+ Y! q- a. R1 D4 w# n
  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
$ D9 Y0 q7 w# k' H7 A! g2 b% E  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。  V$ g  t" W6 g% Y' S  O
  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。4 ]( f$ Q" B" _, w! q
  SDMMC驱动SD卡支持1线和4线模式。2 B  V1 Q+ c, I
  STM32H7的SDMMC也支持eMMC:
- N) u% s5 S3 J) z& u$ c  * q4 z6 Z3 d: g( r4 r  o
87.2 SDMMC总线基础知识: @7 E) p* L- o
87.2.1 SDMMC总线的硬件框图0 Z$ H9 P3 {% r8 y8 l
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。0 Z0 I  F: x$ I1 C) w0 a

  {& v7 U) @5 }4 a
6eea62abe623396815a50adc87205b83.png
+ K. N. ~1 V# m/ ^1 x

& h4 h. d$ s- F6 l) a通过这个框图,我们可以得到如下信息:
3 x7 H, Z: j& [3 h( x( e/ M; z. v7 |
sdmmc_ker_ck输入
) K* i: E7 R1 O0 x. d. @* uSDMMC内核时钟。
6 @+ ?  E( F) c# w! \
  o$ l7 N7 G* j/ c- _  A  sdmmc_hclk输入, O$ O/ S+ Q3 x6 Q) ]$ ]
AHB时钟。
8 T* ?& t5 O- {' X5 |9 W7 x: M+ y; i, O' c' D' m
  sdmmc_it输出
- d0 }% V; h" G/ QSDMMC全局中断。
8 ~% b, v  w9 Q* L- ^# L2 m& q) l$ y8 _
  sdmmc_dataend_trg输出
9 P( f9 J" E4 I" IMDMA的SDMMC数据接收触发信号。
  I+ F3 k/ I3 z# T, h4 z
& ]" f0 c1 K6 ~  SDMMC_CMD
2 B/ {/ n6 p6 Q* o" \" B$ mSD/SDIO/MMC卡双向/响应信号。
6 X6 z* `6 v& b. R5 o4 v  B
' [- a' K! M: y% r( @1 r9 |  SDMMC_D[7:0]
- r" }$ f0 o3 E1 ]: lSD/SDIO/MMC卡双向数据线。
5 D  c3 n" J" K6 ]" t) Q( T: g- B  b$ O
  SDMMC_CKIN7 ]- B- ?- N5 U# J
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。* ?+ E4 ~9 I; r5 D' O+ {" T

+ Z7 l- g6 v: e! z1 K5 r  SDMMC_CK/ t+ e- Q5 f7 i" G+ {
SD/SDIO/MMC卡的时钟。# P4 x' P0 o7 d3 A4 i

2 A3 e. P0 b# S  SDMMC_CDIR
/ h  S1 H( `5 p0 Q; rSDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。# `+ i; t/ j: ]! t

& |5 i5 k0 e) `  SDMMC_D123DIR
! ~4 r3 H. w; i: pSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。+ i9 r9 G) d  A; d4 s+ {

& n5 n. L- ]+ e2 d$ `  SDMMC_D0DIR& T( ^. A, X; j. S6 Y. I6 E# f& B6 Z
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
1 B$ h2 U4 `' E6 p
6 `2 X* `3 G7 g6 m( Q" a* d- @STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
7 T- I2 p' _7 M
4 C8 L3 _4 d  u' ~6 x- a87.2.2 SDMMC时钟) t; n; a2 t2 U( i
SDMMC控制器的时钟来源:
* c+ ^0 @) }; g/ T- l6 C
  M3 p$ p, |$ J& v( ~
676ec31792fcb80bee640ed979d48084.png
/ e: X9 |1 g7 Y' E* q  q9 V4 B( t
" ]8 N* Q5 x" x) X+ t% u' \. j
SDMMC1和SDMMC2时钟源是一样的:
5 u9 k7 ~# N3 e5 \& B, O+ K/ w5 `0 k  `8 K" s  e1 m- C
79b1c69986d1ee5bc090bf1676f396fd.png
# U' w8 _0 o) e! v2 C) `( r4 E
) P( }6 e0 d  B# _1 ^
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
, B/ T# j2 x# o( G& Q9 O' }注:大家应用时要特别注意这个问题。' O) q! X# C# P# L

% M; r3 q! b8 U使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的( l, c2 ~  o2 @- g& f; s* v
6 y; x' `9 J% d* s
6a5491d2f4a8740d838af58d034b7597.png
/ A5 |- d( A" l) n$ N
7 M% l7 U" [2 O, ~2 p
87.2.4 SDMMC支持的速度
5 m6 K  z, W4 ]# \驱动SD卡支持的最大总线速度:( p4 z: g6 L, F/ e% E

7 K) [1 ^" d0 J- k  B/ ]
b70ce31107b38ea820dbc28c3caec38e.png

" b/ T  W  X( V0 R( p
! T0 f7 G& u. M& J) Z% P驱动eMMC支持的最大总线速度:
, f" ^0 O- W7 L! C8 G
( ?% }( v4 x7 ^3 E# w
843bf7a054944ba7d5d137ca84e1d4ed.png
8 d0 N$ E4 p, `, a+ _4 ~4 p

# ^& c0 r1 d. r关于这两个数据表,注意以下几点:1 O  x: q" B: T7 N' z. U

  a, y, |7 `, p, T# M5 t% X  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。  J4 J2 D4 i9 @1 y! P. \1 J
  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
7 _$ d/ h# S* B& C, v$ G  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。. y) z  X6 m1 c% u" `4 {- {- \6 A$ u
87.2.5 SDMMC支持UHS-I模式
% n6 p; y4 \. J1 M& T; qSTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:# c. G0 ]% T8 k# y
, V8 J  u5 V) j3 z, x" J+ U
2b8e4430b8a60dc5a1b342d7c7f75f52.png
0 y1 F/ S9 O# X" o7 |
6 H! m5 L* V) J$ b/ h; h
85f975745619c9afc64f8889289dad58.png

9 n/ I% }$ l. }# }9 o3 `5 ^# @& H6 `; r; O9 @% h
87.2.6 SDMMC自带的DMA控制器IDMA
$ [5 r/ y1 N- c/ u' ^5 K" kSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
# M# c, z3 |2 Z7 K3 h) X1 T: h6 M6 M4 f. @: N+ w; q
87.3 SDMMC总线的HAL库用法8 R  b; r* ]: X0 M3 t* r, G
87.3.1 SDMMC总线结构体SD_TypeDef
. ~0 ^8 I, v2 q) r( J1 _+ S% JSDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
. }5 J. `" \$ l' W
# H0 y. I5 n8 T. D! h  t# d% G
  1. #define SD_TypeDef          SDMMC_TypeDef$ Z# s4 @6 t7 @7 ]' s
  2. typedef struct
    - y* E7 P. x" i, x& G
  3. {- w0 o9 n$ ]5 z. p  \+ P8 y2 Z
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    $ P5 S7 G3 A7 U) O/ [
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    / u# T( h; x- u/ x5 V
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  *// f$ s/ h7 Z8 g0 g, Q. O" D
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    " P$ U' V' K6 }) O
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */) ]& q/ K1 J  B1 k( |' s
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */3 i: X% g# u( u% F& W8 e$ A- o# m
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */7 G4 R3 V5 Y. a5 g
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    $ n0 O  {" N5 ]- y
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */; }4 P* D3 s  J/ E6 r3 m
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */% O" _# K+ h( q$ m; ~
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */% S. R& c% I0 q, ^3 h+ T7 d& C' Z
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */5 U) s  P8 ]: g1 R; [$ m  L
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    / x: j& W5 h, m7 I" b. V
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */
    7 T) Y& @: l5 e4 N1 Z* v) l5 d
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    & ^- _* V2 i( J( G6 P
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */6 O" G% ~0 P' v' ^. W
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    2 V$ z. c" Y) \& u! T, z
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */
    $ ?( }( {4 E6 @) K! _1 S
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    2 W% D- k/ h6 g6 J/ G9 G
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */& M! L9 ^2 |' O: Y) C* s* q( s
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */$ @$ D' R* `7 e- j/ R, l
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */2 H' @9 R' e3 s' l
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    1 _% {6 x0 V+ G' x% z0 {
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    # g; F7 l1 r# g
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    2 k+ q) A- c& [% r0 A$ W% N4 s6 ^
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */! h9 ~  y5 w. c  N! ^
  30. } SDMMC_TypeDef;
复制代码

. ?2 s2 C2 {- _5 O这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。- w$ Z  ^9 E) l9 y5 \5 p
2 C! p( g5 v2 ]- L! Z  }
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:' f6 a9 A$ z" F+ Z; r2 h  h( n
+ e3 c. R  }% ~! N- ?
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    ! o* [7 x( b: D
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
0 Y) f8 J7 u+ n7 R7 E) A
下面我们看下SDMMC的定义,在stm32h743xx.h文件。
4 ^6 a5 ^  S* C9 O" @+ b4 y9 r
5 Q4 [# h: w% e
  1. #define PERIPH_BASE           (0x40000000UL) % _+ M$ g$ s4 Y. t  }/ i
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    9 F- l5 }- T5 W5 ?+ G
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)! s" H) M* S$ r% E
  4. * [$ N# r, ^" m5 ]; ^
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    0 P* d2 I  f) K/ u3 s8 L( W
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    ' O# W$ z7 D% R. {3 n4 @1 B3 |

  7. * y3 U8 b( Y; T) ^2 c0 o) W1 ^: u
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    ; E$ W& J- U& t+ T: p& ~1 ^
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

- [5 O9 I' k/ B) d0 p6 u3 a& ~" E我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。
% j8 v) J4 ^  H5 T
6 L: O; N$ C5 t$ Z5 J& ]7 x87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
* b) A" X+ \# t5 m& m5 ^- q下面是SDMMC总线的初始化结构体:% o, }  s8 o: Y7 j' p4 n5 p
% w4 _9 t: M& j
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    ! s' U8 Z; x  \( P
  2. typedef struct8 C7 G% D+ c. {. H$ b8 x
  3. {
    6 C! q# [4 V4 m; R& f0 Q8 P
  4.   uint32_t ClockEdge;            $ R: w1 r- `! g- d) R' \
  5.   uint32_t ClockPowerSave;      , }% `! P( G' V) R' y& v' n
  6.   uint32_t BusWide;            
    * J$ h4 I+ Z  I+ B. M2 a
  7.   uint32_t HardwareFlowControl;  
    9 Y* J0 f2 w! w) i- Q, E
  8.   uint32_t ClockDiv;             7 e: k9 J# O' n" G# H
  9. #if (USE_SD_TRANSCEIVER != 0U)
    " v% M" d8 X$ _1 k7 {! u: ~
  10.   uint32_t TranceiverPresent;   
    8 G8 L5 T; y/ X; D! F
  11. #endif
    & B* P1 I8 L; G' j7 M
  12. }SDMMC_InitTypeDef;
复制代码

: T3 m9 [5 k+ k2 h: i9 H下面将结构体成员逐一做个说明:
, \: \: b! V& ?! O7 }; x" h+ ^5 C& l' ~
  ClockEdge
8 |6 T; a9 E$ J! @3 m: S用于设置SDMMC的数据或者命令变化的时钟沿。, m9 N; g, a& n5 w- c" t/ S
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U), I7 w! k9 y* m( m- s5 G; ^9 Q
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

  a6 i' L$ {" _: q  ClockPowerSave  \, M9 [( [& Z+ W
用于设置空闲状态,是否输出时钟。
( M: [+ J, {, E
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)
    , m: s2 t  B& R& H, r1 ?4 N
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码

; ]0 ^3 Z# j  R. B  BusWide' D# Y: J2 j  g( V
用于设置SDMMC总线位宽。  \3 P  ]' t) E4 ]4 @$ H
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    / N, e- P2 S6 T' `3 c7 X9 P% ]
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_0- F0 B, m$ y4 e! d% G7 i  s
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

# O6 `- T# Y' {. p& B7 f7 q  HardwareFlowControl8 B/ o3 e2 W4 d! ?
用于设置时候使能硬件流控制。
3 @+ I: N* W5 m6 Z' m2 t. k6 [
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)% ~# t2 Q' {, r: @! M' m  d
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

% ?8 G0 j/ `- O# d  ClockDiv
0 n( O/ ^0 a0 _- N. B  ]+ p用于设置SDMMC时钟分频,参数范围0到1023。4 a+ [' Q) g* \7 ^& `7 m
3 y# B. a" n  P! }
  TranceiverPresent
0 Y6 T$ \4 p: C- a1 j% l/ p8 O用于设置是否带1.8V收发器。( x9 G( j" Z, `
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    5 y3 r( [3 z. X* s6 N* F+ W& G8 h1 o' i
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)1 b+ X0 e  g. B) q6 q$ G. {6 i
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码

& D" P& p! I, h. m( I; R87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
9 ^0 v% F: h6 l  z下面是SDMMC总线的卡信息结构体:' o) d+ \+ _: e3 f' X: `0 X: G- P4 {
  1. typedef struct
    ' R" z; Y0 L& ~4 @  s; o
  2. {. g; w! X7 h7 P3 \6 w
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    8 C3 _  w5 [! k. t) R" {" d
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
      b" W. Z5 O- ?$ [
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */9 F2 n" c, o7 i# ~
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    . \" q' e+ J* j8 z+ s
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    ! n3 N# r$ h9 ?6 m1 T
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    % p3 Z8 C. }9 z+ o6 A9 P% p. e
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    8 M) P: s, X1 z: m
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */) {2 N" b' S9 W. x9 q: l1 e
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */, _9 _& L) `( v$ O/ X& f1 f
  12. }HAL_SD_CardInfoTypeDef;
复制代码
$ `3 i# P. i: l
下面将结构体成员逐一做个说明:
' E; v, [. ?- G; a9 }" a  W$ @  s1 O  }) k
CardType
, M- l( f2 I5 y卡类型。
* X5 c* a) s% \, P; I
  1. /*!< SD Standard Capacity <2Go                        */- d5 C* U8 p/ b1 L$ M! d
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) : C0 V, y: k& a- c4 i$ i
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */5 A7 Z2 Z  J* E; C* A, E
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  : y& o! O2 v2 d, i
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

) b4 e- O- ]; R  CardVersion
: M5 p- ?6 j) y/ X4 g7 F/ ?卡版本。
% _: {! S- [/ [
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)2 y6 X; {  n/ }
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码
) e+ U2 b" [4 W$ i5 f0 R% C1 F
  Class
* s) [0 r7 M9 K) ]% n卡类型。1 ?/ o7 f/ U: _" a7 q* ~) s/ p8 V

8 T* M4 O+ D  v  RelCardAdd
  C2 k3 @3 r* N6 ~* o卡相对地址。
. g4 X8 P4 O3 L! |& N2 i, d0 D
8 c6 k# Q' w5 D2 ]( n4 Y  BlockNbr
/ }+ X* o- K; O$ V% \  n* t整个卡的块数。
* `$ h8 }1 {8 l) @+ L. ~& o* K. R0 K$ t& i- O3 m" E4 [$ C/ R" u. a/ o" i# A% S/ P
  BlockSize) H1 a, [5 Y' ^. n
每个块的字节数。
4 J. N! B3 h0 W* [& [9 `
3 V* {* Z% H3 c( t! t9 R: Z  LogBlockNbr! _1 Z6 p3 O( {+ \
整个卡的逻辑块数。
2 c& L. |) w$ x$ U& J  f: k$ S  \1 b& ^3 H: H9 V6 n
  LogBlockSize) G3 M6 D2 b5 ], n+ E, [
逻辑块大小
0 |3 I# |& j. M8 D+ z
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)
    " ?9 I4 u8 ?9 O1 f: @2 p4 L
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码

) I0 o; m/ g3 j; |8 B: y CardSpeed
8 ?# J7 r; K- e" o1 t1 p用于设置是否使能SPI总线的TI模式。, k+ [' o! t- D# _, K$ e
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */$ D7 E7 f2 M/ @( N
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  
    * y- h# g$ Z6 A  h0 b% C8 j- ^& `" D

  3. ( u& b: p! C5 C& y* G% v6 y& _
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    $ g  z0 f6 _5 u0 W/ d) K+ M, N
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    3 d3 c( t6 N3 e
  6.   j/ _) Q' d* ^7 m
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards
    , ~' c$ k7 D2 M+ y7 y, x
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    2 q/ X( @: }& F6 W
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码
1 _3 S' d* j" ~9 N
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
! l$ t. n  T- t0 K下面是SDMMC句柄结构体:, Z, W3 d" H5 F& B5 J5 A: x- x

0 z+ t, I8 C$ ^; D
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    2 l! w- L1 w/ v0 @6 N; T
  2. typedef struct __SD_HandleTypeDef
    / F2 R7 b& q# R# h+ T( Q' ]8 w
  3. #else$ D  t% f/ ~& {) c$ d
  4. typedef struct
    6 \5 l6 r1 y" I2 G8 C) N, N
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */; R9 d  J- i6 S3 T0 U: o9 c  d
  6. {6 e, Z/ S! O# N
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */0 S: j$ _) G& w1 f
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    7 S) n7 v, x8 |# h: E$ k! X' E
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */
    " y0 Z* |$ l, n! A$ V
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */$ ~: C9 G& K+ Z& L% M$ g/ Q' z6 l
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */
    5 C" Q% W3 x7 P) K  j8 W; U' b, D
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */6 e. U  o; N# i2 L, y9 l8 M
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */1 \  ^& l: ~% d: C; c
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    % a3 {. W; d6 |9 e% z6 Y
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */( `! `4 l. s* n9 @% |; T: o
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    + p. |/ G* m4 z% Z! C* e6 w
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */6 p- ?/ M9 R# f! `8 p5 P
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */3 [" u* C1 L9 o) e9 E& A, r
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */6 N' D- ^1 g2 s& v4 G% ^  i5 r3 ]: M4 [
  20. ! n$ i# F5 W! Y$ E' F
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)  O0 v8 c7 l3 N* F
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    9 H) e8 ~' J* B
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    / A, Z/ s6 v8 p& f+ O
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);9 i% _2 f( M( m3 n
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);
    , R: ]( U7 d8 _
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    ! _8 J, Z% g# e7 E, J7 r$ X
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    & l1 \. |7 R5 f, E
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);! G, m7 }& P1 c& v* p
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    . U! K' }0 l4 {$ }% |
  30. #if (USE_SD_TRANSCEIVER != 0U): ?+ S" s7 ^$ K( i
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);
    7 S) {7 L+ |8 r
  32. #endif /* USE_SD_TRANSCEIVER */% h' @# Y2 h' `- X
  33.   L$ ~; ]3 F+ x. |
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    ' {. O6 J/ l: h/ j
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    9 F5 L  B0 u: Y" N; w3 W
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
      `+ |" a" ^. U5 z5 ~* f# H0 g
  37. }SD_HandleTypeDef;
复制代码
9 _- a" |2 G& D- ?8 u+ |# g3 q
注意事项:  i: f" t' o: U" O  {, G: \* v

: ], ?# ]: s3 ~% I% V条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
/ |+ q( s" D. N. N8 H9 U; T& e( t2 D: A( H8 {: S8 b5 V! ]
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
8 E, ]4 ?  T( F8 u% s
  [/ d! O) b% }: e. {% ^* \通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。% X7 q$ t# L" Y
7 c# U0 I, u5 ^0 a' t
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。6 b) I' O- i7 m" @
& b; v1 q3 H$ A/ A8 U
  SD_TypeDef   *Instance; ^! v( W! ]5 X. n5 _
这个参数是寄存器的例化,方便操作寄存器。! u4 J9 m/ Z) C4 Z$ X
8 B, A" V% F% k1 I7 u
  SD_InitTypeDef  Init" K' [) Y# ~5 s/ ^: m2 O) Z4 x
这个参数在本章节3.2小节已经进行了详细说明。
1 I5 I- J$ u7 j: m" j9 G8 V% Z" O  ]& E1 F  h# j
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c
2 d' h2 n% G% M) |- b# s此文件涉及到的函数较多,这里把几个常用的函数做个说明:
& W! V" I2 g( I  r
) w' @) \/ F4 a( s$ H  HAL_SD_Init% _. e! r; m3 c1 \- `- Z
  HAL_SD_DeInit- e2 D7 S  o- @& e; J; Z
  HAL_SD_ReadBlocks6 d) B% ?" V% e- o
  HAL_SD_WriteBlocks9 m) |+ {! r- u: p
  HAL_SD_ReadBlocks_DMA
0 l+ B% G! g( n8 z  HAL_SD_WriteBlocks_DMA
: Q' y1 x5 e! f, Q7 _6 ~. z1 y  HAL_SD_Erase& b0 ]' F# @, [) u
87.4.1 函数HAL_SD_Init
( {+ G1 k6 G& e$ \: [! e函数原型:
! Z" h& E" C% w8 f( [4 m; q
+ R+ m" g2 x8 [+ k3 O7 f
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd); t4 T0 ]4 B  }8 g% O
  2. {
    5 N/ ]' ?" p4 j) J# {
  3.   HAL_SD_CardStatusTypeDef CardStatus;8 `  R1 @, Z  ?+ }
  4.   uint32_t speedgrade, unitsize;' K7 ]0 {5 ^0 P+ M9 z, o0 G
  5.   uint32_t tickstart;
      _" N  ~2 i' M( a0 i
  6. 4 Q! T$ e6 b3 O& A9 ^& s' T! Q
  7.   /* 检查句柄是否有效 */% ], u6 h1 H  e" g( G
  8.   if(hsd == NULL)
    3 q8 Y+ T' D) m  x: }9 |9 ]
  9.   {
    0 G. L! V% E* z0 Q* V6 ]
  10.     return HAL_ERROR;
    / e- d7 y2 E2 A% o9 H2 Y; T
  11.   }
    & X+ D, g$ c. G' X

  12. * R/ f/ v1 t+ R4 A7 G
  13.   /* 检查参数 */: }* {: j1 e) }( ~
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));' I* ~& I7 `/ t
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));) e% N& q# v; s/ a6 ^: T  j
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));4 d! Z5 @# M# {( X; f
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));% E) M( `0 H1 L" ?/ i; y  [
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
    % \3 C& m% Q4 ^
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));7 V1 a9 S; R2 i

  20. - V& W4 E& `* w8 c6 Q
  21.   if(hsd->State == HAL_SD_STATE_RESET)  T' p! R( ?% K, W) ~
  22.   {8 b% n' a; x$ K, m0 h% Y9 H1 v
  23.     /* 开锁 */
    ' V& y0 e' n/ a6 Z: g& F
  24.     hsd->Lock = HAL_UNLOCKED;, }  ^& J# v  c( L* d" B; l  q

  25. % Q, V, o# |, J5 e$ C
  26. #if (USE_SD_TRANSCEIVER != 0U)
    6 z0 i8 y8 b  k% d% A
  27.     /* 兼容 */
    ; }/ w2 T6 _3 X& {
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN). G! N3 I8 U- D( T4 T
  29.     {
    7 C5 `- g$ y, g
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
    ; ]2 u; C8 K% A' H5 C- R' |
  31.     }
    - q( ^, H4 }+ I/ M6 N; ~% s
  32. #endif
    6 e3 _( e, J! \, m& V2 \
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)) j: j, o7 h# O1 U7 e/ \3 x7 O% F, S
  34.     /* 复位回调 */
    + J4 W- I0 z4 m( @9 t# R/ r% ?
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    ( K6 y5 d$ @$ I6 w5 a$ [& H
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;% @& v& ]4 ^" E( \
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;: }# S' m: [  f. Q) s
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    & J7 g2 O4 l- I2 e; ^- u4 `
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    , W3 f- R! b4 \! D4 M
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;# s$ p. }5 g2 h) m
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    # y% d4 y( A- \& ^  q, J/ o
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    ( H' s0 m4 T( e" ^7 h0 z& m
  43. #if (USE_SD_TRANSCEIVER != 0U)
    1 l  g6 ?; j  A$ c
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)5 y, d7 u  F: t; b& [$ v: x
  45.     {
    + q% f- f$ _- F; l8 ?; Z0 f
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    / h; L6 G! a* E( h' X5 N
  47.     }
    ( ]: V- e, z; K* H0 L$ t* p
  48. #endif
    " [8 H) s, m& q5 _1 a+ w/ P; t( U
  49. 2 a1 G, Q, t9 h: z
  50.     if(hsd->MspInitCallback == NULL)
    5 U) o7 A. c- M" T
  51.     {
    ' X; }; R1 N; e' h* o5 F% g
  52.       hsd->MspInitCallback = HAL_SD_MspInit;
    ) o; N. J, E' {  P6 h5 N
  53.     }+ V2 s/ P4 G$ b) S
  54. - Y2 |4 J4 b2 U
  55.     /* 初始化底层 */
    ) Z6 f. a- j5 i, B2 ]% e
  56.     hsd->MspInitCallback(hsd);
    + R# ?1 h# e- H* K% @$ r* h
  57. #else
    4 K) K! W; A( c" j7 W
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */. Y' a; z% N+ N; S
  59.     HAL_SD_MspInit(hsd);7 u, ?7 g( R8 {, J8 d
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    , ?/ |2 ^& I/ ?  R; p# D
  61.   }
    9 `! y0 V' r9 r9 F
  62. : C# \" d0 O- j7 S& }4 R
  63.   hsd->State = HAL_SD_STATE_BUSY;" x* w6 y  i8 t& @( \" {  h# h! a

  64. ) a/ g# l! g) l
  65.   /* 初始化卡参数 */5 w( j1 O7 Z1 I! f
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    , m* d8 N1 [' y2 m! a
  67.   {4 u2 F- N4 H+ a/ V/ s
  68.     return HAL_ERROR;1 O' W" h( v* z
  69.   }; Z. p$ N# V# l, Z; J. l! s! \

  70. 7 i- v0 O2 A4 V4 H$ Q/ ?
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)& T5 [4 G- b6 s6 N* J: c
  72.   {( x8 r0 l: h8 U/ w
  73.     return HAL_ERROR;1 Z; h! V' t2 [- I. R  R2 F( v9 U5 R
  74.   }
    - H, m, M. a% k# N% B' U
  75.   /* 获取卡速度等信息 */2 Q  ]2 A3 |/ b$ z( H) d8 m
  76.   speedgrade = CardStatus.UhsSpeedGrade;9 `3 l! b9 y! {/ I+ n1 s0 e
  77.   unitsize = CardStatus.UhsAllocationUnitSize;
    " R0 T! L8 J" A) J7 N/ X- ]
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))" ?' ^3 W! D% A- D
  79.   {* _/ n8 a+ Z# r
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    + Q  ^2 i% T3 A! `4 Y- f2 D8 N5 L
  81.   }
      ~5 u0 O2 p" P; \( b: e" \
  82.   else; D+ t3 w* A8 {7 K1 A
  83.   {
    & ~+ y: J# y2 g) ~9 z
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
    4 B& x8 Y  I+ Y! d; j! Z6 o$ }, m
  85.     {7 o! g# k% d3 q' ~' _
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;: S5 [% d! y% O& \3 F
  87.     }
    / j# o( J. C3 c$ g# n
  88.     else
    " e6 w6 Q( D6 Y, y2 d4 P9 V; X
  89.     {
    1 l) T7 d0 F( ]( S; D( c
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;# ^! B6 k2 f$ g9 Z4 ^
  91.     }
      s! r: t) m+ S: M, B
  92. 7 x! d& V! a: I  F7 H2 U# ]
  93.   }( J0 o, h3 a5 s, e
  94.   /* 配置总线位宽 */
    8 p# E- c# m" ~& n
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
      n0 u& k9 f& `2 }" W
  96.   {
    # t) J/ ~6 j( z' \3 ~
  97.     return HAL_ERROR;' q8 g) u1 {+ |( Z, i6 [9 W
  98.   }* s. E' S* v: Y( u9 D2 d

  99. : \% w" N$ O3 @5 d. }9 C: F
  100.   /* 验证卡初始化后是否就绪 */- p6 E# R! Y! b/ ~* E. T: h. y
  101.   tickstart = HAL_GetTick();; ]4 H  g2 v# W$ w+ {" R: P
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))" V& G, B0 S8 z8 S, p; k* ~
  103.   {' N' R' Z$ q8 \: E7 K* A
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    ( z) s" W0 p  p& ^- a
  105.     {
    : e5 Y+ n' l* _' X+ M
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;! i4 E/ k  V4 a# F" W
  107.       hsd->State= HAL_SD_STATE_READY;5 u6 P- X. N% a8 y: v3 S" s) n
  108.       return HAL_TIMEOUT;
    ( ~( g- e7 W/ C
  109.     }
    . O* x3 K1 d! c3 D1 j
  110.   }/ ]% g5 c, x: ?+ _( m, _' _
  111. * v8 n/ ~9 t$ K9 V- F  r9 W  v4 r
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;7 e+ K) e# T; ~) e- d5 a- |1 x* \

  113. " Q; B) I! I# ]# C  @
  114.   hsd->Context = SD_CONTEXT_NONE;* O& k: \! Y+ {# l% Q: C8 h+ S7 P

  115. & A# [/ `2 M3 T% L  l. ]2 T
  116.   hsd->State = HAL_SD_STATE_READY;$ t2 n2 ^6 {# L7 g, R8 s- d& g% v

  117. ! f8 ]) ?4 W" D$ f# A. h! h
  118.   return HAL_OK;
    * ~: A5 e# ?8 p1 g3 d3 \% P, h
  119. }
复制代码
0 h8 C( E1 D/ A- y# v
函数描述:( k: L: u! i& R. x* D( g' z
$ e9 c4 E# d! @: d
此函数用于初始化SD卡。7 ~4 \% M, @9 e' T9 v( C
% h& k' L0 \1 t; w. p
函数参数:! [4 L* x8 p0 Q

& Q' w# z' R, I  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
) E, \5 [& i: l0 \4 s  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。9 k7 `; u  S# L5 F+ B9 m
注意事项:1 k; ~# s: _2 z0 T1 n/ E
$ J4 ?* J" A4 u+ ^8 q: M
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。+ M/ W5 G' ^$ `! @
如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。  S* O' a+ `. W
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
, @/ J4 E+ _1 e
0 f8 u7 N) i" N; w3 l解决办法有三
9 u1 g- v0 B3 _8 a! y6 M  |% ]9 |' p' ~9 t
方法1:用户自己初始化SD和涉及到的GPIO等。- a2 I; `" F: v5 f& {8 O* z

" s! V+ ~' ^) F$ I$ i方法2:定义SD_HandleTypeDef SdHandle为全局变量。
) p0 P: u" }+ W! C% H8 t+ V
. H- I3 B) M( m" \8 k方法3:下面的方法
8 H& Y4 f5 j+ L$ m
7 V1 Y& i# c! J) J( Q
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)) j1 `, h  [$ R% f, |
  2. {0 I4 ~+ q" D/ l. }" L3 r
  3.     Error_Handler();/ e% U4 K: L6 Q8 E3 x
  4. }  
    % {' B# w9 `- C
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    0 G7 L$ ?- ~& a2 C, F/ G
  6. {! q9 y$ C8 u4 I0 Q9 h9 ?
  7.     Error_Handler();
    . `. }1 b- Y7 }8 V  s& g; x
  8. }
复制代码
+ _% B5 n  L3 J
使用举例:' r$ E% D! U. Q/ l$ A8 n6 o+ A
% n) J# B8 y, W6 J& N( q
  1. SD_HandleTypeDef uSdHandle;
    1 ^$ j: K1 C- E' O" g1 i

  2. ) A" `4 o, i1 @1 U
  3. uSdHandle.Instance = SDMMC1;
    5 _+ x6 m% `- D

  4. % P" @  C# q8 Z& X. W
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    & P8 R) \1 `1 b! c9 m9 [# I, g
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].- ], U' T* {9 V! M4 F
  7.      200MHz / (2*2) = 50MHz
      w3 ~- P4 P& [! Z* B
  8. */
    # f: {' Z- \& Q. j
  9. uSdHandle.Init.ClockDiv            = 2;
    9 b% ~' \) D6 d/ w8 T8 s/ t0 [9 K
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    9 Y$ b2 m; P2 {1 Q  q
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;& o+ u3 D6 x* o; g
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;9 F9 _; ?" q! c& S
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;! l6 V+ }: l9 Q. a
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    6 l( \5 Q4 ]% t: W  e% ^' h
  15. {
    3 [, i$ E# X% V& _2 J3 n
  16.    sd_state = MSD_ERROR;
    ) |7 M0 i" o& s5 n
  17. }
复制代码
5 j$ E7 [( c3 q" B8 O9 o+ d
87.4.2 函数HAL_SD_DeInit
+ G4 Z4 U3 q2 e7 s  e& j) S函数原型:4 W+ z2 N1 y7 K( K, N4 |

% G4 m1 @: S; v; w6 h) Z
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    8 R6 i' d* s  @5 q9 ?* {% D- y
  2. {
    5 r+ v6 {! ?$ \5 k- ~  U+ o( l
  3.   /* 检查SD卡句柄是否有效 */( N  A7 C& J5 t8 b( p$ f3 C+ v
  4.   if(hsd == NULL)- U( A6 J8 [# R% K) Z0 V0 I' J
  5.   {8 L2 D4 {* b( y3 g/ [5 d7 R0 @7 e
  6.     return HAL_ERROR;
      N% b( h4 X' [1 K" }- _6 J
  7.   }
    ( x8 s) x! s9 {, j* P
  8. 4 K+ V) H) U7 q9 z) k* q
  9.   /* 检查参数 */; m9 j, V. _" l2 R
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));- W; Z2 W5 X, i0 _; u
  11. # ^4 A8 m# M5 z, F4 x* ^
  12.   hsd->State = HAL_SD_STATE_BUSY;; a7 {! w2 i" }1 ~( q' C* l

  13. 8 ~  V) d" s: `" U' k9 E' W7 V
  14. #if (USE_SD_TRANSCEIVER != 0U)- m2 Q) i" O8 X8 g
  15.   /* 关闭1.8V模式 */
    ( N% j+ P& }; o: s1 Z: m# r9 L5 H( r
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
      h5 ]" H5 K1 R. f1 j2 F* z9 b. K! V
  17.   {
    . Y9 t" N6 j2 D) Y+ g6 j: B" n
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    ' \1 z# |3 Q. {3 Q
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)9 V. ?) U0 J7 ~9 ?8 c: ^  c
  20.     {
    4 E( w0 L% V8 |, d/ z" r: K; F# J* f
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;% y1 ^* h, a9 D% S; ]) n
  22.     }
    9 B% a: C/ ^% Q
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);- v) k, g5 O: ~- n% p' m5 k6 |; e
  24. #else
    4 ]9 O: E6 a4 d4 ^- @
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
    7 _1 Y  j3 c2 a9 j
  26. #endif + o/ n" A3 g7 S8 Z7 I2 d% x% ^
  27.   }                                                                        
    % Y% x7 q; }  @6 f
  28. #endif! I  ]# w- L' f

  29. 3 H; w& c% w, H+ p% V( i8 i6 A
  30.   /* 关闭SD卡电源 */2 `( \5 M) Q6 {2 c7 O8 M* N
  31.   SD_PowerOFF(hsd);3 l( ^$ s0 y  A/ S' A% i

  32. % I5 ?& n% v/ P% `2 t7 u
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U); W5 z, }' r6 Y) |% b1 x4 ^
  34.   if(hsd->MspDeInitCallback == NULL)
    0 o4 ~* _1 P( W) y1 w" O' o$ Q
  35.   {
    7 m$ n; W. o  n! @. U
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;
    6 p% \* s* W/ o% _
  37.   }/ C9 r4 e+ b6 Z

  38. 9 M9 U, p) M, }. i  f4 M
  39.   /* 复位底层硬件 */
    $ z& \& f- Q' A5 E1 r3 ~4 k
  40.   hsd->MspDeInitCallback(hsd);
    ' _. [0 X, x& y' L
  41. #else
    ) N, v: t  c8 W2 U
  42.   /* 复位底层硬件 */
    ) s/ j; ]' y% _. r0 N0 D0 ?
  43.   HAL_SD_MspDeInit(hsd);
    . Y+ l8 y% v( m$ h. n
  44. #endif
    " |, h! |/ o# O3 G1 d

  45. + j2 N- A3 j1 G6 c9 R$ _8 a$ k
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;& G! `) u+ q$ ]; P: @; K2 `8 f, p+ B
  47.   hsd->State = HAL_SD_STATE_RESET;) y6 m6 j) r" L' M8 i, E

  48. " P% q4 w+ Z& u, y' r& Y/ A: x: l' z
  49.   return HAL_OK;4 z3 q% N& Y9 Y3 n5 O/ |
  50. }
复制代码

! y$ Y' r$ R% |' |函数描述:
' J5 K1 f/ y% E! f# U9 @" `
6 L$ @- U% ?$ \+ \3 k用于复位SD总线初始化。) k' U6 `5 Q1 G9 v" b

( f# ^6 Y/ [: y9 ~; r  I+ V8 s函数参数:6 T" e2 Z$ {" D% G
7 L% V! N5 }3 s5 C! ~! y0 a
第1个参数是SD_HandleTypeDef类型结构体指针变量。
, B% F  h, A2 m2 ~# l6 L 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。& b3 w. d0 l- H+ L8 Y- X: n
87.4.3 函数HAL_SD_ReadBlocks4 P! [( R0 [! L2 Q
函数原型:
, A: u! z: _# z4 K4 y
5 X( G. N2 `9 O, T, e0 P: L
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)% y6 I8 u8 B0 `* T0 U
  2. {% W3 T6 Y: k) d. @( P
  3.   SDMMC_DataInitTypeDef config;
    8 b$ |+ @. Z/ \3 A4 U$ f& A  N
  4.   uint32_t errorstate;" W( u1 J$ h) f
  5.   uint32_t tickstart = HAL_GetTick();, W8 J. B2 I7 @7 D+ y
  6.   uint32_t count, data, dataremaining;
    * ^; v7 Y/ l3 ^# a
  7.   uint32_t add = BlockAdd;
    : `% P' J; D1 w( }( H2 \+ y" X
  8.   uint8_t *tempbuff = pData;
    ; i4 T6 n3 ?6 d3 P

  9. 4 E3 G: A3 @* l6 _  R
  10.   if(NULL == pData)4 Q% o' n' ?, L( R
  11.   {5 h3 h" D/ n# n$ Q9 q) M
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;0 Z, r2 g& L( ~3 e
  13.     return HAL_ERROR;
    5 h  X2 u* P/ r" E, x7 i" }
  14.   }
    , Z5 O! _8 `# F6 `1 M, y

  15. % W* l: j% n6 q7 F( Q. ?% n  c- v) K
  16.   if(hsd->State == HAL_SD_STATE_READY)
    . k# A" O" S9 D
  17.   {$ n# \7 s3 [. L$ ^' c  o3 c
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    3 i0 E4 H& O: I4 f

  19. 7 [: n3 c: h: f/ w3 p
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))% F6 Q0 g( r6 U, S% Q
  21.     {. F( q/ P$ u& _2 k) H
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    3 n% `) P/ |# p* z0 V4 a
  23.       return HAL_ERROR;
    7 H" |- w9 l0 p6 B3 p
  24.     }8 ?: D7 P. h. i# L

  25. % B8 f4 @3 D, [: M% ~" e
  26.     hsd->State = HAL_SD_STATE_BUSY;3 S$ K# t8 i. b; |) L: O

  27. * j0 |  h2 v$ M$ o1 R# |+ j* s
  28.     /* 初始化数据控制寄存器 */
    & y' b& k/ \. Q8 E
  29.     hsd->Instance->DCTRL = 0U;: n. `0 `4 H- G& O/ ?! I
  30. ! ]6 B; N( k4 C. a* R: F
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)1 T7 ?  M4 a! `, @* A0 O
  32.     {$ V+ z  ], A4 k/ e+ \$ n9 A
  33.       add *= 512U;1 d& _5 Y: K/ ^3 w/ P
  34.     }5 ]2 X) F( P2 L/ K* F

  35. ' W& b% m3 e- ~" F& |0 h$ Y
  36.     /* 配置SD DPSM (Data Path State Machine) */
    . T: Z" P5 g) E. I; R& W# r: D
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;* D$ B1 w3 R. y( R; |- k) V$ o
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    ' C, I  }- E) o3 q7 C( V
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;3 l, U3 o4 l4 A: r$ Y
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;; g+ C  S& L+ ^
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;- O0 r9 `/ i  p$ W( K7 o
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    & X0 p3 s( e' l# ?+ d6 S4 r& r
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    # Q5 J3 w$ ^9 y& R
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);' c0 W7 K0 k/ B5 q* S& r
  45. # n8 {. W+ L6 K# l+ y% |) [% `! H
  46.     /* 查询方式块读取 */
    & O) y1 y4 u) N) l
  47.     if(NumberOfBlocks > 1U)
    ' M7 c5 T1 m; J
  48.     {
    " h1 P! ]. k3 q7 h% c& b
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
    ( i) ?9 @$ H. {/ w

  50. 4 D5 h7 p$ m" H# }! o
  51.       /* 多块读取命令 */  b/ u; j$ F: }
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    - f/ A* z" p+ Y2 D; c8 M/ X
  53.     }
    * t$ g! ~5 s  W
  54.     else
    ; A$ I- `5 u# I9 c' }5 t
  55.     {
    9 }: _6 h1 ]; V% A2 ?
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;# k0 Y% V: V# C4 I( K9 _
  57. # i2 F; k) I. s" W. N* ~5 y7 i
  58.       /* 单块读取命令 */
    1 P- y9 E* y% c: G
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);( d- a6 Z1 K# u+ g/ a6 s# \
  60.     }4 [4 P& G6 g, c  E! X3 j
  61.     if(errorstate != HAL_SD_ERROR_NONE): z) x5 o/ n1 O1 _8 O
  62.     {
    1 X6 D$ Q6 c  g# O- m7 i6 @
  63.       /* 清除所有静态标志 */
    " {# F% }# v. _
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    / E9 C3 W( a, F  {
  65.       hsd->ErrorCode |= errorstate;5 Y% m+ j6 F! Y. o1 k# C6 X
  66.       hsd->State = HAL_SD_STATE_READY;
    0 S0 I3 ^. C# x9 G1 {6 D
  67.       hsd->Context = SD_CONTEXT_NONE;
      ~/ `2 W' n- Y! A' [( |, n
  68.       return HAL_ERROR;
    . e1 P1 Y0 {( J4 r7 {- x: H6 [
  69.     }
    / W& S1 l9 I9 Q$ @" G; P

  70. % o/ n4 c/ D6 J2 ]2 \6 h. ?" p
  71.     /* 查询SDMMC标志 */' ]3 N" |$ D' p- @( }
  72.     dataremaining = config.DataLength;
    " Z1 q  e6 ^3 R4 k  I
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    9 ^0 ]1 B1 ]5 Z6 m
  74.     {
    5 e; @- k6 W+ q* n9 r' u
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U)), ~8 B* c1 @7 R
  76.       {
    3 f! {( X: o* q8 E
  77.         /* 从SDMMC Rx FIFO读取数据 */
    7 P. @, u: d6 x) i& `- G
  78.         for(count = 0U; count < 8U; count++)
    9 ]% k9 q9 Y; V! a! ^" g) l( W
  79.         {. V5 \# w% C+ u' ~3 e( x
  80.           data = SDMMC_ReadFIFO(hsd->Instance);
    ! _& G+ y6 m8 z/ G, J4 W/ M! ~5 ^
  81.           *tempbuff = (uint8_t)(data & 0xFFU);2 \3 C0 W/ y+ R
  82.           tempbuff++;. S, Q) \: v. W2 X
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);) L. g* J" B( g3 n6 M! f# y9 Q2 S4 r
  84.           tempbuff++;
    # L9 h$ n/ \0 c* V8 ]! ]6 U
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    % e  G' C% m" v
  86.           tempbuff++;
    , t6 S) ^. S9 e& E9 b6 I
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
    + o1 `. g/ Q1 X6 m$ y& v/ O$ Y
  88.           tempbuff++;/ j& F" U" y! x6 Q( P
  89.         }: N& {8 u( k4 }4 k( I9 Q
  90.         dataremaining -= 32U;& J5 f3 A/ \! v0 N, u
  91.       }% y; O8 G: P; q) C6 h5 Y' A
  92. 5 }7 e. \- d  J& @' O; N
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))) ]* E9 E- O/ x8 F7 f" k2 y# c
  94.       {: r  Q( M; ?3 ], K
  95.         /* 清除所有静态标志 */
    , ]$ N& H  J1 ]! C* o
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);/ s% `: T. z7 E: T
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    ) i" W7 G2 Y' g
  98.         hsd->State= HAL_SD_STATE_READY;
    1 c' X' o) U5 ?/ y/ d/ y! M9 c1 i
  99.         hsd->Context = SD_CONTEXT_NONE;
    * b- T$ }) ]# r6 m' Q" j
  100.         return HAL_TIMEOUT;
    , q# O* s- V* @
  101.       }$ l- P0 h1 d- q* V' A0 z8 L
  102.     }" l' f/ Y, i: V3 @$ |) f
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);9 X! U1 }7 q! Q6 b8 y
  104. / L0 T! h) |% Z0 z- k- j* r1 V
  105.     /* 多块读取发送停止传输命令 */
    , I7 o6 P0 ]8 x; e
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))% [" S1 K; B% i: O1 E6 i; }5 M4 v
  107.     {" |# J4 O( I; {7 x/ ?
  108.       if(hsd->SdCard.CardType != CARD_SECURED): Y- Q' L1 n( }3 u6 ?* J2 d
  109.       {
    7 W: {. v' A: W% K3 J" i
  110.         /* 发送停止传输命令 */
    . ?1 R2 }5 Y1 M
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    / A/ ~' A4 \1 a+ m' D5 Y0 {# p, r
  112.         if(errorstate != HAL_SD_ERROR_NONE)' N8 w; S0 T* i
  113.         {: c2 `: k2 E" ~) T% L  }
  114.           /* 清除所有静态标志 */
    % D# L8 p1 J( G" O
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: C4 m8 v! P& p# n# q
  116.           hsd->ErrorCode |= errorstate;7 j/ c, `4 S/ ~
  117.           hsd->State = HAL_SD_STATE_READY;( x) V4 V* ~% R0 s. H5 K* B$ g: _
  118.           hsd->Context = SD_CONTEXT_NONE;
    4 D$ g. M: x6 Q; J$ x
  119.           return HAL_ERROR;. g( P* _5 [$ f9 h0 q
  120.         }: s+ h7 j9 a0 P# t& _
  121.       }6 R4 r" Z/ e! z; @- N
  122.     }
    + t: J1 Q$ B1 q! W7 D" R

  123. & e* X- T- J2 s* w5 _1 d
  124.     /* 获取错误状态 */$ r1 a# C  h6 n5 k3 n4 f4 O3 w( l
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    # L% w( q6 i+ |/ L
  126.     {' s% I' c$ [& N8 z3 {& J% K2 n
  127.       /* 清除所有静态标志 */
    9 J5 I! A* j0 o' U! Z
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    8 J9 ?$ w$ B: o( ]. ?  J
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    & c% s% A! j: Q' c; s5 e% u" [
  130.       hsd->State = HAL_SD_STATE_READY;
    6 H/ o, y8 G7 \7 g
  131.       hsd->Context = SD_CONTEXT_NONE;7 c% ?6 _3 v: n; l6 ^
  132.       return HAL_ERROR;! z$ Z; o1 d6 q/ D5 {9 D2 ]9 N
  133.     }2 k  m4 e4 z9 X4 B
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    7 [! F. u* Q) M0 X8 X8 L* F
  135.     {, B7 r9 D0 P2 [. m/ q, E
  136.       /* 清除所有静态标志 */
    ) H  X' Y: o/ z1 v8 a
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    5 ]- c, ]2 s4 S
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    0 D+ r. g: G9 v( h# T
  139.       hsd->State = HAL_SD_STATE_READY;
    7 X4 e' d- s0 J) _( ?
  140.       hsd->Context = SD_CONTEXT_NONE;
    ( A0 ]3 }" w. n
  141.       return HAL_ERROR;
    # g' y/ Q" Q+ R+ Z. |+ V0 U
  142.     }0 N4 c8 t% C( d; e
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR)). W1 g$ D8 }- X& K
  144.     {
    8 s- s7 w4 R: v# a
  145.       /* 清除所有静态标志 */
    7 e$ N# W! t: D) Q7 S- F1 J
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    : ]: D8 c' \* j; D3 u3 C7 a
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;* v5 N9 S" A6 J
  148.       hsd->State = HAL_SD_STATE_READY;
      M% Z% r# c' t: A9 O, }: [/ P$ a
  149.       hsd->Context = SD_CONTEXT_NONE;% B; @2 W" K8 w, n% D) U1 d
  150.       return HAL_ERROR;, W! e" R$ {/ N6 D; e2 \" B/ M. A) P
  151.     }
    ( y& f4 v- m$ y( Q% O, B9 q
  152.     else2 A1 o. J  }0 Z6 {% U
  153.     {9 r, m5 J  T5 f- ?- M
  154.       /* 什么都不做 */
    ; |$ a' t3 [5 Y7 T3 }0 q7 Q
  155.     }% B) \) w" E* \& ]# A0 |& L4 J. a

  156. 0 n' f+ U. C7 k+ L4 q' G" Z1 p
  157.     /* 清除所有静态标志 */) q& e# d+ `* u& T/ s9 E0 n8 I6 h( W
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    - g1 _( t, u2 ?) M( g. O* J2 k

  159. 1 W4 }% e4 A9 I8 b1 ]4 x: l
  160.     hsd->State = HAL_SD_STATE_READY;$ {2 U4 Q# X1 Z7 ~: H: }+ C3 M; s
  161. ! g0 p0 M8 u# j/ ]$ N" y
  162.     return HAL_OK;8 O8 U2 |7 ^4 D. V
  163.   }
    . o3 K- ?# s/ N6 Y. f4 _; }
  164.   else
    ! z* X  N' ~9 g# d; z% A
  165.   {
    & O! }" T5 U- ~$ N
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;, l" w( c) L! k3 }) s
  167.     return HAL_ERROR;
    " S; f; T$ _0 |
  168.   }8 @) q' T: R- C: q3 P7 W; `
  169. }
复制代码

& o( @: s# s$ V* }5 g) T0 A函数描述:
( }# ~+ Y+ U7 \: g) P" w" Y: x3 K0 [  j7 ^
此函数主要用于SD卡数据读取。* y% G- z% o4 u! h1 r9 X2 m

5 H  Q8 _) b5 M  U函数参数:
2 b* _* I8 J0 Q
* \2 ^& }& d. f# p9 t  第1个参数是SD_HandleTypeDef类型结构体指针变量。$ V5 L3 i1 D0 z' |" p4 Z9 P
  第2个参数是接收数据的缓冲地址。" v$ U, m% c, S# L4 g
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。  x# r, @, f4 k+ p! o) i7 E
  第4个参数是读取的扇区数。, R4 d: n* S) T
  第5个参数是传输过程的溢出时间,单位ms。! o! f6 S  X  w% v
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
7 |. a1 G. [- H: X使用举例:
  J' z9 Y( ]- G
( \4 O; `3 |9 ^9 Q. q( m
  1. /**
    2 [% Z) x: W3 N1 h& M
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
    0 m: T& e8 ^4 k( y( `$ k. k
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    9 d6 d) f6 j. f! c# C& e/ f
  4.   * @param  ReadAddr: Address from where data is to be read. E0 Z0 q: ]# L' ^6 d2 ?- C" p% m
  5.   * @param  NumOfBlocks: Number of SD blocks to read/ f3 K5 I: l% y/ e* \
  6.   * @param  Timeout: Timeout for read operation: K* @6 V% B9 X$ C- s0 l$ s) q
  7.   * @retval SD status
    3 `& u% d( O* z% N( [4 D* J  M
  8.   */) W; P3 K5 V' T3 I( K
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    * K! i  `4 H3 f7 D2 E# L/ w
  10. {
    6 S* s+ x; s8 g0 N+ o1 n

  11. , c; @/ U4 F! S+ ^; @  ]
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)2 Y% K; |& L; o
  13.   {2 R  [+ \) N  ~1 _- ]# C
  14.     return MSD_OK;1 C: J4 ?/ b  g3 d' u* \7 r
  15.   }- p" T& X, ~: B! \
  16.   else, \. R/ E7 Q# y5 q
  17.   {
    2 l7 m. O' D- v! b/ O8 Q
  18.     return MSD_ERROR;
    * g% l! @. W- N6 P
  19.   }  a$ S7 k: j( o: {: I% x* v/ P5 e
  20. 2 u& c  z; u2 I1 g4 Q) k+ ]8 j" s5 W% e
  21. }
复制代码
( P4 o* F9 [: e' X6 K6 M! M
87.4.4 函数HAL_SD_WriteBlocks8 \: h# B, s2 \4 }
函数原型:
# h! y% s% \. ~! N8 X  S' ]% u: J/ f8 k
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    3 o: }$ F5 |- L- R% D
  2. {3 u; ]3 V) G3 v- x) |5 M5 B/ q
  3.   SDMMC_DataInitTypeDef config;3 I6 H5 I4 z6 K6 _6 k
  4.   uint32_t errorstate;
    ) z0 f6 m  s% N+ n
  5.   uint32_t tickstart = HAL_GetTick();( Y/ k% u2 [) [8 h) U! M
  6.   uint32_t count, data, dataremaining;6 G2 `8 q3 A/ Z# ~/ M
  7.   uint32_t add = BlockAdd;
    9 I) j# z1 |& D- E) i
  8.   uint8_t *tempbuff = pData;+ ]. R. m+ M( O

  9. 7 c, x  ?+ X, T# h1 q( j2 E
  10.   if(NULL == pData)
    . [# q% `) |0 ~  B" a
  11.   {2 r+ [( ]# F$ k4 H. V
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    , H- e& b# f  n! r8 {3 D' B& |
  13.     return HAL_ERROR;
    * e% j( R( E1 r. q
  14.   }0 B$ K9 Z& k( W! b% l. f  v
  15. 6 \" q7 F/ k1 ?* b
  16.   if(hsd->State == HAL_SD_STATE_READY)2 G8 Z  b0 {( W
  17.   {
    4 s- m* P% F% W+ U& ^$ Y& V+ [, Z
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ! Y; }1 u# l' I( V5 A0 E0 E
  19. & o" P7 O5 W3 e& M
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))1 w. X6 U* E* `, X
  21.     {3 a7 S* B* |! E: s7 f
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;; z+ W. v" c3 J  |" q5 Z
  23.       return HAL_ERROR;
    " A% n9 b' u2 Q1 Z" t
  24.     }
    . Y2 ], C: e, R4 w6 F. t1 z
  25. ; I7 X* b/ }0 O1 Z0 X9 i8 _
  26.     hsd->State = HAL_SD_STATE_BUSY;
    $ k" Y1 L( N0 b) N

  27. $ E5 C) Z0 `7 }' f
  28.     /* 初始化数据控制寄存器 */; p9 g0 l/ D' Z2 h2 o: Q& [+ |
  29.     hsd->Instance->DCTRL = 0U;% Y) Z) G* q! f7 r# _
  30. 8 P7 i8 }9 M" \6 U! v
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    * O+ N7 [  T" m
  32.     {% R+ M# s3 A( \! n- z: d& C7 x
  33.       add *= 512U;
      K/ {: K% v' a; Y8 z! r
  34.     }: t7 a6 V* V/ i" ^8 c. C) d. F

  35. + P$ e9 e( N5 h0 D  z, x0 N8 F/ @6 o9 _
  36.     /* 配置SD DPSM */$ H+ b+ F+ I& a" s
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;( y0 D* H5 s: o& S( @! R
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;: D8 i# L8 Z- v( W2 g* Q
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;; H" f9 S$ W, d
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;* }$ G  D2 D: w# p; b
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;$ o/ f$ @/ O- T
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;; Z: h6 U9 O7 ~) Y
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);; F& X5 z0 C4 _. _+ D
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);/ c2 ^2 K' {! B' @
  45. * h, N' `6 v- Q3 {
  46.     /* 查询方式块写操作 */4 z: y( F) |# y5 v+ U
  47.     if(NumberOfBlocks > 1U)0 V1 Z7 v; I& s- m& Y5 N. M) I
  48.     {4 v8 f$ K2 X* r& ~9 X9 [
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;/ ], B% d. ~* N; }$ f, p& o- G% R6 |
  50. 2 h3 B: U+ _1 v, b
  51.       /* 写多块命令 */' j0 s& O1 I9 `( d# }  V- b3 R
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);5 L0 \) E$ y9 s0 U1 |( J
  53.     }
    - [1 j2 g. T$ _1 O2 j3 \( d
  54.     else7 E% `/ N8 z: b1 s* M
  55.     {
    0 j. U3 N7 V! l6 I4 V5 H
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    . [0 C6 @8 i+ D* w& p

  57. $ d% U) d5 ?# m7 B- y1 k( a
  58.       /* 写单块命令 */, h  J( O, `" c: \' |4 Z3 L7 H% S
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    " N- p2 l6 S! l' g; E+ |5 W
  60.     }3 \* |+ m# X4 p- r" W
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    + }( e# z% f. N9 x6 `
  62.     {
    & G; l) P) ~+ o
  63.       /* 清除所有静态命令 */
    ! x0 h5 R/ e  M* k! ]7 V' g
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    5 Q- F: E* U) H' z0 x$ G+ B7 g
  65.       hsd->ErrorCode |= errorstate;
    & Z# e. p7 G4 M3 }1 Q$ l
  66.       hsd->State = HAL_SD_STATE_READY;
    - i( ~& E$ K8 ]0 L0 a3 h' ~. @
  67.       hsd->Context = SD_CONTEXT_NONE;
    " _9 `. I& _0 Y' K: i7 T
  68.       return HAL_ERROR;
    2 N% @3 Q4 r0 \5 ?2 ^! D
  69.     }) V% b: j! C$ l5 A3 w0 [& Z+ S
  70. + ~5 p3 M+ \; s9 |/ ?1 b6 }5 R
  71.     /* 查询方式块写操作 */+ D0 ?$ ~' h) B9 ]6 u
  72.     dataremaining = config.DataLength;
    4 ^+ g- ~+ b3 |0 M1 \0 N* O7 p( x
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    5 E1 ~4 H& v" o. {# ?' S3 f% y) W4 M6 a
  74.     {- [% X( ~: O! @2 D: p9 f
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    6 b7 }. J, ^$ B5 l+ g6 q& F
  76.       {5 ~5 N! A" Z- C; Y4 ?0 u/ [3 \
  77.         /* 写数据到SDMMC Tx FIFO */: d/ C0 s- S( w4 T
  78.         for(count = 0U; count < 8U; count++)
    . Y  `* Y! J: D3 S: q9 G8 R
  79.         {) j" l4 c) A* v1 a
  80.           data = (uint32_t)(*tempbuff);
    + m4 ?( y' O8 T
  81.           tempbuff++;0 n0 j; c1 R8 M/ p- S/ L
  82.           data |= ((uint32_t)(*tempbuff) << 8U);, ]2 [. O/ [2 |/ E* a
  83.           tempbuff++;, B2 e5 N+ E" g/ y/ |
  84.           data |= ((uint32_t)(*tempbuff) << 16U);
    : J! H2 Y' U9 t& M( m
  85.           tempbuff++;/ g1 z) f& ]( x3 \6 a9 o
  86.           data |= ((uint32_t)(*tempbuff) << 24U);8 z- t6 a% E8 z0 N+ @, H
  87.           tempbuff++;
    : G/ H* b7 W  B4 i
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);) m( y9 _8 V# C. @! P( C
  89.         }! U. q/ f  v' A8 j" r$ |8 T
  90.         dataremaining -= 32U;( r  [7 _3 }! H& {
  91.       }
    3 l* r) K, a6 P# n
  92. 9 h- m/ M7 D* Z1 t, J4 O
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U)): t7 R" ^3 z" J
  94.       {# f# X& B6 ~; R* H& Q7 e
  95.         /* 清除所有静态标志 */
    ( ~3 @( `9 z! ~2 j
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; `% i' O$ q1 W# Z7 A/ K5 `3 [: x$ q
  97.         hsd->ErrorCode |= errorstate;8 {! Z  b- U9 f4 i; a
  98.         hsd->State = HAL_SD_STATE_READY;  H3 B$ L3 g, r; I
  99.         hsd->Context = SD_CONTEXT_NONE;- S6 s+ P+ z1 j/ E
  100.         return HAL_TIMEOUT;( R, Z! m& f/ d; X
  101.       }
    2 }: q. B- y& N) t+ }
  102.     }
    : b' P0 F1 ?' }: H% a
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);1 |1 z; n5 q3 R  R( S" P# f

  104. - U: D5 [* B5 [; ?
  105.     /* 多块写操作,发送停止传输命令 */
    8 m8 ^6 ~* W: h0 B. [1 ~+ a
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))7 O9 [/ e4 n! d3 W; k
  107.     {. `! v: s( R8 o2 i
  108.       if(hsd->SdCard.CardType != CARD_SECURED): F( [' p; x7 i+ @8 |4 t
  109.       {
    4 ~& _" h7 S+ Y
  110.         /* 发送停止传输命令 */- x, x9 J3 J2 i
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    2 d6 a* m) y  G. Q- J
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    : V0 _2 [3 j! v( H) o
  113.         {
    8 o  ~5 P( w* G: z/ j
  114.           /* 清除所有静态传输标志 */
    5 N4 z! Q/ ^$ k8 _! r- [: Q
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);9 a0 m. @, B6 N  R! x' I
  116.           hsd->ErrorCode |= errorstate;
    ( S6 p% Z* l# J, A3 c: I
  117.           hsd->State = HAL_SD_STATE_READY;
    ; Z7 a: p2 K+ e4 M1 X# |( i# r
  118.           hsd->Context = SD_CONTEXT_NONE;& b/ W* s4 m# w
  119.           return HAL_ERROR;2 U" n+ D  M0 }: ~
  120.         }4 @* h8 e# y$ Q
  121.       }% p- V  z& k" D9 w' T8 S
  122.     }
    3 ?7 v/ s0 @% y) |

  123. & O( M3 O  k- ~% {+ T  O# c6 q
  124.     /* Get error state */
    1 C6 b4 V2 y( ^% b" ?
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))6 P+ y8 D# `- F/ J5 K
  126.     {- y  [' ^$ u! }- n9 }5 t8 V3 F- Y
  127.       /* 清除所有静态传输标志 */
      S# Z: y( R2 ^$ ~) u
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);( v5 O! l4 q! ]. ~/ y  U; T
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    - _5 E. M* t  e# R+ }, `
  130.       hsd->State = HAL_SD_STATE_READY;
    5 j  {4 d9 H; t4 ~1 N  U$ K0 X1 ~
  131.       hsd->Context = SD_CONTEXT_NONE;- q3 v- R. T5 }4 r3 ]1 g5 x6 b
  132.       return HAL_ERROR;6 g7 \2 R+ V0 G2 \0 O
  133.     }
    " M5 s& i7 h. c. j  J' X& U
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))0 P' n  x' K$ j0 x$ h+ {
  135.     {& ?8 f# f- n: K, ~! G
  136.       /* 清除所有静态传输标志 */
    . Y7 P2 M5 |1 U
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    $ Q* `4 Z. h' S+ V5 ~! ~
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    0 M* f6 J, U% L. u6 C' n
  139.       hsd->State = HAL_SD_STATE_READY;
    $ |0 h7 O) a1 }, x" W6 |( V% C
  140.       hsd->Context = SD_CONTEXT_NONE;
    ; E3 L6 U* x' w" F$ Y9 d
  141.       return HAL_ERROR;  X  E7 T( W% k+ S
  142.     }
    ; C. f! a' l  p1 I, v
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
    ' Q0 P" B. Q2 ^5 r! C! I
  144.     {
    ! w# L( @+ l% T5 O9 Y
  145.       /* 清除所有静态传输标志 */
    . d) M# T& K8 _  m" d1 t% m
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; _: F2 R$ |; A7 Q
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
    . B# R6 |4 K9 G- W3 |3 d
  148.       hsd->State = HAL_SD_STATE_READY;. Q  N8 v$ A9 u! d' n  m
  149.       hsd->Context = SD_CONTEXT_NONE;
    ! Q/ c. v% \0 k
  150.       return HAL_ERROR;4 E" O& g+ J( _. a/ K& {- x$ H
  151.     }
    3 f3 }' S. X( o$ @% _& q
  152.     else/ n! \' e) j8 W$ }) \3 g+ {
  153.     {
    4 D8 T7 {; m/ v& H2 Z- z: I  L4 k3 ]
  154.       /* 什么都不做 */
    ' K0 F- p4 ?: K
  155.     }+ N0 q$ Y6 A& ]' `9 a* ^
  156. ) g7 L% [) X7 d+ p7 B8 g
  157.       /* 清除所有静态传输标志 */! |% s7 z" P; A' a
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
    1 f0 k4 B$ i- U* S

  159. : H( ~, R$ J: v' _' n' V
  160.     hsd->State = HAL_SD_STATE_READY;
    : J$ y( Q8 \7 e- X! I( d' ]
  161. 4 T% d/ Z, P8 t( q5 t
  162.     return HAL_OK;1 M- X8 ?4 o- K" P4 q$ v2 O
  163.   }
    7 t1 j1 Y1 Q9 J6 F- R5 w
  164.   else
    ; O$ K$ Z- ^: H
  165.   {
    3 Q  N$ q! _# D/ C& |. \( j
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    9 N4 Q" Z" _; S% _9 x6 v7 o! t
  167.     return HAL_ERROR;" G8 \- b9 Q/ Q$ N* f
  168.   }0 d1 l% E  c! R
  169. }
复制代码
6 r8 r; u2 `2 Z- h2 B* q$ o
函数描述:) T, R  h4 m6 b0 G, e$ n- R+ u( p: m

( }8 I8 L, |% `( V; r( ^& T9 k4 F此函数主要用于向SD卡写入数据。' Q3 I$ j; x+ y

7 A* L+ _& J" |  k" c函数参数:
2 x; H( H/ _  S( G# \% Q9 r! U1 e3 ?* T' d; k) ?8 l/ o
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
" {7 R( i2 f3 k8 k' |% w) U  第2个参数是要写入到SD卡的数据缓冲地址。
# v& p! k: K+ b  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。6 M: h% Z: o3 Z' c7 X
  第4个参数是读取的扇区数。
/ {- Q8 w" ]2 u/ U* Q- ]$ Y& t. l  第5个参数是传输过程的溢出时间,单位ms。
3 Q( ], u: Z, \' O! d6 u+ ^, c  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。% a1 S; M4 b& D/ F
使用举例:
8 U( T/ f' x* i4 ^2 f
% t/ l& n* O: @% _
  1. /**
    ) U! \( a, t+ [9 J/ a4 z7 u
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.
    " c1 L: ]: V7 S4 x: b0 w5 v( M
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit' F# [* z. F, D% h
  4.   * @param  WriteAddr: Address from where data is to be written
    6 L9 I- c0 A  f3 y/ _, L
  5.   * @param  NumOfBlocks: Number of SD blocks to write. ~* O+ u3 k, E3 d/ c
  6.   * @param  Timeout: Timeout for write operation3 S% V, v& w3 V5 U
  7.   * @retval SD status. r$ L% d# V* p, j
  8.   */  P) [+ D8 c8 I7 f3 c1 r
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    % ~  y3 m1 \4 t+ U& ]; R
  10. {
    " t' ^; F8 w( ~
  11. 7 ^. q% B; S8 X6 s# ^+ R
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
    , _' Q  x4 }/ _7 d% L$ U* p7 D
  13.   {3 I  y. O. \$ f) Y. O' p/ F
  14.     return MSD_OK;+ Z- ?; j0 _# T0 F$ e. n1 }4 o
  15.   }
    ; C! l( y9 T# {: N  t6 L( B
  16.   else
    6 l8 L4 k) \" P4 U/ p  M! m
  17.   {! E. q) d6 P8 M2 @  @$ [
  18.     return MSD_ERROR;( f. {+ F; y! g3 [% a1 G( @
  19.   }& Y) d+ y2 ]9 T" I* y  W: S; }' u+ o
  20. }
复制代码

4 T8 l1 T: o1 `' r9 h0 z: U1 X$ z87.4.5 函数HAL_SD_ReadBlocks_DMA
) U0 Y, U& v) G; u- ~函数原型:
8 \; J) ?" J3 i6 Z
/ G9 P6 h$ E2 Y$ |8 a; }( d) O1 @' {
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    7 L: ?. B: p/ h) [
  2. {0 P3 A) ^3 V, Z8 p
  3.   SDMMC_DataInitTypeDef config;3 b% r: g2 `3 r! Z
  4.   uint32_t errorstate;0 y  B, K! e, Y0 k; C
  5.   uint32_t add = BlockAdd;. A* p0 K* z& Y5 E: B8 R
  6. ) n' H( o/ y2 ~9 k8 W4 m
  7.   if(NULL == pData)
    , }1 R. Y' B$ g7 {
  8.   {
      c9 [0 C8 Q" @  L. q2 u1 m
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    # b/ D! s1 |4 g: u
  10.     return HAL_ERROR;
    ) m1 B- v& Y/ X, E# @
  11.   }
    % M. _4 @- _" l0 b

  12. % Z3 u" G, Y8 T5 ]. n7 q
  13.   if(hsd->State == HAL_SD_STATE_READY)
    # W- \) H' T/ P% \, Y
  14.   {$ b( k3 u4 a  y
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    ! ]% ]4 h* F2 g5 }6 _3 K

  16. + B7 i+ j" [3 C# n" x% o2 {' m
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    - A- ]6 D7 d: ]3 X" `
  18.     {
    ( P, @9 U/ P6 \, n
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    2 P7 x' @/ @8 P
  20.       return HAL_ERROR;  J- b8 N0 {* J/ d5 O1 K) L
  21.     }
    # X5 r. ~, ?5 I, `- M& u
  22. 0 G. e# B! ]/ K, a. O; _' J
  23.     hsd->State = HAL_SD_STATE_BUSY;
    " J( r/ ]6 q5 Z& Z' a
  24. ) z# H! }" \1 S; f5 F
  25.   /* 初始化数据控制寄存器 */
    1 P' S8 p+ `9 Y1 }( h+ E; M
  26.     hsd->Instance->DCTRL = 0U;
    0 X3 Z3 q, N4 v! k
  27. . F3 V7 n" [* W8 o* p" h
  28.     hsd->pRxBuffPtr = pData;4 u" L' A0 v2 Q4 p- b/ H: b
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    * \8 P# a3 y4 ]( q3 `

  30. - x/ o! @, m" a$ ^* T) d
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ! u3 k* Y, I) s0 f3 d
  32.     {
    . i* I, ~7 O& s2 ]- Q$ O
  33.       add *= 512U;5 A0 {6 j* @; F
  34.     }
    5 t( x  ?8 ^" ~4 A$ F  F0 B

  35. + o! H0 s3 t- r( s
  36.   /* 配置SD DPSM (Data Path State Machine) */
    $ P; t* t+ A2 D% S. Z; g# @  w
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;; c/ J5 Y$ i7 d& y& N: s  c; c
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    4 [- @' N5 `, M% k) @1 W% a
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;$ x+ x0 D; X# j, g1 g0 }
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    . v# h' T1 o& `  N8 {* ^& d
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;2 @* R( K' n! B) m0 E/ ?
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    1 T8 ^/ w/ d! \
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);) p9 w3 h# b7 X! z, N1 D
  44. . V0 H* c% @9 q0 t( W0 N
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    . }  z0 j: j/ j# d& H; c
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;) b$ r5 d/ Q0 R8 W
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    ; m/ t& G8 U7 i8 O* x
  48. ) w- U4 e/ ]( E. r
  49.   /* DMA方式读取多个块 */' @6 f# d6 U  ^5 Q
  50.     if(NumberOfBlocks > 1U)' t; }' L1 T: [: o  y
  51.     {
    / T% ^- Q) j# E9 |0 K2 s
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    7 X0 l; m" ~  P1 d

  53. # C) |8 L! Y  ?% x1 V! g6 S% G
  54.    /* DMA方式读取多块命令 */6 o9 y& ~: C. `- `% S6 C1 a" A6 Q
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
      m5 p/ ^2 ?6 D. d. p( w3 l6 O
  56.     }3 |) `6 P+ K8 @
  57.     else; v6 L& j! [6 Z  w5 Q# L" A
  58.     {
    ' d- b3 Q: p2 r1 B" O8 d
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
    6 Y# u7 `" l9 v! M6 i7 t
  60. $ S' {6 h0 R! v; F0 n. ]) D8 M8 W
  61.    /* 读取单块命令 */) Z& z2 f; H/ q' [, R' f, B
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    5 `- n5 E9 p3 u" ~
  63.     }9 Y; F  P0 W3 L" G
  64.     if(errorstate != HAL_SD_ERROR_NONE)
    : O6 |! [6 m. r# d1 v
  65.     {' @# Z% X6 d5 h7 `2 U' j. ?4 K
  66.    /* 清除所有静态标志 */4 v, F5 F7 M3 R- s+ x1 S6 R; e
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    , N# [# c8 ^+ x2 l; y
  68.       hsd->ErrorCode |= errorstate;5 p, _  x$ y7 Q' ~! Q8 G- p& ?
  69.       hsd->State = HAL_SD_STATE_READY;
    7 c/ Q! o8 `) @- m
  70.       hsd->Context = SD_CONTEXT_NONE;
      W! T. k2 R& d! h, V: S
  71.       return HAL_ERROR;
    + L$ B) T2 x! C) Y6 r; t4 l) J+ ~
  72.     }
    - T7 n: o) M' M$ f
  73. " j' {3 L: I5 D0 _
  74.   /* 使能传输中断 */: e7 {# D9 I" j0 E$ p: x' a$ A
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));) A- F3 W0 w- I6 N; V
  76. 3 Z( X: Q( \" K( g$ E
  77. , E4 X  y9 o, K0 G: r
  78.     return HAL_OK;
    0 H  F  v8 B+ {% o
  79.   }
    $ G8 \2 \6 q3 \7 D
  80.   else- B# \5 [. w! M6 A
  81.   {
    # r$ F! x7 g* H( V  K
  82.     return HAL_BUSY;+ R" D  D7 ^; V& }% Z
  83.   }( i; _! n2 U9 [- P
  84. }
复制代码

0 P1 k' t5 X$ i2 q6 _函数描述:
$ a, P2 X0 a- B) [
- ~' Z/ ?" {) B此函数主要用于SD卡数据读取,DMA方式。4 v0 D3 D+ z7 i8 q& S
/ c# ?1 s2 i1 f; x) f
函数参数:" j* r7 H* i# N$ _$ j* r/ ]' [

# J! k3 F, R# s! c; p, Z  第1个参数是SD_HandleTypeDef类型结构体指针变量。
  R5 a7 I- \! U9 A% M* \/ }  第2个参数是接收数据的缓冲地址。, ~2 h+ E  }+ v+ E
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
" G' I: A% M3 M1 E  第4个参数是读取的扇区数。
, v0 O9 V/ N/ @6 ~# n  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。9 v4 U% U& t$ f! ]1 ?
使用举例:% V5 Q  P& S4 ~) j- C, v

1 C2 _5 m" H) k2 F& p
  1. /**
    8 T4 w  M5 _/ j7 {- c1 C
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
    ( z0 D( p" ~; b7 k$ Q! I
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit  F9 q2 V. g: [6 Q9 }/ S
  4. * @param  ReadAddr: Address from where data is to be read
      K4 K9 S, ]4 q% `
  5. * @param  NumOfBlocks: Number of SD blocks to read. l7 \* m8 Y: m. u( T
  6. * @retval SD status
    & K1 O# n/ r1 Y3 z; b1 d1 T
  7. */
    - _2 d2 w4 G7 _3 `) P7 p* o
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    - m5 b! L) L9 \5 g
  9. {1 u" K$ L1 {2 Y5 [! k3 G

  10. , X# ~4 i& `2 f! v# ^
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
    9 i9 B1 H2 j" C4 q) n( V
  12.   {
    5 I$ a0 g% _3 m$ Z3 T5 p4 Y/ Z& `
  13.     return MSD_OK;
    8 a5 w# L8 _5 l& t% E+ v
  14.   }# }  H. t$ G5 w8 ?6 u
  15.   else
    ! r# R2 b! Y9 S' u& i
  16.   {; m& G2 A/ N8 ?9 O2 G5 V
  17.     return MSD_ERROR;
    $ `5 z. i* t0 n2 ~- m
  18.   }3 I3 D& P1 m7 n4 L2 }
  19. }
复制代码

4 E5 g2 L' z; p$ J+ i87.4.6 函数HAL_SD_WriteBlocks_DMA
3 A& ]* f6 k6 @; c8 E函数原型:
7 g- N3 c$ @/ h& H0 o) k" a( [+ R4 o7 _9 _
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)0 M  t) O3 K4 T1 C
  2. {
      s5 F- R7 K; @9 G6 G( w0 b5 B/ A, Z
  3.   SDMMC_DataInitTypeDef config;
    ! a% P0 x; I. m) s% T6 w7 q+ s
  4.   uint32_t errorstate;
    . T2 g0 U& l# f
  5.   uint32_t add = BlockAdd;  c$ _- _, k  K) H" Q0 _0 C
  6. ! }" n! N: R/ J+ E9 D- X$ Z
  7.   if(NULL == pData), H* i. H/ Y/ i* |+ Q
  8.   {3 ]1 D  @/ p& ^
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
      n. i' Q9 l* |6 Z, ]9 ?# j
  10.     return HAL_ERROR;
    1 ~/ }1 ~3 I% G  I
  11.   }
    : W' |/ Q2 T# A  g. U$ R
  12.   ]0 P: Q/ P! k/ P
  13.   if(hsd->State == HAL_SD_STATE_READY)
    # L9 P; `% Q! t3 e2 U; f* p/ c# K
  14.   {
    " l1 Z1 b- O$ b3 g( r* u
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;- G+ K( Q9 `2 e0 |- }

  16. - |  y( G5 F5 Z$ ~) b
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    7 y6 B5 B* q1 A) D- i3 C, i
  18.     {
    , {# Z& G" C9 T- ]* P
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;0 {- d( W  ?5 S- w% o6 n& q: \" P2 M, H
  20.       return HAL_ERROR;, @& ^! m2 R4 q
  21.     }
    ( F: c5 T0 k" U" I
  22. / l' j" v3 H# D6 N5 f
  23.     hsd->State = HAL_SD_STATE_BUSY;
    + d0 \+ g) W  J: M* X6 @  W
  24. . d  L( U! g9 l
  25.   /* 初始化数据控制寄存器 */
    0 m3 V; a9 \+ r
  26.     hsd->Instance->DCTRL = 0U;
    7 \1 l8 [- v' p+ F: u& Y. e
  27. # B( E5 }' |7 z; ]' S
  28.     hsd->pTxBuffPtr = pData;9 x! x2 f( _" M0 I% ~; c/ d; @
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;8 l7 O! k; K- T
  30. . W! p+ L  Z7 J- C+ a% }1 _- y3 p
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)4 Z/ s2 {( F3 e9 ~* N
  32.     {
    ; A3 B4 U1 q7 A- o. T7 ^: Q; ^) ^
  33.       add *= 512U;' B+ i0 m5 m$ i/ z) v4 W' _; Q) a
  34.     }
    ( w3 d& f" K2 x* W

  35. $ z5 N( [6 T! ?4 ]4 r7 Q
  36.   /* 配置SD DPSM (Data Path State Machine) */# X9 Q# C  I: X- r4 ?, ~4 ?
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;1 U4 v! R* f8 S" b: y, {
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    & _9 P% B# R/ c2 K' s1 Z$ f% w3 C) J3 H
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;6 {: b, a- C2 @2 }: a: G
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    9 J+ ]* p- Y+ o. p
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;6 c4 B$ P. D: V5 Z& M2 M
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;) B1 M, Q3 m% X7 c- }* i
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    , X8 M; H5 A& T: N+ W; {3 l1 t
  44. 9 h! `2 N7 P. r% Y
  45. $ A. a! ^# N: N* [6 J
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
    3 v5 f- o+ v+ C" c  @* X/ w

  47. 4 q+ t0 X7 M' R6 |5 J# W
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;' z8 V1 _$ C$ ~! F0 e
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;1 X8 f2 I- X' l( v. e
  50. 9 Y2 `  ]  P' E. P) t8 I' F
  51.   /* 查询模式写块 */
    1 |. \( l% \& d" g5 v! G
  52.     if(NumberOfBlocks > 1U); }5 E2 I8 x  |! S5 C- G) [
  53.     {
    1 e6 ?* K7 _7 r7 A
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);8 I" t# {2 u4 c+ {# X: R% G4 Z
  55. 8 w+ t. V8 h: g5 Z
  56.     /* 多块写命令 */7 G! s: m: \6 x. |* F. @
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);- {' ]  n1 y1 S+ e
  58.     }
    ! s. ?0 j5 u* ?1 k7 j; ~  c. `
  59.     else; ?. X4 m$ n0 [! y0 s
  60.     {* {3 r9 T- E1 n
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);  `+ u5 l1 v, S. f  C( I% }, M2 Y- _' q
  62. : M' G# O7 Z5 C
  63.     /* 单块写命令 */& J6 c1 d  P9 S
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    / F7 r6 p, P( c! Z
  65.     }8 `3 x' P$ E* @4 c3 q7 L6 ~( A
  66.     if(errorstate != HAL_SD_ERROR_NONE)
    ' o/ x* h4 F6 Y/ j7 M
  67.     {) P5 |+ _( z$ k  a0 `/ ?, {8 O
  68.     /* 清除静态标志 */
    6 v, ?7 I' j, b4 K& V- |
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 R# ~. ]% q! |2 a$ Z
  70.       hsd->ErrorCode |= errorstate;
    # J4 X( ^8 m6 K3 M2 g$ Q" S( B$ M
  71.       hsd->State = HAL_SD_STATE_READY;
    ) S' X" Q; b* f/ H4 U' l0 V
  72.       hsd->Context = SD_CONTEXT_NONE;9 s$ J9 c; b) T) @1 J5 _) v
  73.       return HAL_ERROR;2 K& x! T3 I+ p3 F' [; d
  74.     }
    ) K& [! i% ?- r4 V5 O; ^
  75. . J" a! o* o0 u, g
  76.   /* 使能传输中断 Enable */& R: A0 m" i% F& Y# A
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
    5 j* D0 ^/ U, a. N* D+ j

  78. ! D/ H5 q0 G) n# S8 Z
  79.     return HAL_OK;
    : |  _9 S! O3 w' j7 L. R; b
  80.   }
    2 W9 f5 H: C2 f5 G
  81.   else
    . q8 @, C# Q- {% _4 ]
  82.   {" S. l- _9 M% F6 [
  83.     return HAL_BUSY;
    - D" ?8 o- S7 j9 |4 F9 ~- F# }
  84.   }
    6 A" g' c( d$ s" ~. Q
  85. }
复制代码
# r( \9 n  A. J  n* |$ T1 g
函数描述:8 Q9 }6 r) \# |4 p5 _( y9 |
. i6 q6 A* U7 b) }, A
此函数主要用于向SD卡写入数据,DMA方式。
3 H9 s# S' Z. l% N- ]5 V9 d+ }& g4 O* q8 [
函数参数:9 A3 A6 L( x7 j8 s* ]7 W
) C$ B! N5 t2 F6 j, u2 P3 p
  第1个参数是SD_HandleTypeDef类型结构体指针变量。" V! B% |6 L) c  K6 L- b# I
  第2个参数是要写入到SD卡的数据缓冲地址。
* |0 Z; Y( T/ I' V  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
/ m6 t) L0 Q' z9 k7 U  第4个参数是读取的扇区数。
+ ^# S) P( P4 Y" z+ N  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
  e- F! K0 i8 ^- k使用举例:
3 ~) h, Q4 k3 P# R$ m8 H
. g; y- V& W/ _2 U) G/ D
  1. /**# @; ^' q$ \' x# O# ]+ g, E
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.% C3 R: e( {' r8 q9 v$ E( ]. Y; G7 L7 n
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    : i/ E7 E' r) m3 W- `
  4. * @param  WriteAddr: Address from where data is to be written
    % ^% u/ ^$ ?/ |9 k/ Z: h
  5. * @param  NumOfBlocks: Number of SD blocks to write
    ) @1 H0 ~4 z! d4 Z; g" ~# C; [
  6. * @retval SD status  N3 @3 Z% X$ T9 I4 A( Y
  7. */7 Y8 y% N, S6 y9 h: B+ c, u# |
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    ' d8 K1 f# Y6 b
  9. {
    6 [2 G8 O/ b- }: R
  10. , `7 ^. \/ n- [% [! e) a# n  I: Y
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    2 w' `5 o  ?4 N- W) k4 l+ _
  12.   {
    1 e! G* _9 P' P9 Q
  13.     return MSD_OK;
    / ?( j+ a7 h* L5 V
  14.   }
    8 b* u' z4 d$ B+ a
  15.   else
    % m; r' m2 `6 w! F+ |% e
  16.   {, M3 q; D3 W. Y* t
  17.     return MSD_ERROR;
    ( N& Q+ w& D3 \& B$ @5 t* E
  18.   }; |" u; E. A# Q( }$ N/ k4 ]) k
  19. }
复制代码
% q3 o) F+ H- p! u
87.4.7 函数HAL_SD_Erase
6 K* C5 Y: \2 t函数原型:
8 |' B1 f1 r* U+ X) e( }2 m3 N$ H/ V+ E2 g- X0 ]$ }! r& Z# v
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)2 r8 g& v9 W& }4 k% {* X7 d/ f
  2. {
    " ?- F3 _- U% f. v8 i6 \
  3.   uint32_t errorstate;
    ) Z% b! I  y* g5 W( b$ B6 |6 B
  4.   uint32_t start_add = BlockStartAdd;
    6 H/ H1 ]" G$ R7 E+ s% P
  5.   uint32_t end_add = BlockEndAdd;
    2 ^( _9 W$ @. l' Q3 S0 W
  6. * L2 A6 d" d/ |3 u' M
  7.   if(hsd->State == HAL_SD_STATE_READY)" r+ _# [7 H! G
  8.   {
    ) v, Q* c4 v0 S" i( @' q
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;! z' E* }$ r9 o1 d+ T) ]5 t3 u2 \% w

  10. " f2 Q1 O- `9 T+ [
  11.     if(end_add < start_add)5 G' s+ |  I1 _$ A
  12.     {; e: z/ v7 C1 ^# f+ e
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    % x; D9 E. i$ Q$ H4 O3 P
  14.       return HAL_ERROR;3 p5 d2 @) w+ {3 [1 g0 H
  15.     }  y- D6 l) E& M- v! ]& c$ }2 g

  16. 3 d# @% l$ p' R+ j9 X# t# @8 H
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))* G  H: i( M- y6 K' z
  18.     {
    0 q6 A  Q. K# f3 i6 b: O
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;" R0 i# ~! E% l7 V
  20.       return HAL_ERROR;: \5 f% W; X7 u/ ~" P
  21.     }/ o* j. _  M8 v6 r# c

  22. 7 P- S7 Y. D- t8 n4 n, W4 H
  23.     hsd->State = HAL_SD_STATE_BUSY;9 R0 g  M% q$ j3 I- x% |& J. k3 u
  24. + c: _: l: y' n' O
  25.   /* 检测是否支持擦除命令 */! @6 u9 f. P: x# K/ |8 [7 g& M4 n7 m) e9 Q
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    + |7 F% U" }6 j
  27.     {
    , t. r5 u( g! K
  28.       /* 清除所有静态标志 */* E( F" M% H3 B  s3 M+ l# k9 v
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ! S. V' e6 P. V  {. @$ R
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;& n0 a4 C" Y  g$ T
  31.       hsd->State = HAL_SD_STATE_READY;
    7 h( J$ _) V4 g* \
  32.       return HAL_ERROR;8 S4 Y( v2 [  e7 d7 l8 j: v
  33.     }
    8 c  U7 F; d: @$ ]  t% j4 o* i% T* m
  34. 4 U. H0 w; X6 ]  s  i( Z- F0 q3 U" k$ j
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
    3 l; x: I" D' b- J( P5 }2 _
  36.     {
    ( Q+ e( _- E- w5 C
  37.     /* 清除所有静态标志 */
    4 d8 Q1 h! J8 f. N7 [6 O! z
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    0 K& n5 T9 A/ L) i# G: X! f. \
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
    ( [3 {1 T" g- t& A1 @" j: A
  40.       hsd->State = HAL_SD_STATE_READY;
    3 d' i6 @; E3 T9 G& M7 Y& y& {
  41.       return HAL_ERROR;9 `7 Z0 l+ G6 U+ x1 ?' L
  42.     }, I# p! n) J/ b3 z2 Y1 d" [( w

  43. / T8 @: ]# e( x+ q2 g$ q0 @, m( }
  44.   /* 对于高容量卡,获取起始块和结束块 */% |2 z' K$ q- W  {8 M% k4 ~# [
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)! T& [/ C2 U. [9 X2 W9 E
  46.     {
    % ]  u- c. ]# U+ P
  47.       start_add *= 512U;9 v9 C. E' L! o0 j  U, E
  48.       end_add   *= 512U;
    ( ^* K& t$ d: b: C7 }
  49.     }5 G- [2 T! d* S9 q
  50. 5 x. A& L3 U' H) w
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    9 k  V5 i- M6 S- j: E
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    ! N. k/ N4 y8 m1 l1 ]
  53.     {  R0 Q! h* q' ?  \& m( |
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */  f8 I5 Y' o% j, n
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);$ \! r& I- S2 P8 h6 n6 F# H
  56.       if(errorstate != HAL_SD_ERROR_NONE)+ K2 I% e9 C2 A
  57.       {
    5 B0 m' K& e, L$ g9 t, L8 P
  58.         /* 清除所有静态标志 */" r* N8 [5 U1 K, e5 _8 l! t
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);6 P- Y% y1 k1 j$ N+ v: H2 ]
  60.         hsd->ErrorCode |= errorstate;5 h/ f, U7 I0 `+ R3 W7 t# p
  61.         hsd->State = HAL_SD_STATE_READY;
    9 }  f+ G7 ^% T- O" {4 F
  62.         return HAL_ERROR;
    0 T4 M% L0 \3 ^# ]1 U
  63.       }
    4 P* }- |8 y) I  y
  64. ) O' |% y, q! ]8 `2 r/ u8 ^
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */1 b4 {& A$ Q2 h. B; z
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    / |0 q/ m$ X( K+ S+ t2 S  p# Q
  67.       if(errorstate != HAL_SD_ERROR_NONE)( T( ~7 m# G2 o. ~& q
  68.       {
    ' U' K5 d3 N- ~! T- }! r
  69.         /* 清除所有静态标志 */: A5 Z, S, Q9 R* T) ~1 T0 j- ^
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);5 U2 [2 T+ H1 Z+ {5 ^  V; H+ L
  71.         hsd->ErrorCode |= errorstate;& P2 W0 e" ^) {+ M( p
  72.         hsd->State = HAL_SD_STATE_READY;
    ; Z) o* B. k% H5 `9 w" M6 G" V
  73.         return HAL_ERROR;
    & j; ], i8 B1 Z) U
  74.       }9 f5 a3 h6 I7 y1 B/ a
  75.     }
    ; K. F) B2 M, J- F1 }
  76. " X' Z% ^* ]) s2 w3 _, Y
  77.     /* 发送CMD38 ERASE命令 */8 C& _; i: `3 G1 q9 a  }" L
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    4 _& J) Q( q" n8 S
  79.     if(errorstate != HAL_SD_ERROR_NONE)) H1 v7 q0 F( Z3 d. D- c" `
  80.     {
    : b" E# G6 s+ Y; n- P( W0 c
  81.       /* 清除所有静态标志 */
    / i' E' A5 g2 d( Q" C: ]0 `" \, |
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    6 [# _" G3 {9 @" C0 z
  83.       hsd->ErrorCode |= errorstate;1 u( v% |, m! }. E$ j  C! |: X& \/ R; Z
  84.       hsd->State = HAL_SD_STATE_READY;6 G  E* @7 O( v7 q2 o; V1 q
  85.       return HAL_ERROR;
    % H0 v# {1 @+ t" ?* q% Q; `. }
  86.     }- ]$ N+ ]: P( T( [. Q1 J' I+ v
  87. 1 m! K, j( d/ r5 s; I. P; A4 ^
  88.     hsd->State = HAL_SD_STATE_READY;
    $ b# K5 \" [1 @7 L8 X* d9 [2 S
  89. / v6 f) C8 ^) [3 K' `1 I, m
  90.     return HAL_OK;5 i/ w8 C+ ]+ }$ V% D7 v
  91.   }
    - }, P5 h( A7 G7 Q
  92.   else
    1 h# ~( b& e- b9 o; _2 y1 D
  93.   {
    6 S! \6 H  t: f% h) l
  94.     return HAL_BUSY;
    % n) t7 z# S9 l- C& P2 g# z
  95.   }
    2 d. }( O7 n; Y. W* X, G
  96. }
复制代码
1 P8 w' J* W& i* e8 J9 [
函数描述:
0 g# h8 Y7 e3 S" d5 o/ I( [' G/ ~" O7 K0 t# V
此函数主要用于SD卡擦除。
3 P5 ]- J/ N+ \
1 V( w- y4 e" @2 E" x3 q函数参数:
7 p( I; W# B$ [; N% ]2 X/ e& P/ Z2 [6 ^/ e# l4 z- Z
  第1个参数是SD_HandleTypeDef类型结构体指针变量。) Z1 D$ g: D2 M
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
% F( ~! v1 R: H! \8 U9 ^2 k  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
: _5 x& ?' k2 c. V7 d1 C2 @  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。+ X6 _3 {+ g# q& o( r: G% Z
使用举例:
$ H, q5 n6 H: D& v: ?6 z
2 Z" _+ c" b3 r# w( Y
  1. /**! Z8 ^; j$ d$ O7 X/ r' e$ G
  2. * @brief  Erases the specified memory area of the given SD card.: [8 T. j9 I: M' Y+ p: Y( l$ E
  3. * @param  StartAddr: Start byte address/ P/ f: B) v7 a+ j) p
  4. * @param  EndAddr: End byte address
    9 T5 O5 o3 v/ q0 g: V
  5. * @retval SD status% k  M! [# w% N$ p: d) ~
  6. */
    4 |% g2 K  I/ ^  c! g
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)7 H# k  {! b8 |3 w8 R
  8. {8 I% D+ e0 S0 o( C% d6 K

  9. & w, q/ u- b5 W" T+ M2 \
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)) d- b, L" A; J( J+ K
  11.   {
    . N: N) ^8 {/ p9 n
  12.     return MSD_OK;
    7 o; k* l9 [' a: \6 x; P  P2 j
  13.   }
    7 q) U9 [! f* v( B
  14.   else% ~8 `; ^. X8 ^+ x6 u
  15.   {
    2 F2 S; l+ s+ ^& @/ b/ L& v
  16.     return MSD_ERROR;1 K" Z0 i6 B$ n& u8 H( p0 S
  17.   }: |3 c, u: n" @, H, J
  18. }
复制代码
5 C' U: T% g( O6 U& N
87.5 总结! Z3 y: m0 x/ i' Z2 h+ M4 e
本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。6 L, j8 m9 ]5 ?7 T! Q! W$ j8 t
9 x1 K( H( q9 N" i

# Q$ V* z; a; F. U
收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答

所属标签

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