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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:38
87.1 初学者重要提示
, c! w0 O# }; S  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
$ G4 l0 w$ r5 a# p" X  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。
: y& H8 f; N/ z0 ~( o! A, }  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。
8 l+ W9 k1 l  A# p  SDMMC驱动SD卡支持1线和4线模式。4 K  I5 Y! K( r: y- [4 ^
  STM32H7的SDMMC也支持eMMC:
$ p6 z+ e# v& d4 o  
1 s; E" h8 o4 K0 }4 |8 S: U4 {) E5 c87.2 SDMMC总线基础知识& F5 N5 Q" s  ~2 x& [9 \" ^" |% ?
87.2.1 SDMMC总线的硬件框图+ j6 V/ W5 y' I, C7 @8 Z5 r. r
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
+ U+ O' U3 x0 M# L$ C5 S  {2 e& J9 K8 x; V
6eea62abe623396815a50adc87205b83.png
/ b! Z) i) y0 |) g/ S
1 Y8 T- v9 M0 Y# i6 i
通过这个框图,我们可以得到如下信息:# a4 V) j, z1 _7 ]$ [
; J9 W6 B) [' |4 }5 V+ V1 b
sdmmc_ker_ck输入
" _% h& L/ @* A$ FSDMMC内核时钟。
2 l8 Q" Q3 C  ^7 L: f0 \* l9 f6 `; f( u7 b$ D, T& l* \
  sdmmc_hclk输入. L* Q: M4 i2 }! s0 ~7 {
AHB时钟。0 c8 {3 k! |6 t5 T
; q, C" r3 `: ?8 s# x6 d9 q
  sdmmc_it输出
; }! N: Z1 \, ^( A* ZSDMMC全局中断。
( X4 A& h& c+ K- a) P/ \8 S( W1 o5 Z, p1 @" r0 V
  sdmmc_dataend_trg输出& [) o; L9 N1 q' ?1 y& O/ O
MDMA的SDMMC数据接收触发信号。
- D" j& j( t0 ~( S, f/ Y* K2 ?; c
  SDMMC_CMD
, J8 \$ k, k% G1 t% N# YSD/SDIO/MMC卡双向/响应信号。# U- O2 v( h0 Z6 G! ~

$ V0 o, e! |, N3 }  SDMMC_D[7:0], w) f* ]/ p% S. s- C( r$ B
SD/SDIO/MMC卡双向数据线。
1 C: S& j( Q7 e
! z, R# ?6 ~+ j$ q- x/ j7 B  SDMMC_CKIN
0 A3 R, x5 {' u; T; `来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
5 ^( l1 \+ g$ l  z, R- p9 W
5 b; r! J/ g( n6 ?' o: i3 ?  SDMMC_CK
) }* B. Q- |/ H8 x4 s. `" `+ n, LSD/SDIO/MMC卡的时钟。
3 g/ E: n( c- q& o* R* j8 t; s1 m
; S1 |! S1 }2 T" ~  SDMMC_CDIR9 s3 h4 O) |4 L. z1 S
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。( n/ J) |. {; \# @. i
) r4 R5 t4 G) G
  SDMMC_D123DIR
4 e) L( K! y/ k5 KSDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
) z7 w, h% Q% t( n1 }$ ~$ v+ s: e, P, U# s' X5 X. D
  SDMMC_D0DIR( [( j  Q( g6 C" O
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
# r  U, U# W; i1 U( S# l+ ?
  ^! {1 @# s6 V* ]% N3 g: {STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。8 `, r. U" Q. x. U9 }3 }2 D
- g  P: i% P& |' q
87.2.2 SDMMC时钟: O$ h3 ]3 k* |* W
SDMMC控制器的时钟来源:
2 t" q9 Q/ p( i
: a; I5 q7 ?, P+ |8 u2 `5 h
676ec31792fcb80bee640ed979d48084.png

" Z* Y! G' B0 [. P5 c+ {2 Y6 H: v+ \3 n2 w, J
SDMMC1和SDMMC2时钟源是一样的:1 o: c5 {$ `. Z

7 b# [2 n7 E8 n, J2 I$ B  l" R2 T( @% k) i1 [
79b1c69986d1ee5bc090bf1676f396fd.png
6 B. w& T1 K; H7 x9 P1 q7 Y

. H/ J: u% [  k87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
( s5 ^, X. B7 U( ?) j注:大家应用时要特别注意这个问题。; p8 G# U( B3 k1 ~3 u
6 |- e% x8 V' f
使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的+ @  s7 ~# X: S. J2 z
: T. C8 s. \8 {- H
6a5491d2f4a8740d838af58d034b7597.png

" f( G" |* L: `. s' L! t- N( y: h, D" m- K$ [+ W( L
87.2.4 SDMMC支持的速度4 d, v, b3 J6 s2 q5 E
驱动SD卡支持的最大总线速度:
6 `' k! |8 y- n; \' B
- p9 K( h5 |2 {+ E. N: H6 ^
b70ce31107b38ea820dbc28c3caec38e.png
% G% X. b& \* f* y9 o7 U

9 V& k2 y7 o5 y& b驱动eMMC支持的最大总线速度:- D6 v( V( M5 S

, G5 @" x# j# u
843bf7a054944ba7d5d137ca84e1d4ed.png

+ H9 B0 {+ z  z/ R1 ~1 f7 @7 U% S8 r' W; A* Q
关于这两个数据表,注意以下几点:
  b# v+ d+ t0 k' a! X+ R+ K
; ~5 i0 L9 M# \$ V; ^; ~1 G  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
9 |+ B3 ^1 ?5 n! A  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
& @) A. O( g+ [6 E  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。/ c" i# e" {- s0 y. D
87.2.5 SDMMC支持UHS-I模式
5 E; L3 n0 l6 F/ d' r  Y' pSTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
: {! ?: |3 N" v3 L% b1 k3 m9 t+ Y1 i+ x- d# a# j
2b8e4430b8a60dc5a1b342d7c7f75f52.png
- ]% g7 n, }* ~/ G: K7 F5 A2 ~( @
2 ]* A& x5 T2 u& z) _( M* `0 d
85f975745619c9afc64f8889289dad58.png

0 P1 Y1 q7 T' Q% b" J% l" m& ]* O# [1 X* G! R6 V5 X
87.2.6 SDMMC自带的DMA控制器IDMA
5 r: k. q6 W, |5 J3 N- hSTM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。, L' t4 y3 C- t0 O7 f. l6 O9 v

/ E. w! C& a3 v% U2 T- m$ y87.3 SDMMC总线的HAL库用法
6 w) ~/ u3 n9 D* |" R  F87.3.1 SDMMC总线结构体SD_TypeDef
+ E8 q) r8 c2 `SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:: o( k; Q8 @' Q
  a% \/ p) Y8 d0 G. D% |1 |; d0 G
  1. #define SD_TypeDef          SDMMC_TypeDef
    . ?9 P8 e- x( b% y' s7 r/ h
  2. typedef struct
    * h* r' n8 m1 u- T: R9 _' b; D
  3. {
    9 A$ d$ Z( e+ `
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    & l6 W' {% b* E. _" N2 a; f
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */
    ; V; H& D7 {, ]/ k
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */
    ! o  D5 C$ d0 O5 E
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */
    ) K# _% H# s% H3 I8 v& v
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    % G" T* K5 a$ N/ d
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */, t% M6 D/ s" A3 o9 ?
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */
    - r3 i1 _+ M. c. @: J/ E: Y- S
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */6 [7 Z8 K" h  A& W$ j
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  */* z( a, v- y" C- C4 J- h3 t5 c
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */
    . x9 t6 I; |7 L" r3 B9 A
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */. S  C) E5 I0 l% Q( i) U
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */
    5 k& X9 y1 B6 K: z5 F4 U7 ^
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    . m: f4 }% k0 ^
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */$ |) M/ Q4 K* [1 i6 M
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */3 x4 L5 U* A8 h7 t# S/ u/ D
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */
    . I3 b8 I9 Q, x5 x5 w
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    ( c) F- Q& a2 P. j% p
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */# n9 J2 y+ ]% g6 }
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */
    0 j) ]/ r1 }+ d: U: T
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    ! H& {4 B- e9 p7 {; ^3 m- n
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */2 k$ G: ^* p$ W! |& Q$ W0 n: U7 A
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */, g) h/ a2 L% H% Q
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */
    % ?& h, q* r* h9 l! P
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */! u. W  z) o/ `3 \" h! X8 p
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    . s2 f6 X. r& U! @3 \8 j+ m
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */1 }% F7 }1 u4 Y5 [
  30. } SDMMC_TypeDef;
复制代码

( t1 F* ^. @" \5 O" n0 I. X$ H这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
  {0 h: B2 ]. L& U: P2 ?' E  z( H7 H, Y; ]% ~- b
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
6 ^) D- F, m* h2 Z- B( G  n3 S% e( [5 O1 K8 o
  1. #define     __O     volatile             /*!< Defines 'write only' permissions *// F, z. y1 a0 Q  o9 z0 t+ _
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

0 Q: s  c5 x& l2 W0 I# N4 i下面我们看下SDMMC的定义,在stm32h743xx.h文件。" }! N$ B0 s) T, q2 Q
5 X" M# a! ~% L7 D
  1. #define PERIPH_BASE           (0x40000000UL) - P( ]3 w7 `% G& ?# S
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)
    7 ^" m7 P  A" o; Y
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)! b9 @! ]5 U, A

  4. + [; Y' F" a& ]. y& x- a8 o
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)6 L" o0 H& Y1 A) Y8 \4 l( y
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL)
    . V, C0 J1 H  Y& Y* B3 _, k

  7. " ]; l* F. L8 l, ^4 g
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    ) C) m7 j: g0 r& ?
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码

' T" b  }( |' Q& Q0 u) B3 C. J8 B/ b# d我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。+ @0 Z7 l# W4 ?7 G- _; ]- [

- x* ]% ]' i6 b8 Z8 A: R87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
4 F: N' X; f2 ?: y; u. H- @( c下面是SDMMC总线的初始化结构体:; e. \) ]  a3 _. B

! |2 A" p2 n( [5 e3 I( L) N4 O, M
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef' Y. p7 r  W8 e3 ]  Z. \
  2. typedef struct
    7 ~$ \/ [. h& M% z5 e
  3. {8 Q( m: t! x1 |- ^8 Q8 n- p" h
  4.   uint32_t ClockEdge;            
    : ]; B) @+ |$ x$ l0 G: Q# C  U
  5.   uint32_t ClockPowerSave;      0 m& t! s; q# v
  6.   uint32_t BusWide;            
    ' _6 y% W: m6 Q7 X
  7.   uint32_t HardwareFlowControl;  
    4 z- k) B* |9 r5 ^3 q
  8.   uint32_t ClockDiv;            
    $ ^8 k" u! r6 a- o+ _
  9. #if (USE_SD_TRANSCEIVER != 0U)
    , G5 P$ K3 K0 ~* @  N7 t8 n: L
  10.   uint32_t TranceiverPresent;    7 a8 p( H- S' n8 [: `( w7 e  h
  11. #endif % F1 F9 {8 C9 m
  12. }SDMMC_InitTypeDef;
复制代码
& X8 A2 h+ o* A) t- P% L$ r8 _+ l
下面将结构体成员逐一做个说明:/ s4 }% w4 L. p" R" Z' Z
  [& v+ R$ Y/ G! i/ D) e
  ClockEdge
: p: L6 }: I2 ~7 w$ i4 j用于设置SDMMC的数据或者命令变化的时钟沿。" o/ L; @* {8 d  O0 U; Q
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)) L7 K3 I  H; W" G* a( v" x1 U6 \
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码
8 p# k$ [% {6 h1 |
  ClockPowerSave
) K/ H: A' ^0 P. G6 \用于设置空闲状态,是否输出时钟。
, Z# S6 {9 P: {7 P3 v0 a
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)7 c9 B  i0 T" ]$ N4 T2 M; M/ B
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码
- s+ r% l  F& i% D9 i8 S* c
  BusWide' p6 c- j% u4 V1 K% m% H
用于设置SDMMC总线位宽。  `0 H7 n7 }; ?. X; m( \
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    ' ]  `& B1 n  x5 C. k2 t
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_00 H- F) v1 J, z' e, d
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

; {0 Z, g" t: z$ n1 z  HardwareFlowControl
* f, E; x" n2 v; W8 R! d用于设置时候使能硬件流控制。0 h6 X8 E/ u: ?6 o" ^
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)% ^, Z% X$ ^# J9 T/ B
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码

( O, F* P# G' D" B% z  ^# i7 F( F, I  ClockDiv- R  g- f* ]/ M! ]  Z
用于设置SDMMC时钟分频,参数范围0到1023。4 ^, ]: G+ ?) C, A* @
6 T/ c- }/ a2 I0 O5 o, m
  TranceiverPresent! h) K; W$ v2 A  }! D  A, U
用于设置是否带1.8V收发器。, b: l" F+ t: `
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)5 {! g" q( k) t) G2 W0 M% ~
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)
    2 u2 j, @$ w) d! {! E- h
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码

  O6 F9 s5 x$ v- T" k87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
1 z) q9 d7 p- [# f$ ?1 b$ P下面是SDMMC总线的卡信息结构体:9 k/ B, b* s/ I+ T; H
  1. typedef struct
    8 x# G( F- B6 \
  2. {
    # v3 J6 I% F& `4 T7 @/ ]7 U
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */7 l" i- U  _, \! l
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */
    ; U& K, C( }' t+ D' ?
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           *// v/ U* K! Y: |* p
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    8 _! Q& R& b/ r3 @! ]* o
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */1 a% }, ?$ m2 {. p' v7 p0 f
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    ( ]1 _% t3 h  p2 m+ i
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */' F% ^6 X0 r9 v5 x$ I5 R. h5 k
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
    ' a; h$ e4 h* u0 Y- G
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */
    2 G7 ?6 l- m1 W) P8 P  I- K# @
  12. }HAL_SD_CardInfoTypeDef;
复制代码
" j/ l! |' d. K
下面将结构体成员逐一做个说明:1 q& d$ p. O$ {6 V. e7 Y1 ~* Y. A
6 B$ R" j8 a. u5 |! F" W
CardType
7 A, `# O5 I/ O3 M0 f+ F6 h卡类型。; M" N, Z+ i8 c; S
  1. /*!< SD Standard Capacity <2Go                        */8 Q, R! W( D# c9 s- Y2 x
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U)
    " ?- N7 |$ A, R; |  Z
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    4 K* y- Q6 s  ]- v
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    1 b% W5 q6 @3 F! B  n( v: }6 Q. `7 j
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

% |$ E7 [: x* M  CardVersion
" q% S. }. {7 I- J9 D$ H1 F" M卡版本。
! s3 r0 d+ e$ d/ E5 o
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U)
    ' e1 f# q4 O- G
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码

4 Z& L' u3 K/ T! D% n  Class
- y- \; }& `+ w2 }卡类型。
  K) i" d6 {# d6 V+ q% Q
! E: O: R0 F. H+ {8 T8 v9 y2 v2 O  RelCardAdd; i' i8 T; ^# {7 P' u/ A" Z
卡相对地址。
5 d4 u8 K9 J2 d0 I/ U- `3 h8 j: ?9 P2 h
  BlockNbr
9 |  G" ?  g* W整个卡的块数。
$ z& |( a$ [( z3 j& w7 m. }6 a( o% ~6 ]; h' Z, ~
  BlockSize
# l0 Y6 `/ c4 R! d. M每个块的字节数。
! _4 H( S3 I; m' S; _3 C2 a3 y% q! C4 r1 D$ F
  LogBlockNbr
! V+ C4 E4 ?9 p整个卡的逻辑块数。
6 R' h: n, M3 Q$ L% x& X6 C% S- o7 z0 s, r4 B7 V
  LogBlockSize
7 E$ ]* J5 O5 t2 L; o逻辑块大小
( G) X: @9 s! f8 T" M" h
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)$ w( q- i. u8 e# Q9 S8 A
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码

/ S. [1 L1 b  u8 e1 v( x5 S CardSpeed
% ^$ O7 O( f: k  R' W2 \用于设置是否使能SPI总线的TI模式。
" t6 L& L0 U5 X- g7 p
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */' c8 j! K) P; L% T1 @4 i2 ^' d$ F7 @% l
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  * F+ p" `7 [* t- ]2 Y1 @
  3. 7 c% ?) T0 ?) n3 p- s
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    8 d2 b$ d: \3 X$ R3 M$ `5 U! ^
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U)
    , t& w2 j( r9 {1 R
  6. ) H' c/ w8 B1 |9 R5 Q. ]" b
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards. M5 a( U5 d, a& i3 v4 [# ?7 N  @
  8.      and <104Mo/s for SDR104, Spec version 3.01        */
    9 |5 U$ d. [5 W: L. L
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

2 n6 \  S* Y, |" ]2 _: k6 y( ?( A: w87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef- w/ {2 o' ?$ [3 M8 D: b, {5 h
下面是SDMMC句柄结构体:6 j2 s4 R  O! g. b3 D
9 h! h; V2 i3 R$ d. i
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    0 H4 U$ q% }8 G  n7 a
  2. typedef struct __SD_HandleTypeDef
    ; {/ y7 }4 e0 M& e% S7 s' [
  3. #else( d- B+ ^: D; f) R7 s& M9 a, z
  4. typedef struct- i& j$ y( u$ g3 M0 D8 H: V
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    8 @, J# z" H# c" W- t4 I
  6. {
      i  p8 X3 G+ I" `  S
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           *// {' B8 W3 b. X( N9 a# }) x
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    : h" U# k0 e1 A- y
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */$ }) |7 J5 X( z; y( E
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */1 f9 Z0 ~, c  g- T. k/ @
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 *// H  c* h2 `+ L! t" E4 E) d
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */& @4 a7 U# N1 d+ q- D
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */6 j- L& d- c! @7 @
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    8 k1 I: |4 I& a0 f" I- f
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */
    # t. G  s; J: ]. y
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    5 N2 [% j) y$ n2 u0 h2 P
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */
    / N& f9 F  _/ q0 l7 x) N9 \% z% ?* L
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */
    9 E; i( m! |0 Y9 K( u6 }) y
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */
    ; N" l$ E1 b, e( F

  20. 0 R3 {5 j# \% k0 R% \5 }' ^' Y$ `' u) a
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)$ C2 u. M) n0 M& Q6 B; I4 u% A
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);/ L7 A: h5 ~( ]& Y5 B) C
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    : S- T1 z$ `% K
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);: b, c+ [. V" @8 N& ^5 i
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);
    . A$ t: |3 `* c6 F: W0 t9 X
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);
    7 v8 m% _& A; L  F
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);: J6 w* S6 ^# y2 L  Y4 x, Y
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    3 ~+ ]$ [- b0 r% W1 {7 s
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);2 M' v* P4 Y/ }0 d- v0 u
  30. #if (USE_SD_TRANSCEIVER != 0U)7 p# T9 c1 o0 m3 x1 V. t
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);
    7 T4 g6 }9 \9 C# ~& m
  32. #endif /* USE_SD_TRANSCEIVER */
    5 o2 t% D& A7 o+ T5 |6 i! @
  33. , T. N# ^3 i( J- c5 I! U" H/ m
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    4 R, v: P2 g" o2 E( C
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);" R: G0 B% F+ p% v9 F4 Q
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    7 Y+ K! I0 ~8 g" u1 R3 t2 n9 |
  37. }SD_HandleTypeDef;
复制代码

. H, `# Q$ A/ y: J& D8 I/ M; C注意事项:
/ K: W- \5 h4 k; A2 t& F
& j( q" u+ \* ]6 Z3 c% {条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
# f: {/ E1 |# V' t4 z7 }: `- n/ z0 V+ z
  #define   USE_HAL_SD_REGISTER_CALLBACKS   1  k$ F; c3 ]0 z" f( r

1 L1 z* s* D# Q通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
* W3 Q+ @/ e; u5 U% x* X% z* i( Q3 E7 _* n/ _# H
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。! C, z/ }# Y8 p9 G

6 t2 S! b- ~. o% B5 C  SD_TypeDef   *Instance
0 ?$ V. W9 V( z9 a% n6 S1 J& w8 r0 T这个参数是寄存器的例化,方便操作寄存器。; J* r' y* O" g7 b8 b" ]5 c

& K6 ?' s2 D, ~* G& ?/ _8 Q3 E  SD_InitTypeDef  Init2 j+ K6 [0 x' W* q6 b, P
这个参数在本章节3.2小节已经进行了详细说明。/ k5 N  ~" [5 X' _+ K& h/ A9 ~1 D' {
6 O, p+ y. K- X5 ~' j3 y" I4 g
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c& [$ |0 `2 l, Z: T; k/ z2 x1 [" t
此文件涉及到的函数较多,这里把几个常用的函数做个说明:, C% E/ E2 D- n8 @9 N

5 V, z, e' B+ P+ ]  HAL_SD_Init4 ?' a! s' f4 `; T# W2 |* s
  HAL_SD_DeInit
* u( h* _( C9 q; p7 F: |- A; v% ^% e  HAL_SD_ReadBlocks
. N, T8 U. i8 i1 f% u$ {" {4 [  HAL_SD_WriteBlocks
8 q  E- r( ]# h3 b  r  HAL_SD_ReadBlocks_DMA
- d9 {" B, z- Z  HAL_SD_WriteBlocks_DMA! d4 s, I7 Y; D  I
  HAL_SD_Erase
* _. X2 \5 U- ~5 x( E  u, n87.4.1 函数HAL_SD_Init
4 y' @5 L4 F6 [6 d' g+ _函数原型:
! _$ {. S) K. ?: Z4 n7 ]
3 g! ^# y9 y0 P4 ?1 [
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    : ?+ e# z, z) u: a3 a3 j: H
  2. {
    . r& q; t& g5 M8 B, k  @# t
  3.   HAL_SD_CardStatusTypeDef CardStatus;7 v7 S0 l$ i/ C( E
  4.   uint32_t speedgrade, unitsize;
    1 \& [7 n& n- k' C
  5.   uint32_t tickstart;3 M$ @! ^# p6 z0 T4 K9 E6 S

  6. # b2 j" _( K/ o
  7.   /* 检查句柄是否有效 */
    5 H0 ]2 U! }% X3 j- B8 Z
  8.   if(hsd == NULL)
    $ q( i& T: W4 }( J! {+ h
  9.   {0 V  ^* c  v! z% l* D! G
  10.     return HAL_ERROR;
    1 [0 T- f" }' a( X. Q7 L3 K
  11.   }& S+ t; q. p$ @; S7 B2 t* I
  12. 2 d" C; \( |) I0 Q
  13.   /* 检查参数 */
    4 ]/ C4 D" S/ B0 e% h
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));2 u. |8 y) I) V/ w, `6 j* I: Y
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));, ~" z  s2 H+ Y; a
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
    ( t2 ~4 j: U/ }; @2 K5 Y
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    ; r& Y/ e: |* M! u- B5 `' H
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));! S7 J7 D5 b  M
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));5 q! J6 Y, c1 f/ s5 V3 r, J6 F$ i

  20. 2 C4 [4 Y! m5 v9 F
  21.   if(hsd->State == HAL_SD_STATE_RESET)
    ! b' I+ U0 `( @1 x$ Z
  22.   {
    2 C) {5 a8 p& d0 Q. k( M
  23.     /* 开锁 */
    1 e+ M7 u  z- k" D
  24.     hsd->Lock = HAL_UNLOCKED;4 i# o3 ]9 h5 T$ {- T$ r- K9 T1 r) R

  25. 2 r! ]4 {* Q; ]: J% F3 c% ~% n$ H
  26. #if (USE_SD_TRANSCEIVER != 0U)
    " A% y  C# ?7 I  t
  27.     /* 兼容 */
    8 w& u% {$ J7 S1 G$ q
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
    - z: s5 A  N/ z
  29.     {
      k  q2 g& n! \* w1 d! p' m
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;" E! r+ ?+ K6 i) L3 y/ T: N
  31.     }
    ! ^; A" ?8 ]! a' f
  32. #endif" E0 @" `8 P$ G
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    0 _. e1 Y$ T% e3 e& C5 O
  34.     /* 复位回调 */
    : J8 h# w! S) f' z7 Q& l+ v/ t
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    : ^4 G+ C  n7 d, J4 v- g9 l
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;" \2 Z7 S1 j* F4 U. Y4 z
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;' W+ y. s5 m0 {! @
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    ! m+ e5 ^' `- }$ `
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    4 a# p+ V, t( N; N2 ?1 m  D2 o3 I
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;
    + B' K8 }% ^& c3 [$ U
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;, Z5 z! T1 u& J0 F( R! q- S8 N
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    - l+ _- W  i% v0 ?
  43. #if (USE_SD_TRANSCEIVER != 0U)
    ( @& a, j, |" x0 k% k# @
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    5 g- C- l8 ~, b$ _* ?2 j
  45.     {; n. n! h3 O  B. W" V" e# ~6 @
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;6 d0 T' V, J- k& @8 h! Q! X! P
  47.     }: Z8 O+ w7 S' [$ B5 y
  48. #endif + v3 S2 Y: p1 P6 N, k3 s

  49. # j7 d' `) A& D0 {
  50.     if(hsd->MspInitCallback == NULL)
    ' A6 u" v6 ^4 m' E* t7 M7 f# ?
  51.     {
    , |3 d' Y! p$ S6 F+ x
  52.       hsd->MspInitCallback = HAL_SD_MspInit;, O( c9 h5 I) v) f- N7 f$ {! S5 W
  53.     }
    + C6 A' |$ I+ d  X" A

  54. * W3 j1 v# E* f7 q
  55.     /* 初始化底层 */6 V7 o# v  U3 l/ d/ L/ k" c1 Z
  56.     hsd->MspInitCallback(hsd);  _) w& z% d4 E# S! y8 ?
  57. #else
    9 l" u/ E5 h* `2 t1 T6 p
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */$ w/ y3 ~+ u/ b. j) m
  59.     HAL_SD_MspInit(hsd);! g3 ~6 z" |: v
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */8 _3 Q/ O7 T) s3 x! T  V( A
  61.   }
    % g4 ]$ f# {. G* N( U

  62. * a/ T; d+ O' ], d4 x8 W7 g! L
  63.   hsd->State = HAL_SD_STATE_BUSY;% _* h, B% b, j9 _9 e
  64. 3 ]+ E& i: N0 W/ O
  65.   /* 初始化卡参数 */
    $ ^1 E% B& N# P
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    9 Y, y, {& o1 v" H; w
  67.   {4 ]3 ?' y; H+ m3 t% a: m; h) @) j
  68.     return HAL_ERROR;
    : y$ H" J2 |2 b3 h, O, g
  69.   }' ^; z3 R) Q& M# k0 g: n4 `+ D3 t

  70.   K! Y. q+ f# H4 Y- H
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
    2 S0 W  ]$ y5 W7 j. }# H! O1 S9 D
  72.   {/ \0 L, A+ P( y* G& S5 R
  73.     return HAL_ERROR;, H& o3 P! h1 `- L
  74.   }) G$ J) G! N# h: o7 B
  75.   /* 获取卡速度等信息 */
    " {) Q* ?! r( S% N, M3 f/ {/ K
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    * i' r6 z6 v2 X+ |
  77.   unitsize = CardStatus.UhsAllocationUnitSize;
    , u: r9 j8 V2 A
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
    # Q; ^4 @% k0 V+ _
  79.   {
    9 v/ N  V! M- m& l% u& \5 R7 o- Z% D
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;& U' \8 D3 V8 u2 e
  81.   }
    ' L$ G6 q0 ]4 i* E  g( G5 `. o
  82.   else
    ; O" n1 d0 W6 X. x* n
  83.   {5 B0 d' u' h. F9 M  g5 s9 n4 _
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
    / ^& d& D3 u0 r& w, N
  85.     {0 `) ~) i3 `8 r5 I- i
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    / P, @+ e: g3 `0 i- p7 y& t
  87.     }! J7 h& [% j; K
  88.     else9 D9 m0 o9 }  f; ?
  89.     {8 z1 U- w% ?  v
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;
    1 |# X3 ?2 A8 k, F4 E
  91.     }
    * v0 ~: S/ f; C4 s6 ^

  92. 6 Q9 S  W  A4 A* \: Q: \9 `
  93.   }
    ) ^; K8 U6 T3 ]: P8 s% G
  94.   /* 配置总线位宽 */8 _9 G5 E" _. @! T4 L
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
    0 @+ E6 f$ w' Q2 W  |/ ]! K
  96.   {
    % W) w* v2 `2 N+ q7 l, _* _
  97.     return HAL_ERROR;& X( M9 s5 [( J' p) U
  98.   }5 M0 l' s3 L4 O6 O
  99. 3 ~* w$ c8 D: ?. z# K" F; O
  100.   /* 验证卡初始化后是否就绪 */
    2 `) w7 M- v( v% u6 c, j& C1 N! A: d
  101.   tickstart = HAL_GetTick();! l( u" l4 z* ^" C- }0 T" Q; m4 X# q
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
    0 |- Z$ g0 E6 O4 p. _' ^
  103.   {4 N( s* N4 @4 ?  z
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    5 ?3 M0 x  E# a" R$ _( L: V
  105.     {
    7 ?4 }% n9 `% F1 k9 _
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
    / q1 Y, g8 `' b, h* S7 @$ P
  107.       hsd->State= HAL_SD_STATE_READY;
    0 }  B9 B$ s4 d% G9 _7 L' q' N
  108.       return HAL_TIMEOUT;
    " x3 T1 Y1 U. W1 f7 n
  109.     }
    . {$ }. n0 w2 _0 C
  110.   }
    . M( c4 U3 y+ y2 N$ b

  111. / v! m! L- I5 B- v. h, U
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;! @+ Z- O" R4 l/ V$ ~
  113. 6 x( V0 f4 T8 f7 @4 R2 l, e8 s
  114.   hsd->Context = SD_CONTEXT_NONE;
    ; Y/ j" ^: k+ A% u8 y) B

  115. % B+ N1 N) x, [. Y# E+ {
  116.   hsd->State = HAL_SD_STATE_READY;/ J4 \& \9 a8 i; Q

  117. # ~' H$ _& T+ D7 u7 G! l" _; f3 @
  118.   return HAL_OK;
    " u0 j, J$ N! o8 e% C
  119. }
复制代码
' b) C+ Q4 M( u4 d& X$ f6 I
函数描述:4 E2 V& P; y8 @. Y/ v/ P0 b

. p% h& i/ {$ B8 N此函数用于初始化SD卡。
# g5 d2 p+ I5 g% T: a3 u0 u" g. x' }
函数参数:( j6 X8 A7 e& F, `8 A4 s) l) V: t
* j1 D- z+ [: H* x5 @
  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。: E7 }/ p) A5 m5 o1 o9 n/ `% J
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。$ t5 k) |" S; h  n& n) V( I
注意事项:" ]5 Y5 [7 X0 C- f  ^
* Y3 x) l; K1 ~' K- F; M
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
; E, `# _7 a# n1 Z' P# K8 {如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。. }% v6 i0 E1 J; J  }
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。
; a0 X% A& K% O5 m, g* s; F$ h
0 X8 l0 }$ i. o6 o6 e解决办法有三
# V$ V7 n% A1 G. R; S& N7 y- M! R9 m2 L" e9 N
方法1:用户自己初始化SD和涉及到的GPIO等。: \) A2 h  F* ]9 G( R
! x/ L" Z( k- f
方法2:定义SD_HandleTypeDef SdHandle为全局变量。
1 M: b+ I6 U. }( b* o2 V: Z" @0 {2 ~3 q) K4 V
方法3:下面的方法" o: [' v. L' {4 }: j
& v7 U3 x- V, d" g
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)+ K$ t2 W7 _  S( U$ P2 x7 u5 q, p
  2. {; y+ A- l7 Y* L
  3.     Error_Handler();7 C  ~6 g* l. ^4 x: v% I
  4. }  # {$ L3 I6 @2 b. i
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)
    ) i8 l/ J; A3 m2 Z4 |7 C, `
  6. {- x' X5 A5 J0 {  A  F" U
  7.     Error_Handler();9 y: E1 v* l4 n, {
  8. }
复制代码

9 R6 b. W# U, F使用举例:- \/ E2 j& ~7 p& {* U* O7 g4 e. ~6 Z

  K/ l- i8 u9 e5 `! g
  1. SD_HandleTypeDef uSdHandle;( |* o% l5 e) v. w# f. G, f
  2. , s9 S4 |# k3 ^) d7 |* H( n/ }/ w
  3. uSdHandle.Instance = SDMMC1;% m7 M4 W+ ~+ w# J
  4. % O- |4 M$ ]1 \7 ?4 c$ G9 [" j
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
    ! f# l0 T3 s9 a9 c3 D2 J" B
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].0 f7 k6 ?  A9 G+ C( D
  7.      200MHz / (2*2) = 50MHz2 v4 a  u2 B2 |" Y
  8. */
    + k* e( y0 o  t
  9. uSdHandle.Init.ClockDiv            = 2;
    ' d0 z: d, l- e. U. S
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    4 v8 f) D- L# w1 j1 \: c/ u" l
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
    1 t, Z8 i5 A( d$ Z6 R( m7 Y6 h: b  b
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    + Z4 ]/ s: t7 Y! q: n# z
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;4 v: f3 e+ B& @) h6 ?
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)
    6 k: W9 r/ g7 ]8 c  s4 e/ b9 }
  15. {; l# a) n7 p0 T$ C, K
  16.    sd_state = MSD_ERROR;
    # E2 g" Q8 ?" e$ g" j5 V) w
  17. }
复制代码

9 R% W3 x2 o8 V/ d9 ?5 x% n3 B87.4.2 函数HAL_SD_DeInit" [# G, }/ M7 I3 Y- D3 ]3 v1 F& \& a
函数原型:/ R/ E1 i" w: R; q# @# b& z5 r) |

7 N1 P5 g5 \- b$ v' D8 M8 e) l
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)5 l* i, @. n2 |. A
  2. {9 p2 I" }2 r# q: R' i% _+ x2 S
  3.   /* 检查SD卡句柄是否有效 */
    $ t8 U" y) |' G; {. [0 [
  4.   if(hsd == NULL)# L7 F* }5 h& ?: s  g7 m0 |6 d
  5.   {- L) {5 m, z3 I; {0 O7 ~+ u& x) m
  6.     return HAL_ERROR;
    # V( v- e2 W& E5 D% D3 B
  7.   }3 C; Q5 @5 H: J. o6 S5 j, v2 H
  8. - F/ L1 {$ A# L# y/ u
  9.   /* 检查参数 */6 L) @* v' z9 M" z9 u% b. L1 A
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    * \( q/ {8 G8 z. f9 J7 u. o6 x
  11. 9 O* B0 P4 S5 f
  12.   hsd->State = HAL_SD_STATE_BUSY;& w5 g- O# |) }$ _3 E
  13. - N- R4 u. }& S% P, e0 t4 x) Y
  14. #if (USE_SD_TRANSCEIVER != 0U)* c/ L2 X* v- A
  15.   /* 关闭1.8V模式 */
    8 [: B6 J8 q& I7 L0 C+ G
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    2 J5 \& |  o/ F* t4 }) ^* U: x
  17.   {
    % k& c$ J: t$ a9 K: }* W" y
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)+ y2 [2 s" w8 E
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)9 ~* ?6 N' y- q$ F
  20.     {) }8 X0 J. ?+ c* Z/ j& Y
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;6 P& p) t, V: z1 K& V2 |. I
  22.     }# w& m1 Q7 E& X6 y
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);# u+ l$ Q6 S! y
  24. #else
    " x- E$ m% J1 M8 K* a
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);. k7 j) ?  q& p9 o1 A
  26. #endif 9 s3 C& c' g3 Z3 e
  27.   }                                                                         4 a- U/ L2 `# v
  28. #endif/ {8 F& G3 Q4 i7 v: f* E# B
  29. : |4 X- U7 ^, Q# K! F
  30.   /* 关闭SD卡电源 */  d* ]. q8 {* b3 s' B) A5 Q4 p
  31.   SD_PowerOFF(hsd);3 e0 x% p  h& a8 H4 q
  32. ' t- W* b: c# g) Q
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    8 |7 m8 m8 X; z5 D
  34.   if(hsd->MspDeInitCallback == NULL)
    1 U! l& J' l1 g; h
  35.   {
    ) l# F# }* ~  E* v: \" C
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;
    ( u3 R3 J2 ]3 H2 |
  37.   }
    * k4 o& m; `% ?# {
  38. 9 w5 y0 j) m" F& O1 \- x9 {
  39.   /* 复位底层硬件 */' ]! {" g8 @5 w: H& v- u
  40.   hsd->MspDeInitCallback(hsd);
    ) \+ P: f2 v7 t5 ^2 E( w
  41. #else
    " X2 K+ M# S7 [' X
  42.   /* 复位底层硬件 */
    & M& v# w7 N6 _6 ]- R3 O
  43.   HAL_SD_MspDeInit(hsd);
    . `& `0 w2 ~+ Y2 b/ `
  44. #endif 4 P$ \! h# h( \4 l/ D) E9 L

  45. * k* J; v7 }0 u7 n! c/ F: s; e
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;# p/ `5 l# p5 ]1 S- R4 K; v
  47.   hsd->State = HAL_SD_STATE_RESET;( ^* b- S8 ~" y' B  P* f
  48. # A" ?  O2 s; {$ h9 t. F
  49.   return HAL_OK;
    + i, F# e5 }) `( s
  50. }
复制代码
! S. |; S0 i9 o. n+ u2 ^. N
函数描述:. ?/ G$ g% B7 w9 I2 A

% F3 T/ o* x, X2 A( E9 P用于复位SD总线初始化。
2 O: Q% c1 H; X) E( t! l
* f2 E! \! A6 T  p$ J函数参数:( c* m9 i1 c5 X6 T7 k
( m! r! `% ]& m" y6 r& B
第1个参数是SD_HandleTypeDef类型结构体指针变量。
1 |; \5 W: w- u& N9 d! q  U# z6 x 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。: S# m( d$ ]0 M( ^0 h- ]
87.4.3 函数HAL_SD_ReadBlocks
' k9 x" E$ k( M# Y函数原型:
) k8 x4 }- c5 P. s7 \7 c
0 k% A1 W& ?5 T% L: U/ l& w
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)  u! E# i7 h3 b; W
  2. {+ b; E# J) ~3 A- g2 b0 _
  3.   SDMMC_DataInitTypeDef config;
    : B: l7 o4 S% c) B- h* Y9 O
  4.   uint32_t errorstate;$ v& S# ~, W! I
  5.   uint32_t tickstart = HAL_GetTick();
    ( u* R* t/ M) ]4 C) s  w
  6.   uint32_t count, data, dataremaining;
    8 p( [- H, R+ b& s1 `3 B- I# M7 P
  7.   uint32_t add = BlockAdd;9 y5 v. P$ m. R
  8.   uint8_t *tempbuff = pData;
    / ?8 U  i2 ~- t1 Y, _: h
  9. : j6 Y/ J! o$ e) |  h+ O( `: v
  10.   if(NULL == pData)
    , b& ^# H3 L3 x7 X: Y! A
  11.   {
    5 f5 P6 {7 ^: A! ^- a
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    " v1 K; q6 V6 `  f
  13.     return HAL_ERROR;
    * s& [3 s9 y4 Y. A& g1 n
  14.   }+ Z( r4 n4 ?1 z" s/ J3 h

  15. , s6 N' F0 G8 L0 ?7 p4 Z
  16.   if(hsd->State == HAL_SD_STATE_READY)
    ( V. E$ j; ^$ m: C7 |
  17.   {4 g  L7 m0 f3 n1 T% {" j
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    : y0 G4 P) W' U0 S' \; `4 M

  19. % ]1 u1 }4 v: b( j6 ^% K
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    ( H( ]8 }# L  L" J
  21.     {
    6 M; E7 ]! o; M6 N7 E
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;: m+ a3 l3 |/ y: ~! m) Q5 e
  23.       return HAL_ERROR;
    . F) K$ A% J: ~, H$ T( f2 Z  g$ H
  24.     }: E% Z) K; }! K; A0 p8 @+ k
  25. ' @8 s' s0 U) `! G
  26.     hsd->State = HAL_SD_STATE_BUSY;
    ( w3 n6 `1 M, P5 T1 }; `/ k& l
  27. 7 s8 o! i2 b! M
  28.     /* 初始化数据控制寄存器 */
      L+ s. h* k8 b, w
  29.     hsd->Instance->DCTRL = 0U;
    1 V' ]: S9 A4 r

  30. ! j: {5 b3 ?4 x; S  }0 j
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)  @; |' c5 \: p2 `
  32.     {4 ]7 U7 y0 S1 P2 ^
  33.       add *= 512U;
    4 s- R, Z' l8 A( ~5 a9 N# r  w
  34.     }
    4 O2 K2 E6 U2 S+ u7 J* }5 j- [
  35. + e0 [0 D9 Q8 @8 Y7 O3 {" T
  36.     /* 配置SD DPSM (Data Path State Machine) */9 {( M6 {* @: X& G
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    1 i8 l4 `5 i/ n: W1 W/ {! E7 g
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    8 Q* z% W0 d# D4 G! [- M# {
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    " W0 A5 _) W! p! K
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;% c7 T+ b1 [8 m& e
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    ) u6 k" S. V1 A1 r7 E2 u1 j
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;; v5 [  H2 V5 V- ~* i" _. g
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    - N, u" T8 s0 c% z* l9 a+ S1 u
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);/ F% A2 G: Q* {
  45. ( H) q$ s; {  o
  46.     /* 查询方式块读取 */
    " x4 P- [8 K5 q; a5 @( H
  47.     if(NumberOfBlocks > 1U)
    ' E5 N% L& i: A+ N
  48.     {- i* }( ]3 ~2 r. l) F
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
    7 H) R" ~, s6 g( n1 R

  50.   z5 `# V& O7 v0 S1 U+ g! q4 r
  51.       /* 多块读取命令 */! H9 r* D+ D% s' q0 y
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);. c0 Q& u, E" [2 X
  53.     }
    " f; @3 K' Q% z7 b3 D# w( x4 s
  54.     else
      t2 M- d6 K& r7 _' f
  55.     {
    * b6 q2 k6 ?9 f5 n" ^  k
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;% A  ?+ }8 E0 T4 h) Z

  57.   J, _' }. C# S$ n! ?: R& u4 s
  58.       /* 单块读取命令 */
    + q0 _6 Z& D7 x" ?& `
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    3 g. M& G3 p# H: f
  60.     }/ y; Y' E% K4 e- X) Z
  61.     if(errorstate != HAL_SD_ERROR_NONE)$ ]% Z5 D. K; L; B* y1 I+ g6 B
  62.     {
    * [% V& w! {7 v& R+ w
  63.       /* 清除所有静态标志 */2 V' B6 w7 b+ x  Q- x4 b6 e7 X
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: f, l# z8 S/ D* N5 X' _
  65.       hsd->ErrorCode |= errorstate;
      b5 L& o5 B2 r2 }9 G
  66.       hsd->State = HAL_SD_STATE_READY;
    " ?0 g5 e. t0 j/ p. X+ |8 Z
  67.       hsd->Context = SD_CONTEXT_NONE;
    # j9 y) w$ x$ K5 m+ s4 X" I
  68.       return HAL_ERROR;6 @& ?1 q7 z( V* e, Q; p
  69.     }) d2 Y4 Z' S+ L* g% g

  70. ! m1 N9 `6 k; S9 }' G6 p. O% h
  71.     /* 查询SDMMC标志 */
    % {$ n" ^: c1 I$ s
  72.     dataremaining = config.DataLength;
    : ^! Y' U; W; s: d) f9 }
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    ( I5 S+ |3 p! ~3 Q) n
  74.     {/ w! d. f" f9 p% ]  d) i1 W
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    ' i6 x0 \, a$ \9 y
  76.       {3 J, _) r" w0 e
  77.         /* 从SDMMC Rx FIFO读取数据 */
    8 w! p" t( d& w. ?- d
  78.         for(count = 0U; count < 8U; count++)
      J$ Z/ `, T% r* E8 I& A
  79.         {
    . O/ n. H2 s5 c1 ]  M
  80.           data = SDMMC_ReadFIFO(hsd->Instance);+ [: J) F0 Y( x0 E
  81.           *tempbuff = (uint8_t)(data & 0xFFU);
    % ^& B( u0 `+ H' z& d
  82.           tempbuff++;
    2 P7 j' d* O8 m, m8 E$ S7 o
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);0 Y" ], H$ k+ i+ s6 m3 j* h
  84.           tempbuff++;
    2 d# b+ B% m& }9 `8 V4 d- y
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
    0 Q  F: W+ p- ^  o8 |1 }/ t& m8 W. l, T
  86.           tempbuff++;
    7 L3 R- E) Z, k3 h+ x) z3 {
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
    / k9 P9 t5 s; z% u9 M% Y! t) u
  88.           tempbuff++;
    7 W4 H) A; f6 V! J
  89.         }" A% C1 y9 c* o( u7 M" F! r. c; I
  90.         dataremaining -= 32U;! q0 B& c' z2 x- W; R2 k2 e
  91.       }
    9 h( D7 f8 u4 ~7 l5 a) B6 ?  f3 F
  92. " Q$ M& p/ R# k# C8 b) f
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    - a: p& n& b& A% ^1 c
  94.       {
    / g8 J* u8 T, |1 c3 X! N
  95.         /* 清除所有静态标志 */1 ]# S/ n0 s9 N, Y
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);4 E) w! B& o1 k5 l
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
    & h. S! f4 v' ?4 h9 V' _
  98.         hsd->State= HAL_SD_STATE_READY;
    7 o  g7 h# O& k* Y: y
  99.         hsd->Context = SD_CONTEXT_NONE;; P% t; K! ]" O" O. H
  100.         return HAL_TIMEOUT;7 [+ o0 i/ b0 i5 q1 @
  101.       }. |; V. V/ `, ^/ i& v
  102.     }
    3 P2 U' V: v' ?; Q6 L* O$ ~5 k( V
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);( o+ d  D0 c# q+ C( C+ x# ~
  104. 3 U: t% x! I4 Q6 b+ H- E  p
  105.     /* 多块读取发送停止传输命令 */
    3 D) F( |2 e2 e8 t5 m4 X9 d
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    % Z& g: E' k2 i  l& x. Y$ [7 ]) F
  107.     {
    ! X+ R$ I' X+ z/ U
  108.       if(hsd->SdCard.CardType != CARD_SECURED)5 e' F# R$ H4 [" ?. V
  109.       {& C& B% {# H( C) t" s- ?8 ?& w
  110.         /* 发送停止传输命令 */
    9 j- I0 O0 _6 B2 L  K3 N7 M% f" y% A3 K
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);5 @6 U+ D( T% g
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    0 U1 F9 L) D& z# c( d
  113.         {% D) a+ L( Y9 d
  114.           /* 清除所有静态标志 */; |( v7 \- b5 j0 |# E: W1 C
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: x( M% {. E, q0 N
  116.           hsd->ErrorCode |= errorstate;
    3 Y, G7 W8 c/ Z  i! z  W
  117.           hsd->State = HAL_SD_STATE_READY;
    % C: U( j2 k. V) g5 L" t9 G
  118.           hsd->Context = SD_CONTEXT_NONE;
    ' ~+ Q. D) i( {" |' B
  119.           return HAL_ERROR;+ W/ w1 U* O/ J/ [: g
  120.         }' Q7 }' X: g3 g& B7 n" }
  121.       }7 C) g& j, F: ~0 V# R2 N, i0 u
  122.     }/ f9 }' K/ v! k9 q
  123. # b; f3 Y$ H$ N* R4 U, C
  124.     /* 获取错误状态 */" n4 G! c8 e$ I4 d# X  @3 m( A5 H% K4 g
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    ( S- a! P- Q4 Q. D( u$ d5 B
  126.     {
    / v2 c& M$ P3 w) \: _, C
  127.       /* 清除所有静态标志 */
    5 L2 d1 Z9 u* B7 @7 O
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);6 G' X* }) T5 ], Q; u9 I2 s! v
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    5 o  w8 f# d+ A& R# ^
  130.       hsd->State = HAL_SD_STATE_READY;9 d+ C$ d6 W; B) [2 A
  131.       hsd->Context = SD_CONTEXT_NONE;8 @% _8 V) Z+ x7 u
  132.       return HAL_ERROR;7 S7 m1 Z0 d. f! D
  133.     }
    0 q7 r$ V# P6 ?! h( ]0 l; Q
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
    & F4 Z0 |2 S) W) P7 X' B
  135.     {
    ! L8 l2 D. J2 K* i2 H
  136.       /* 清除所有静态标志 */
    7 H' a3 W0 }0 F7 L3 W" k1 {9 S
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    2 U' K3 c5 @+ V
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
    / Y$ q. b" d0 i
  139.       hsd->State = HAL_SD_STATE_READY;
    9 t8 t9 \/ e: ~
  140.       hsd->Context = SD_CONTEXT_NONE;  h/ H! x; {& Z( E$ y
  141.       return HAL_ERROR;
    6 L0 x; m4 V/ a4 d
  142.     }7 t# {7 }8 R- m# f7 U$ h% z- F
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    . P$ v" u5 w% w
  144.     {
    8 {' i+ o  F, X. s8 ^7 Q2 Q+ R- j
  145.       /* 清除所有静态标志 */
    8 q( a- q3 `! Y1 n
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" y; H8 N# L' D
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
    4 J$ N; L6 E! `' G! D4 J' `
  148.       hsd->State = HAL_SD_STATE_READY;3 Q! ^$ N4 j8 @1 L) p
  149.       hsd->Context = SD_CONTEXT_NONE;
    8 Q, p& }5 w2 ^
  150.       return HAL_ERROR;. w2 _1 _* }6 \# [
  151.     }  \4 ?1 n# N) v* h* ]
  152.     else0 `+ M8 l: k7 e0 T/ C7 N  u
  153.     {
    5 K( M8 `: o! i) S! P4 a. R; @, Y
  154.       /* 什么都不做 */5 O! y3 h' R0 g5 X
  155.     }
    ! g6 r8 t) d- t. |8 v5 T& F
  156. , \/ I, M8 `; E& N5 A  v: l
  157.     /* 清除所有静态标志 */" y3 n# _" a4 C  B6 }
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);7 Y: E! N( G2 H1 a2 f& y- x
  159. $ ^* n' K+ @9 @7 s
  160.     hsd->State = HAL_SD_STATE_READY;
    ' V, P3 M; k% n7 q: K3 i

  161. 8 X- h5 C3 o' \; x( r4 S8 K
  162.     return HAL_OK;
    / y+ Z5 ~/ k4 U1 ]
  163.   }
    / \, Z3 [4 {$ J2 d' h
  164.   else
    " l4 L6 i  {8 g7 E* V( p; ^
  165.   {
    4 v3 E2 v& d. v
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    7 Q, B! `0 _7 J% k6 @, ^  O: z
  167.     return HAL_ERROR;
    5 \$ J# }  J" G( c
  168.   }$ G% \, M8 [7 k' g) F, e
  169. }
复制代码
' p* K) r+ W  L; z! s6 k
函数描述:( y6 F# p  ^$ ^. O, N! ?! h

/ {. p) D) [% J7 o0 P$ d此函数主要用于SD卡数据读取。
" }' H# N3 U3 g2 W( X' |+ _( L% k  v: B! m
函数参数:
) l+ Y  N/ A8 Q
& a9 O. D- |! x5 C+ R  第1个参数是SD_HandleTypeDef类型结构体指针变量。5 K1 b3 S5 K. }
  第2个参数是接收数据的缓冲地址。; r' N" f+ d5 u' Q/ ?9 T
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
9 S, D1 d* x# @/ H" [4 A  第4个参数是读取的扇区数。( V/ D0 g! ^8 b6 z5 ~4 @7 p) e) x0 H
  第5个参数是传输过程的溢出时间,单位ms。
% b( h* b$ U  m& R: n  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。# F9 ~: b# c8 C0 P
使用举例:
: J6 {- _, @/ j0 h
" o, W6 z( v$ W* [, `
  1. /**9 p: b" u' ], k! `. Q  [9 _
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
      }4 e- \, z! }1 t: B% g& v
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit
    5 t0 F! ^& a, A7 W6 N
  4.   * @param  ReadAddr: Address from where data is to be read
    : Z" a* d' A. S- P4 R5 {
  5.   * @param  NumOfBlocks: Number of SD blocks to read1 w9 o% Q7 V- u6 K# g
  6.   * @param  Timeout: Timeout for read operation8 O0 g5 R# G3 ^# l- n
  7.   * @retval SD status7 {1 \) o. D4 e6 b. r; P' Q
  8.   */
    : ^' f. n* q) T/ e, V! R) q( X
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)& `2 u* e) l5 u: R
  10. {9 _( |2 c" u3 _/ |  l) R5 c7 G

  11. ( x# N. M4 u  ~  z# U. ^/ G( O
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)/ A) G7 u. E( f7 N' O
  13.   {
    ! r  v0 }; t# ]. s. o
  14.     return MSD_OK;
    ! l( I# C* @+ r7 I: u' V2 F4 y1 \
  15.   }
    0 A+ M! Y# I6 w, t, r
  16.   else& c: Y0 R9 j4 _; j, ^# f
  17.   {+ d( o) }! w7 p! @
  18.     return MSD_ERROR;% j: g, Y8 \2 M/ P. E
  19.   }5 F, A4 \5 `8 B0 N6 `
  20. * G8 R7 T1 J) f9 {9 T5 @5 U4 l
  21. }
复制代码

! F9 T" m- R$ D6 X% t- G87.4.4 函数HAL_SD_WriteBlocks+ }. T3 t9 I! T2 j$ M; S
函数原型:4 Z/ s3 F, b0 f( B: o4 |8 Y

7 g0 \  }( i& v$ F  @/ x
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)% n: n/ Q. K  L3 |, p
  2. {
    ' P" h9 \6 Q* }
  3.   SDMMC_DataInitTypeDef config;
    8 B7 h& W- ?9 Y/ Z/ C% V
  4.   uint32_t errorstate;
    8 C& z! ~* l2 a. l, U2 V! s
  5.   uint32_t tickstart = HAL_GetTick();1 Y$ b5 B# N* y4 T
  6.   uint32_t count, data, dataremaining;
    1 c* L. ?  R2 Z
  7.   uint32_t add = BlockAdd;
    8 F9 z4 I) e. G5 d* w" D
  8.   uint8_t *tempbuff = pData;
    1 e) G4 G" `% t
  9. / m5 @! U3 _2 j' j# r
  10.   if(NULL == pData)
    4 `9 N$ P7 z" T' f7 L6 U
  11.   {. r/ [# d3 H/ K# G8 Y& W
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;  P, G7 O7 E( @
  13.     return HAL_ERROR;$ P, p; Z0 ?  k4 ^# X! Y
  14.   }' f' V& G2 i) m, e; O2 I; p

  15. % }# O: q& `8 i
  16.   if(hsd->State == HAL_SD_STATE_READY)% f' b* i9 m! N+ V5 m
  17.   {
    ' ^' T' ^# @& ^6 O- |
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;) S% ]& N6 b# k0 y6 y5 W

  19. 3 y! x1 }- w5 U1 |
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    + ?; x* C4 M0 G1 Y0 Q
  21.     {
      w# c& N2 R1 ~$ ]9 Z
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;. @# f+ t  @& h; t: ?+ G
  23.       return HAL_ERROR;
    / i' \# S8 t& {  m) k( L) z
  24.     }
    / O: G, k% Q+ ]* u: ?9 K5 o$ d& T0 G

  25. " w: v- @# r( F0 Y+ X2 i! E
  26.     hsd->State = HAL_SD_STATE_BUSY;
    - T/ x7 D- f* T( b
  27. ; G7 B. ^2 J& ~  _
  28.     /* 初始化数据控制寄存器 */
    # P  F4 |0 y* V+ `$ X
  29.     hsd->Instance->DCTRL = 0U;
    1 \$ u% O/ h/ l/ i" l! `3 n

  30. ! x* O& t  O' h( Z  \0 m
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)* j$ M0 w6 X1 T  V* x
  32.     {
    : c3 l& q& _3 K8 r
  33.       add *= 512U;
    ; G9 m' w1 e! Q% i! S4 ~# X
  34.     }! o; u+ h; K2 J: l) u( q) Z
  35. + A: F2 L8 `3 u$ s/ n
  36.     /* 配置SD DPSM */
    ( z$ d1 _4 c' j7 x: U
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;5 L- I- C$ b5 o/ v+ s" D; f
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;" p' I9 ?- G4 V+ y: z, L
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;7 N  O, h; K/ c" s& @
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;- s( a, W% h2 ^8 _' m/ u
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    7 \, _# D: a; _  l
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;* }0 i/ y5 K0 ]$ E7 x6 y1 _! H& O
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);) f% r# e' W3 ]: u
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);& `. i& j* W5 r4 V

  45. - r# x. k7 i+ o! F
  46.     /* 查询方式块写操作 */2 j" V, \- u5 m& ^1 K) w
  47.     if(NumberOfBlocks > 1U)
    ! _5 k/ U) W6 y; B; M; e0 b
  48.     {
    5 u# ^& Q. X% [3 T
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
    ! N# k( R. c9 ^+ Q0 n6 Q; e; j
  50. - x0 M" X7 [( ^
  51.       /* 写多块命令 */& R# [3 _& y2 w3 `/ e
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    # T  _' L  ~  Z2 F8 Y9 V
  53.     }$ v' L& `  f2 i( y0 @& B
  54.     else
    - |9 Q3 L" [$ `- k, g- n
  55.     {
    ! ]5 e% }" r" C7 A7 h* P* L5 U$ Q
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    8 Z" }- _* }1 r& e# a# e  W) M

  57. : @  D$ [+ Y0 \# u3 |* H
  58.       /* 写单块命令 */
    " j0 B0 a% G$ n' T6 e' V- `. `
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);: i1 }8 z& B5 Y2 m  {
  60.     }
    ) A# g! e3 F  I/ w& f8 o+ n# L" X
  61.     if(errorstate != HAL_SD_ERROR_NONE)
    + P3 }, ^0 d& {* w
  62.     {
    9 u" k$ J3 s0 _2 D
  63.       /* 清除所有静态命令 */) {# D! Q3 ^! z
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);5 D$ b/ K# Z+ [7 x. ^! ?, q0 x
  65.       hsd->ErrorCode |= errorstate;
    & V/ W  ^& E; v8 E% b& X: D
  66.       hsd->State = HAL_SD_STATE_READY;
    " _9 W1 u2 `* v9 t. s
  67.       hsd->Context = SD_CONTEXT_NONE;
    9 ?( ~: K) S! i) x' K3 J( j
  68.       return HAL_ERROR;
    6 Z$ m  |1 O, @9 A6 R4 k
  69.     }
    3 Z( G9 k( X1 T8 z5 C

  70. ; I( C# E6 E+ m$ u6 p8 {( T1 p
  71.     /* 查询方式块写操作 */
    2 a3 {1 p: M1 c# n8 C& e' i
  72.     dataremaining = config.DataLength;; G( Y5 m6 M4 v. n7 z% f: Q
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
    2 Z. V9 J2 o: h" O/ f
  74.     {, J( f6 F! P) H1 r" s' _. X0 z
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    ' t/ x, g+ L/ N; V( W* U1 `
  76.       {6 K5 n+ K, J( x
  77.         /* 写数据到SDMMC Tx FIFO */
    ) t' a" _0 `+ O, K& H; Z8 ^3 H# V8 G
  78.         for(count = 0U; count < 8U; count++)$ [- V8 C  ^# G# K+ ]! Y$ j3 ]
  79.         {. U  O6 O" p0 P( j: I+ V
  80.           data = (uint32_t)(*tempbuff);
    % t) r7 m! D3 \8 \4 g' M5 @6 ^
  81.           tempbuff++;
    % j2 j6 Z: p" }( X9 E( z" ]
  82.           data |= ((uint32_t)(*tempbuff) << 8U);& }% y. W+ U4 i
  83.           tempbuff++;
      n2 I6 ?8 ^  n) W6 s1 n! u
  84.           data |= ((uint32_t)(*tempbuff) << 16U);5 d3 K4 [: X$ j: P9 S8 e! h
  85.           tempbuff++;! u/ A" y' P2 i# }4 L
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    7 [& x+ Z7 ]* z& [  N; M
  87.           tempbuff++;* ^$ `) J4 Z3 M% P2 H4 D
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);6 h3 S# ]+ \6 q
  89.         }
    $ i7 q" g' c  p
  90.         dataremaining -= 32U;
    4 v. r; ?" C% D0 L  A  @, l
  91.       }& u" G) j$ d  b' Y
  92. 3 W/ ]5 e+ w+ i  S7 u" Y* Q
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))  f5 A+ k9 i3 ~2 t) N6 d+ J
  94.       {
    # H4 D* m) x" a, K/ m
  95.         /* 清除所有静态标志 */
    9 F- ]6 o# P+ O& T
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; q6 T9 z+ G, ?/ h4 P! g
  97.         hsd->ErrorCode |= errorstate;' F3 r/ `6 R, |8 b1 H9 V
  98.         hsd->State = HAL_SD_STATE_READY;
    ; D% X0 t- b& W6 C* B1 [
  99.         hsd->Context = SD_CONTEXT_NONE;1 G1 e2 h% Q$ X; n
  100.         return HAL_TIMEOUT;' h; w  C, t+ P7 C- J
  101.       }
    : M0 q* s( P$ l" g* V0 |, H
  102.     }) g2 }) x' U1 Y+ h& T; o5 e4 G
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);  E$ d* z% W7 z1 A9 n3 O/ t
  104. & v, X+ O$ m/ `( \9 K& w6 h
  105.     /* 多块写操作,发送停止传输命令 */# A, q( s  @% S6 t. A# p
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))* Y1 v$ }, I" \$ q* j. Q
  107.     {* a& e1 y- Y: Q4 W2 L
  108.       if(hsd->SdCard.CardType != CARD_SECURED)+ T. s* T3 b' P
  109.       {
    ! E6 F7 O' O! z7 ~, h
  110.         /* 发送停止传输命令 */
    7 v% _$ C/ z) X' Y3 u- f
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);8 H+ n" m1 {* T( R; l# w
  112.         if(errorstate != HAL_SD_ERROR_NONE)
    5 t- Y3 r0 Z3 o" n
  113.         {
    1 x/ R7 Y8 C, Z/ Y( ~  K' ^( C5 D
  114.           /* 清除所有静态传输标志 */
    # c2 n+ x& _: O6 V+ B- C0 y
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);; D- t( L7 s5 x, p
  116.           hsd->ErrorCode |= errorstate;2 z( m4 u; y0 y$ U5 w5 C
  117.           hsd->State = HAL_SD_STATE_READY;7 A. w$ y7 ]; I5 G# @4 C
  118.           hsd->Context = SD_CONTEXT_NONE;
    4 C# F  t0 X2 |" m: B6 u3 X
  119.           return HAL_ERROR;- F& T/ @% M: d2 N  F9 }+ a
  120.         }; k3 w- h$ r$ @) d+ D
  121.       }
    & F: h" f; o- e' t  @% T
  122.     }
    ' g/ |1 ?: R. B/ u8 W) Q
  123. % d+ P3 w* B/ z! Q2 b7 N+ n# Q
  124.     /* Get error state */# j. }2 ?7 h' Q2 r) D, u
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))) b5 f6 ^. c3 A: e
  126.     {$ e. W. L' d% v: b) p3 \
  127.       /* 清除所有静态传输标志 */3 Q& t: \. b7 k4 p& _; n
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 D9 t+ W2 \4 W8 U1 c3 J2 `7 q, w
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    7 q$ f& G) v* }- [) W! Y5 Y
  130.       hsd->State = HAL_SD_STATE_READY;7 Z  ^7 H8 v) y6 d; \5 v& [- O
  131.       hsd->Context = SD_CONTEXT_NONE;
    % X4 C, h/ Y% [! g
  132.       return HAL_ERROR;! x; `2 n% Q% ]- o6 X% W
  133.     }% ^2 A1 }# l" O/ K$ h
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))* H2 d+ k4 a/ V
  135.     {: u* {. t( ?/ b8 `% A" T
  136.       /* 清除所有静态传输标志 */
    $ N* E! {- B5 Z
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);0 o# e% c2 k! B) \' u  b* P
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;+ ^( {# |2 n0 Z3 {3 o7 _) t) ^
  139.       hsd->State = HAL_SD_STATE_READY;! x7 }  I! B; W8 s  m
  140.       hsd->Context = SD_CONTEXT_NONE;% h5 }, N! ]4 ?0 Y) Y* Y8 l; z
  141.       return HAL_ERROR;, h5 O/ t( B) g4 z: g) `0 H8 }! _
  142.     }
    1 ^3 ^' T! M: K# u3 b) x4 ?2 \
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))# L. I/ ~5 _8 ?4 {- @* l5 F7 Y
  144.     {
    & x- B2 H- L  J9 N* p1 X' `3 |. h4 P. X
  145.       /* 清除所有静态传输标志 */* R% {3 w8 I$ O( h, `) L$ O. o
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    . |$ V, A% T6 i
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
    - e2 @0 s$ q: w4 t% e) v$ l. p- x
  148.       hsd->State = HAL_SD_STATE_READY;
    8 `. o$ f  Q5 ~1 `
  149.       hsd->Context = SD_CONTEXT_NONE;
      d: ^* B6 I+ G9 |' ]
  150.       return HAL_ERROR;# x) j) `/ r. [5 o( S! r! {
  151.     }
    " e: F: F& m+ T% Z% P
  152.     else
    % V. y, N( T5 A* v4 }3 u/ u/ F' S( D; F
  153.     {/ m: s; p$ e' |9 e
  154.       /* 什么都不做 */
    5 i4 \4 t! Q4 O) f4 ?; Z7 p2 R
  155.     }# M* A5 B9 ]6 Q% ^

  156. ( |# ]8 o+ T! ]
  157.       /* 清除所有静态传输标志 */7 I  R  e; S9 A( `& ]
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);! H! o: s& {, x3 a$ B0 n- W! w8 g

  159. , m- H, S1 B& X( P5 \' [; m# w
  160.     hsd->State = HAL_SD_STATE_READY;3 b6 ?/ L+ S1 L$ N, e2 L2 S3 z% m

  161. , V  n6 n) z* A$ C3 A
  162.     return HAL_OK;8 S' G: c  T) }, A
  163.   }
    4 q: T) n7 Y. C, ~3 O
  164.   else
    0 ^" t( L; c% Q- t
  165.   {
    ; B- Y$ @- W  ^3 I% {3 }1 D
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    7 B: R: z; N. I3 f, L8 m
  167.     return HAL_ERROR;
    & w* D# E& a7 `& t" v, }" L3 X
  168.   }7 A% ~1 k% T7 c1 i
  169. }
复制代码
( u; L- O6 e! k) p! H3 c0 F
函数描述:' S3 u4 \" o- _7 J6 v
! Z- ~6 ]. g" a7 Z
此函数主要用于向SD卡写入数据。, {- I& I/ h- b/ Y! J" r% }8 r
+ i# Z; ?1 h; z; V
函数参数:
! w1 F( p; p4 T1 @  T- A9 c
1 l) {1 p) ^& W! e2 t) q  第1个参数是SD_HandleTypeDef类型结构体指针变量。
/ ?) M1 d6 z4 A0 d6 _  第2个参数是要写入到SD卡的数据缓冲地址。  x% ]- |8 x1 m1 e' r! Z
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。- m+ c2 A. t  J) a
  第4个参数是读取的扇区数。% x$ X% i! h: o8 }! ^9 R) N$ p
  第5个参数是传输过程的溢出时间,单位ms。
3 T* W2 k" g" e% w& z' S  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。: @, a& f. K7 E/ ~) ]: m: q
使用举例:
5 ^# }: u4 l4 Z6 H' `+ z3 y' h1 Z( R' }& o; z# `# U
  1. /**+ ~7 W3 {" N/ S/ T$ j0 z
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode." c' d, `; M" B. \
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit0 P. d2 H6 S3 L; a
  4.   * @param  WriteAddr: Address from where data is to be written! t+ N& c- y/ B8 @: L- K% W& h4 v
  5.   * @param  NumOfBlocks: Number of SD blocks to write/ U: ^* T, Q) q; i6 t
  6.   * @param  Timeout: Timeout for write operation
    : A4 }$ ?: T( o: ~2 e
  7.   * @retval SD status1 H( s8 c, o8 {& q; W3 m0 H5 `: ]
  8.   */3 A7 f" B& S/ t" E5 U1 j3 n1 d
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
    , U( k* p! h9 s' I8 o
  10. {
    + t! B. D4 L+ a0 O+ D
  11. 6 i8 b1 N+ w+ [
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK): n$ r" \9 _2 V5 y# Y
  13.   {/ b% U- @( a$ G, C- B
  14.     return MSD_OK;  j( a# {6 d& h4 Y: P* A
  15.   }
    & I3 ^' m3 G8 N) s  a  t
  16.   else
    3 ]  D' @3 E4 h0 v9 J' c9 f
  17.   {
    - J+ M5 u2 q- C! s5 U, C; t
  18.     return MSD_ERROR;1 @* o# P( i8 G, _+ O; q" A5 x
  19.   }- q! b- K8 ^0 \  v( m0 G
  20. }
复制代码
$ U/ ]& ?. l* y
87.4.5 函数HAL_SD_ReadBlocks_DMA
+ S( O! n+ h; d4 ^2 ^函数原型:# d8 U0 m. h' e0 Z3 c& a; k
1 u# ~" o1 D# r
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    & P2 m! a' m' |
  2. {
    3 W' k* U! l% V' ^' e- ~+ `/ b% l
  3.   SDMMC_DataInitTypeDef config;5 }4 ]5 V1 k* [- k4 N+ L
  4.   uint32_t errorstate;: L' N' p7 S" t3 a- C
  5.   uint32_t add = BlockAdd;2 W+ [4 Q0 o6 A! f' S: s

  6. 0 ?7 X) i; \& c* ]; G
  7.   if(NULL == pData)7 p; ^5 \+ p4 }: i' W
  8.   {8 Y9 U4 Z/ U0 Y* Z& u! h' G
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    1 }. _/ ~6 j. X1 K- z9 s
  10.     return HAL_ERROR;
    ( e. m  y) o; E* s
  11.   }
    % k. @! m- Z5 P& i* |

  12. % q8 u$ ]1 q* A) X5 A+ G6 T, Z
  13.   if(hsd->State == HAL_SD_STATE_READY)  |/ l, x) @1 U9 |, V- m* k
  14.   {" S, B6 b7 K; R( Z1 B
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;: p3 r" X2 Y. ]; ^4 Z- U
  16. + V$ i3 \5 u- Z' |
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))! ?" a0 v% n. o, W6 a& s" [' {0 T
  18.     {
    1 H, }4 L% x  C  T: w
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;1 q! q5 ?. i/ U  T' a
  20.       return HAL_ERROR;% S# J+ X( V0 p2 E" B
  21.     }
    * _) _3 r& {+ f: A* r# H  a

  22.   H1 y& x; b: X/ I' |9 ~" Q' Y( \
  23.     hsd->State = HAL_SD_STATE_BUSY;& H5 ~. n9 x* ^, \) I7 C$ |- |2 @& B
  24. 4 w" K+ e9 T  v- ]
  25.   /* 初始化数据控制寄存器 */( v4 A/ H; H+ ~+ C* k# n% {( F
  26.     hsd->Instance->DCTRL = 0U;
    * o+ t# E1 N1 b( H# w1 b- c
  27. ! q$ ~; B; U$ H& n
  28.     hsd->pRxBuffPtr = pData;. C2 U2 D! }: @1 V; V
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    7 s) D9 i! g8 [9 P& u! \

  30. / B+ u# h/ g& d# b8 r4 F
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC): O6 Z& z) W: ~9 W$ p3 V" J: S. {
  32.     {
    3 o3 Z, E" f+ n( {0 F1 q
  33.       add *= 512U;) v) g* C2 V/ v' J
  34.     }! k6 T4 O0 Q( R3 U7 m
  35. 6 Z7 O: m* w) x+ ^% n+ W
  36.   /* 配置SD DPSM (Data Path State Machine) */
    . J4 P0 }& {2 r; X+ L7 w7 W
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    * X9 f0 p  f/ I
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;( n, \7 M0 `) N# {7 f
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    + N9 o/ i9 U2 Q- ~8 s6 N2 h
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
    8 T+ _  D" b( R& W
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    & ?2 R# p. |. N% ]0 v* ?
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;$ o7 C- P( ?+ M" _$ N6 b. S$ i: _
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);# r* H9 ^% J2 {1 C
  44. 3 ^2 P# Z* {$ X, ], u8 j
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);5 M6 c% @) p; E. b
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    1 [  F- t* n. d6 C& t
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
    . b. ]2 _# y# o7 w' N, N$ t

  48. + R8 w( q# Y, g% V, e/ v7 y
  49.   /* DMA方式读取多个块 */  D6 e- b7 [2 D, W" d
  50.     if(NumberOfBlocks > 1U)6 {8 n% }  T' h7 N* b4 g
  51.     {
    . z. O# z6 c8 t, }. C% w1 E
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);  S* Q. O1 p/ m

  53. + i1 M/ _- x8 I8 [5 L
  54.    /* DMA方式读取多块命令 */
    ' O3 }0 a# Z* Z( G; X
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    + S! f  |: H% d$ I* ]4 v5 M4 s# o
  56.     }4 j3 O9 y3 z9 B, z! f
  57.     else
    ! f+ n: T4 K3 b1 g
  58.     {
    2 ?7 S% M$ w& @7 o* H% m# w- @* P8 i
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);- J$ U5 |% P/ w1 F
  60. % T- y% b+ E9 i% R+ h% E5 P0 U
  61.    /* 读取单块命令 */' ]% ?* R0 W1 }+ d0 Z
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);# d' o3 U) l) Q4 r
  63.     }$ Q3 Z6 ?! x2 B/ f; U
  64.     if(errorstate != HAL_SD_ERROR_NONE)
    ; x9 ^5 f+ N+ U; z: [  b, |9 v' C
  65.     {& ?- B/ Y8 j; o$ g5 |& T
  66.    /* 清除所有静态标志 */
    8 w  P$ s# j3 ~/ J6 ?" U. S
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    3 d2 @( W! r7 x
  68.       hsd->ErrorCode |= errorstate;
    9 o- k; W. l7 S
  69.       hsd->State = HAL_SD_STATE_READY;
    - D3 _7 I3 q0 v: a
  70.       hsd->Context = SD_CONTEXT_NONE;
    / w: h1 x: ?% y4 [3 G# h# u
  71.       return HAL_ERROR;% ]3 D+ h1 ^5 K; C; z
  72.     }
    : P) g1 Y1 o1 n7 N8 x$ F
  73. + ^; h& F! `- Y; b9 L
  74.   /* 使能传输中断 */
    9 U$ C+ A. z' ~2 Y& A5 p
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    # n9 B4 ^& v* L5 a' U
  76. ! E( p( {/ D( K& e: L: T4 ]

  77. + Z) `0 |% T2 p( D) }; D
  78.     return HAL_OK;) `0 ~) a& Q& l) X) o+ G
  79.   }
    . c: U& o9 W# [1 L
  80.   else
    2 A# z6 l+ G1 y# d( Q' _- p8 t
  81.   {
    4 Z+ j. u7 n+ x) A5 U; f$ P5 b2 x
  82.     return HAL_BUSY;( N& ?; d# D, C+ o' H+ p
  83.   }2 v. u4 D0 w: L4 j) r
  84. }
复制代码
0 _# O# s7 |" \& `" m, f
函数描述:# i7 {' d4 Y$ M6 K1 j8 I
4 ]- H! h' @* {4 s
此函数主要用于SD卡数据读取,DMA方式。2 ?9 o) z3 I+ U) V1 A. Z

. K: v6 L/ `4 e6 d函数参数:
3 Q- z: y  Z% @8 A9 Y% N  I2 u$ H' K5 L, W
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
& y9 I" I2 H# q  第2个参数是接收数据的缓冲地址。
* X) Z! T2 a" W$ q, {  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。. S; Y8 e# q4 D# \. u! X
  第4个参数是读取的扇区数。
0 n0 n* _. G/ H  }( o: U0 Q  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。8 k) y3 S+ ]# s8 L- R) L
使用举例:8 {; x2 `0 |) x5 L, d
  c: k! t2 d5 Y, e/ N' t4 C
  1. /**
    2 O. Z% ~8 Q3 ]) Q/ ~" e# M
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.  D! r# b( _, Q4 [1 ?; a( u
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit* D2 x( T/ i# M3 n7 [* j8 v
  4. * @param  ReadAddr: Address from where data is to be read0 r9 \. ^5 ^- M% ?$ H
  5. * @param  NumOfBlocks: Number of SD blocks to read. `1 E8 x( _7 u+ z3 T; m
  6. * @retval SD status& j- Z& `  T! a6 Q2 q$ J: K
  7. */. k, q8 u7 g6 i9 C
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    - w8 M' J8 S5 Z6 w2 Q% r9 y! A
  9. {" b8 Y! v- s1 |
  10. ' m/ r$ g1 [& K3 z
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)# D8 \' ?4 p' {( r
  12.   {- E3 n% e. u" T" }" _0 p: c
  13.     return MSD_OK;
    ( h/ K: H$ O  Q% t3 m$ J
  14.   }
    4 s( L6 ~) B2 P3 C2 m! n+ M
  15.   else1 |4 g0 E6 ^0 M; L& C
  16.   {
    , g3 W8 m9 D5 \
  17.     return MSD_ERROR;
    + i: v/ W5 K6 _
  18.   }
    . e# G3 U& E' C2 S' l
  19. }
复制代码
0 L# I! e- J1 J$ B/ H" Z! [
87.4.6 函数HAL_SD_WriteBlocks_DMA
6 j1 w3 m1 b* @6 R3 L2 k5 P$ z7 Z- [0 H函数原型:
. K% ~+ ?  ?; q5 E+ R: }3 _# i
* Q; G# K% V9 V8 Q. K
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)9 s- Q" }0 I0 y
  2. {; P! ]- U( [$ y9 r3 P8 S
  3.   SDMMC_DataInitTypeDef config;& W. [" {- h% M( @
  4.   uint32_t errorstate;
      Z: [/ d& P2 m( i) F0 T
  5.   uint32_t add = BlockAdd;
    " b( [& S; y0 I+ q6 x  D1 x

  6. 9 M6 d* R, _3 a  W
  7.   if(NULL == pData), g* {/ p9 o# ]+ c. R$ r7 J
  8.   {( z8 j' D/ F. n& r5 ~
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;$ {2 M# [2 i# ]% n3 J. s
  10.     return HAL_ERROR;, P! D. z. [, z( M
  11.   }
    ! ]! s" @/ ]0 a* x/ g7 s( d5 P
  12. 1 b- G2 }/ j( @0 U0 ~0 U; s  W1 [& B
  13.   if(hsd->State == HAL_SD_STATE_READY)
    & v- U3 R' @, u$ P7 {; P( g
  14.   {
    # k) s5 V& B% M7 F8 _: Y
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    $ @! d% ?; b) k; h, l/ K
  16. + F9 R6 s- P$ u, |  l
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    " ?' j7 p$ Q5 x9 Y4 p+ u
  18.     {
    % k! q' Y/ U/ A! c/ k0 y0 Z
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;' }3 r  o. q3 R$ [/ r4 l
  20.       return HAL_ERROR;
    ) A! U( Y( [7 P7 O
  21.     }
    3 n, o: N- m1 a5 ?4 m
  22. % |- c: a% m8 E2 s) E
  23.     hsd->State = HAL_SD_STATE_BUSY;
    1 r* Q0 b2 h, _0 F" y0 @
  24. 3 ?6 z6 U0 c( D2 e
  25.   /* 初始化数据控制寄存器 */$ K! U' w0 H9 x& F! v; r4 I
  26.     hsd->Instance->DCTRL = 0U;4 m- N1 c7 I9 Y  w0 J- x' o

  27. , I" W, L' p. c0 f9 E( _. k0 ?
  28.     hsd->pTxBuffPtr = pData;
    $ A6 {" g& |: t$ g: j. I
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
      C1 e6 k  Y6 u) L

  30. & a0 e/ g2 P5 l+ e: X5 z) |
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    * H9 L* n+ z/ ~
  32.     {3 t+ O. t' b' U' Z: E
  33.       add *= 512U;
    6 o8 o8 B& j8 B0 }9 u' a5 v% H
  34.     }
    + v/ I0 L2 [4 |" x6 S9 K" K& Y: J9 ?
  35. + I. w9 y( E* M$ q) O; a2 x& J
  36.   /* 配置SD DPSM (Data Path State Machine) */' r; m% w4 L! L+ M
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
    1 X9 I6 O+ [" s* u4 A( S9 s
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;! r/ y. B1 B7 L% Z# p
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;+ a2 y( _& s5 G  h
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    4 E" B8 f4 S; S( X- t1 b
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    ' f4 X$ ?7 o3 x: s3 U
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    2 R! H$ b2 J1 P- O0 v9 C( [7 a
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    ( X5 r( t5 u+ U9 w; A6 k: G4 Z4 l( D

  44. ' K8 l1 ^+ T/ f4 w( Z9 A0 n

  45. 6 d9 S7 F8 W% {# m. ~% U
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);! {" p0 R# E: N) q- T7 P  d) ^* ]6 R/ W

  47. 7 {- ~& w2 _" M* O
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;3 F0 p6 V) U% n4 P6 x
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;( \) {0 V1 O/ `$ [; s: N3 R2 ^5 Q: i
  50. % F" P  ^5 Q/ ]: D  K1 L
  51.   /* 查询模式写块 */
    - ~# V- y2 a7 h' C  f9 n) g2 `
  52.     if(NumberOfBlocks > 1U)8 h! i9 {, J3 ]
  53.     {
    ( m0 `) d! s* n+ A# R# ?7 W
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    9 H2 O% g! I# y; S0 z

  55. 7 w3 D) T1 r. ?1 y4 @8 K
  56.     /* 多块写命令 */
    * @3 s0 @. R, d4 X" J4 ]- n
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
    8 h2 y' _; E0 A8 K- z& q7 w
  58.     }; @7 T% u% j* U9 H4 J
  59.     else+ N/ M$ u" l( t8 Y! B" Y  T
  60.     {8 W' W  `7 B7 g0 o- Q2 B8 n
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
    3 o8 ^/ t$ i9 `& ~0 _+ C

  62. / d3 K$ ~3 |  f3 \3 A
  63.     /* 单块写命令 */
    5 Z& a3 C, [: {! K# E, P" ]
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    8 Z8 V' ^: C8 X" h7 e, w
  65.     }
    $ P$ a) \  A  ?( m/ ?) Y9 x0 M
  66.     if(errorstate != HAL_SD_ERROR_NONE)
    * |& H' X' o4 I' d7 [
  67.     {
    4 c9 ]! l% u4 k+ C) y/ o
  68.     /* 清除静态标志 */
    % [, L4 W, P4 F1 l  f, p
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    3 L, K4 t  r& b
  70.       hsd->ErrorCode |= errorstate;
    8 Q+ Z3 Z. M( a/ }4 V% `
  71.       hsd->State = HAL_SD_STATE_READY;
    * ^6 }+ d! _' L; S7 M
  72.       hsd->Context = SD_CONTEXT_NONE;4 z3 [5 M" T0 x
  73.       return HAL_ERROR;* }, v4 \3 s9 \2 i
  74.     }9 q  a2 p8 B( T$ [' S: \' p8 X
  75. 6 f) z( i' a8 A1 Q$ R
  76.   /* 使能传输中断 Enable */
    4 Y& q4 }6 R* H4 f
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));# ^3 }( Z" h* f1 x
  78. $ [* d! ]) M" ]4 I2 P
  79.     return HAL_OK;" [- f  U9 f" n' V1 }! t5 c1 n
  80.   }
    6 Q$ B. y& s( M$ o
  81.   else
    % v4 i9 P9 G$ j' ^  E
  82.   {% b) t! `5 a. Z$ _
  83.     return HAL_BUSY;% I" A+ d. E6 N
  84.   }
    % U0 t" ^: W6 @$ \
  85. }
复制代码

( M  M8 V* i6 j7 u; O/ q5 O函数描述:" G# V. Q* Z- Y2 s/ M. A4 C  E
% o; j5 p, t4 I/ j  M( d( W. e: r
此函数主要用于向SD卡写入数据,DMA方式。
* T4 h& [7 a0 |
# U' p4 ]' v! k. k' f函数参数:
, Y: }/ h+ @+ G/ k
2 y7 y8 d+ b  W" A% C  第1个参数是SD_HandleTypeDef类型结构体指针变量。8 R3 t& l7 n; y- i& {" I7 O' r+ q
  第2个参数是要写入到SD卡的数据缓冲地址。/ h4 `' N, p8 P4 [7 l7 E: i$ O
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
) F1 Y/ i/ ]' O; d% H; J" R* S  第4个参数是读取的扇区数。
) \# R2 U$ @( ?2 a/ D6 d& c  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。* r+ L1 e0 c( a- \. i+ c8 {6 Z$ }
使用举例:
8 l) |) E' S9 L7 |. f4 g
8 }" z. A5 l4 C. E+ y5 w
  1. /**7 @$ o* l6 Y- g! G  X8 N
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
    6 c' O; J4 u/ V. W  N" j* u
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit0 I/ }8 _  d4 K; k; p
  4. * @param  WriteAddr: Address from where data is to be written% _6 {( n* o( b; \# h: u9 Q# K
  5. * @param  NumOfBlocks: Number of SD blocks to write
    + h: K* N- N+ W8 I
  6. * @retval SD status1 }9 {; a3 E  W& ?$ ~' y( X
  7. */
    - j1 O4 P4 N  ^/ Y
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    - A5 k7 ^: B3 b: ?# }0 V
  9. {3 `# }: E4 v6 p4 I) K
  10. 7 p0 T! ^% b- \7 b  r
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)7 P% F* U* o) H1 {
  12.   {9 X" i, P* x: y7 j  {/ c
  13.     return MSD_OK;6 w5 K% P8 \* R4 P
  14.   }
    ( `5 ]" F7 v+ D) B1 o4 H
  15.   else9 [' s" w% q6 `" _0 O) Y
  16.   {
    6 `, N3 U: ]; V' {0 q# z
  17.     return MSD_ERROR;
    + L" _6 @* |% K/ d
  18.   }
    ( m! _& ~. w2 Z; v
  19. }
复制代码

* l( N4 l, e* t8 x6 C87.4.7 函数HAL_SD_Erase
' o% h4 }' B$ ~' ]$ x7 n函数原型:! u# G( N3 X! J

5 H$ y3 ?; D! a. T
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    7 v* w9 r9 e  a/ z- H  N. a
  2. {
    5 p1 [8 H( j7 Q8 q0 L/ y! q
  3.   uint32_t errorstate;; w; _% p! w, O0 q
  4.   uint32_t start_add = BlockStartAdd;
    8 T( w- N, |4 E5 g9 B" p
  5.   uint32_t end_add = BlockEndAdd;( ?) J6 e$ i/ z9 u; Q8 i/ T

  6. ) b' P; I7 v: m, a( y
  7.   if(hsd->State == HAL_SD_STATE_READY)
    5 R% b: l. q4 l& f# L. A5 v# U+ e# A
  8.   {* E4 h) R! ]7 G. P. K) u# I+ Q
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    5 v& M/ e5 P, ]6 _) i( ~
  10. 4 C- C: \% Z8 s. L, F4 \
  11.     if(end_add < start_add)" Q' n* h) A$ d$ _2 U
  12.     {
    ( W6 I+ h3 k& L& x3 W
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    $ r+ X+ o7 f- H$ Z- D, L9 i
  14.       return HAL_ERROR;
    ' a* H, A: C# b+ ^4 _) B' {2 i9 X
  15.     }
    % R, \4 l& H! M; K! F3 f" w$ ~

  16. 5 A' A; Q1 U' C& O
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))8 S7 K* c  X% ~2 ^! _) r
  18.     {1 o0 e; X" m7 r& ^2 N# x1 e7 f
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    , A3 Y% @+ D& d1 c; z6 B0 i
  20.       return HAL_ERROR;: }2 g/ A2 \; F# s# l, _7 i
  21.     }
      [( i6 ~; X7 Q+ P

  22. 1 \5 H5 K0 k8 y& y7 u' {' L
  23.     hsd->State = HAL_SD_STATE_BUSY;% |. H& C, H" O7 B% }* F  k' _
  24. ' y9 {0 D8 u) B9 m( h# \% N: U
  25.   /* 检测是否支持擦除命令 */
    * i% [$ _6 w. g7 Y2 ]+ O' }
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)/ [: ?1 q. Z9 K% {
  27.     {
    2 |1 U% X2 o  W! M% A
  28.       /* 清除所有静态标志 */' u9 m0 r* q' m, \
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);  y6 b+ D7 H; k$ v3 Q1 m5 j+ [
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
    ) z" g/ v, H, c! g) C6 x4 m# a
  31.       hsd->State = HAL_SD_STATE_READY;# p2 Q8 ~( {! X0 f- T5 h. \
  32.       return HAL_ERROR;- f7 F" A6 n% T0 z
  33.     }
    1 }6 L6 Q/ w1 h1 Q3 |

  34. ' Y$ k7 R1 B" N" C' X0 c2 I& f
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED), e+ A5 e6 t) S
  36.     {/ E  w* e" }$ W# m! s" H9 o2 S
  37.     /* 清除所有静态标志 */( `- Q+ A( Q* n' X1 f% q
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    % Z. J3 k3 w' g2 G1 ?3 L. f3 i
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;" q" R0 f, g3 t4 d" P
  40.       hsd->State = HAL_SD_STATE_READY;0 M- Q6 r& }% E
  41.       return HAL_ERROR;. o- ~" j  _  M; L" ^, ~1 F( Z
  42.     }
    6 x7 ~" y, g2 z& x
  43. 2 i* q) O* u( R/ k0 V
  44.   /* 对于高容量卡,获取起始块和结束块 */
    ( z1 H5 p) Q  [
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)7 T* c2 Q( _! \3 n
  46.     {5 U' y1 F# Q$ y& u4 o9 W
  47.       start_add *= 512U;6 L$ A5 {" v  {# ~
  48.       end_add   *= 512U;
    : J/ X1 {, [  h7 x, a3 R& |
  49.     }
    " h6 v4 D! n6 @7 @" D$ ^0 t0 o) A

  50. 6 Q3 O- t4 t9 y' p: C9 V5 \
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
    ( p; z0 l% X$ B  M7 G1 T  c+ W  z
  52.     if(hsd->SdCard.CardType != CARD_SECURED)5 V7 U+ ~8 F. ^8 h3 q9 H4 P
  53.     {
    : ?* [2 f: b. N7 o( ~5 o8 F
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
    # u% V* z' u5 A
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);5 ~. x# D) p' A  ]' j9 b) A
  56.       if(errorstate != HAL_SD_ERROR_NONE)0 `: h6 M9 t6 g, z, K, u+ h+ H5 q
  57.       {9 [& j7 p. A$ A' B) c/ y
  58.         /* 清除所有静态标志 */
    4 N7 R: C# }6 C
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    + }# ]. w; q" j: X$ {
  60.         hsd->ErrorCode |= errorstate;
    . c, h7 T/ e- R2 p1 A% o+ D
  61.         hsd->State = HAL_SD_STATE_READY;3 O* y1 u! p) N9 F0 I
  62.         return HAL_ERROR;: x. r  n. O+ @, Y# c+ M- q. ^
  63.       }
    ) `  S& Q. d4 f; l
  64. 7 ~- S/ {2 k3 w
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */9 C; Q! M9 u9 d2 D
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
    8 s5 J  l: B% p  L4 N' @; {" `- X/ [' b
  67.       if(errorstate != HAL_SD_ERROR_NONE)
    5 B* s& X8 O; }* T2 A
  68.       {& R8 G2 N: r/ x2 N( x5 U
  69.         /* 清除所有静态标志 */3 h8 d/ g% F% I& O  F/ M2 _
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    ; `, R! R, G  c  O/ A; x
  71.         hsd->ErrorCode |= errorstate;! U9 Z/ w& g& g* }1 {3 O2 A( r, ~
  72.         hsd->State = HAL_SD_STATE_READY;9 z) }9 [9 I; p
  73.         return HAL_ERROR;
    + N# R2 l, `2 V6 p0 K/ c
  74.       }
    % [; ?  [) `- e2 h7 T+ |5 p1 B% k
  75.     }8 Y! _& ^) n$ z4 r! s1 M0 R+ b1 O5 O

  76. 2 W* ^! n+ l. S: P
  77.     /* 发送CMD38 ERASE命令 */
    & I8 i3 H! H- O" |* H" E
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    $ Z8 k* N4 |! X# Y  {" u* o
  79.     if(errorstate != HAL_SD_ERROR_NONE)# |; s) Y1 f1 j
  80.     {8 r7 p: z) ?! ~) B7 T1 k
  81.       /* 清除所有静态标志 */
    / k7 w( b# E8 j, V" {$ r
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);8 z5 S* _  G8 a8 x) K. U" i# m( Q
  83.       hsd->ErrorCode |= errorstate;
    & R+ B& e# Q* C+ G0 O( h. l
  84.       hsd->State = HAL_SD_STATE_READY;
    0 ~! h+ z& b7 k  J2 M; O
  85.       return HAL_ERROR;
    0 Z7 i1 ?' I1 |3 W' G  a
  86.     }7 a+ f3 A# m7 j

  87. 8 z' p# K% r6 n$ f, L5 I7 @
  88.     hsd->State = HAL_SD_STATE_READY;
    + p. R2 e4 V5 T! o
  89. 0 L# p+ P& ]/ n. W- J2 {! i7 s' a
  90.     return HAL_OK;
    1 T+ `5 K0 T" H  G$ A
  91.   }
    3 ]( f: Y# F. l$ r8 Q- _7 F; B, R
  92.   else) f4 i$ r% x: y4 U. M2 L
  93.   {5 ^5 z7 T3 o, u7 k9 ?* e' j
  94.     return HAL_BUSY;3 p. o0 M4 a. ]8 }. J) T- P4 W( I
  95.   }6 @( [( q( @; I: J' ?
  96. }
复制代码
( N3 V% _$ g8 F) @2 q
函数描述:
6 y% v( F1 n$ P
. g+ B4 M' N  F( e9 x. c" l此函数主要用于SD卡擦除。9 Q/ F( s0 W2 F

# ]$ h$ _) V5 x- s函数参数:
8 w% c0 e' C% ]+ J# v9 c
1 o4 ]7 ^& X' }8 O  第1个参数是SD_HandleTypeDef类型结构体指针变量。& [7 C5 P0 {- W6 \9 q
  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
) [) P) M" `" P+ m7 ?9 w5 H  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。$ q' p9 `, S6 q* r* k
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。0 J6 |( n" ?$ M* }% H$ J/ m' }6 F
使用举例:( j8 I- E3 j" Y9 [# S4 J! c
7 C$ f6 ?1 e+ m& M5 Z% O
  1. /**  i( c; f  Z+ O( V; y( b1 F
  2. * @brief  Erases the specified memory area of the given SD card.
    ; p: b) A" h0 j% l; P2 `
  3. * @param  StartAddr: Start byte address
    ! v) y7 S; E8 _, E- _
  4. * @param  EndAddr: End byte address
    / ~( L( F4 ?$ l. n# W" \9 V
  5. * @retval SD status
    $ U% j! M5 ?6 |% B- i5 D  v! W
  6. */2 X8 p9 V" c, C% t0 b1 j) g3 ?
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)' P5 }: i# ?: ~; ^
  8. {, a; U& B) [- O# v8 w  e. ~" D# x; @+ `

  9. 5 N2 M$ b6 U8 c* X  U9 A2 f9 g
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    ) s+ }6 h) W/ [) x! L( ?
  11.   {
    , T$ A- \0 q0 ~1 }
  12.     return MSD_OK;
    $ X! j. i) X9 a. {1 X
  13.   }( j8 @+ q$ {- B3 _) Z& q4 M
  14.   else
    0 q+ C/ j0 o' x& ]* ]* x3 r
  15.   {: R$ ~% H! O, i! W9 h, P
  16.     return MSD_ERROR;
    & I. f$ O# D1 X# @  l, D/ ?1 X+ f' |
  17.   }; s+ {- U) ^* Q  k
  18. }
复制代码
. b8 G8 [2 i# u
87.5 总结
* N( k% u  i0 H2 m# _9 O本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。
% k9 p! l* _9 ~% x3 v6 q. o& v, I' j5 l7 r, S( q- \  {
4 y( ?( X& V0 F( D
收藏 评论0 发布时间:2021-11-6 23:38

举报

0个回答

所属标签

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