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

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

[复制链接]
STMCU小助手 发布时间:2021-12-26 16:43
87.1 初学者重要提示
4 ]% P- F; a2 D/ q3 R  对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。, W# u! Z# R8 z& F) w
  注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。
8 T& o2 {* w" ~: E+ d, \  SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。
) W/ \1 X. k1 I# |  SDMMC驱动SD卡支持1线和4线模式。+ K5 P4 Y1 }5 u6 H
  STM32H7的SDMMC也支持eMMC:/ @: ]. D$ r  ^0 f/ f7 h
' h7 v3 ~3 a6 Z. M2 K
87.2 SDMMC总线基础知识6 s" }7 n0 ~) X% `. ]
87.2.1 SDMMC总线的硬件框图! P9 x4 _1 Q5 N
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
1 ^, k# |7 f& O8 }
; ]* U8 ?! _1 \6 [( ?' D- I0 k
6eea62abe623396815a50adc87205b83.png
/ Q0 P$ b% o1 w! L( l
) v3 f2 \; W8 C9 E$ @
通过这个框图,我们可以得到如下信息:  ; _' z* {6 m( n
   sdmmc_ker_ck输入' _$ i6 \  ]% X+ t( x
SDMMC内核时钟。1 O0 M4 Z+ ~) L- H( {! ~
" T5 @/ t) R7 t
  sdmmc_hclk输入, t# s3 I$ n) b% X% Y4 Q; ^
+ Q4 v& j3 i  ~0 I3 T5 O
AHB时钟。
  [* t! }% _6 M8 v3 W7 }9 |1 `8 |8 B  T9 X1 \: l7 _
  sdmmc_it输出& ]& @8 \" k6 O1 {6 ^+ L2 t0 q
# v" ~3 b2 i3 i" w+ ^/ ~+ r
SDMMC全局中断。5 X( C/ Y  s( z* R7 F: G5 G
) ^* b  Y9 y5 t, d- h; W
  sdmmc_dataend_trg输出" u, m& l- d4 ^0 E4 q( \: _% A9 D

2 N: e' u1 @! D$ A1 p3 l% fMDMA的SDMMC数据接收触发信号。
, @3 c, I0 ?; {$ x5 O" a& J
7 ?4 r, f+ s( J9 p4 o  SDMMC_CMD1 L; c. |# f9 R9 B

3 {: N6 a2 s+ hSD/SDIO/MMC卡双向/响应信号。
  X7 W. i# J& A3 c2 u$ Q: u2 s
9 ~$ ~( r% b& z0 n; X  SDMMC_D[7:0]
$ M) l+ K  k) `; g, e; t1 C
% L6 C9 v& E$ h0 WSD/SDIO/MMC卡双向数据线。
% b  _- `0 l) s9 y+ G3 o7 U; G' D
  ~" _6 R' R' o8 y2 u4 \  SDMMC_CKIN5 o$ ?8 J; }+ y1 I8 u# O5 u
$ V$ I' v6 ?$ t4 e! w
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
+ H/ f% k- z  Y) A6 V4 \' E+ W9 R' d3 ^$ V
  SDMMC_CK
+ Q, B0 a+ b- S& F( |$ N% y' ~  j
SD/SDIO/MMC卡的时钟。/ w9 t8 ^+ c  A: G/ i/ h4 P

  e& ^( V5 l3 S7 Y& |* ]3 s6 O* q% `  SDMMC_CDIR
; `0 {( ~' Y% d9 T7 y7 s# j* O2 z. f6 z$ L2 A
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。# ~1 G" K2 [+ i- {

' e% ]9 d' Z& C( E  SDMMC_D123DIR
! s( B# ^) e  F$ d# C" m2 _7 Z+ v/ _& f5 T
SDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
, B( s: M' E8 b/ {3 Y% A' {4 x! T# w! q1 R& u9 D
  SDMMC_D0DIR
% H( ]- X- W& `9 d$ i% ?7 O$ I& P  D
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。3 I( W4 O& r. d! y. }3 T  e
  t# @6 f* U4 }3 \3 f) ^; J# h
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。9 b' I. i5 y( X) T  L) Z0 i
3 y2 y. P. u5 T* P+ l# X  Y
87.2.2 SDMMC时钟1 W/ Z' \& u% i5 u' q& i9 U" k
SDMMC控制器的时钟来源:% g. m6 ~" p, A3 M
/ b+ r* R* \1 }% }5 [: ^2 N5 t/ }5 H
676ec31792fcb80bee640ed979d48084.png
( V/ @1 z3 U4 a' b  C

# A, C6 P6 h; b* S" GSDMMC1和SDMMC2时钟源是一样的:
* E) {$ d1 A; P. K- y3 z$ w: n5 W) v; W9 Y% P) w
79b1c69986d1ee5bc090bf1676f396fd.png
+ a3 [3 _* v) Q; z' F

; U" y2 G' J8 U* i3 \' h" U2 W87.2.3 SDMMC1和SDMMC2支持的RAM空间区别+ e; \& @  c$ x" m" X2 V5 @: E% J
注:大家应用时要特别注意这个问题。
3 t& t4 B0 P0 C  V0 S
; J+ G; G! U. E- i使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的
, q& d+ r9 E+ w0 |4 b6 ^/ O6 x% D0 g0 o* {% y/ Y# ^6 k( ?7 w
6a5491d2f4a8740d838af58d034b7597.png

6 B3 M- M$ N& }( e9 y
% q7 E' \) D* P. J87.2.4 SDMMC支持的速度
/ e* {6 k5 i7 _3 B/ J. w
驱动SD卡支持的最大总线速度:2 n/ T; `% L& E. F6 I5 ~! g

: G( X& l) J' }
b70ce31107b38ea820dbc28c3caec38e.png
6 c( E% h# d9 @% p0 J* {

! E+ c) G" R/ J% ]* T0 C- a驱动eMMC支持的最大总线速度:) d4 H5 |  ~# F3 b/ x

& T8 V$ H9 _9 p: k; B( f" n6 n  m
843bf7a054944ba7d5d137ca84e1d4ed.png
( E8 k6 z# E- ]; i: i" t$ z. m

' v2 G3 c5 k5 H  H/ {关于这两个数据表,注意以下几点:
3 e9 ?* C7 a: A* D7 M, v& B- J- u2 x  O9 V
  驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。& A4 i. f; Y" w) K# R1 u
  针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
8 P" W! p% D/ ~# `% D! @4 m  最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
3 v1 T! L( N/ P3 c& }  ]$ a) e+ F* |) m* B0 Y6 J5 m  Y( r
87.2.5 SDMMC支持UHS-I模式

. |( E+ {$ M8 f6 K8 ASTM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
5 p" ^0 }3 B) ]$ e6 H2 y7 x# {, [0 w) {# s, Y
2b8e4430b8a60dc5a1b342d7c7f75f52.png

; n: f  _" r# q; y9 `7 ~1 w( t- s( E$ R" i
85f975745619c9afc64f8889289dad58.png
9 v8 h2 H$ `+ x/ Q9 [2 Y

9 R  s8 q$ S$ E7 {! a- o3 `; w87.2.6 SDMMC自带的DMA控制器IDMA
5 M2 X0 v; n8 B  P/ i
STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
+ x* i" ]- p4 f$ E' r* V" K% ]) X4 n+ _/ w1 z) v+ Z7 r9 _
87.3 SDMMC总线的HAL库用法
* a5 H) f/ n6 a/ V  r) ]; N4 p. D# R87.3.1 SDMMC总线结构体SD_TypeDef
/ ~" f  W4 r- A, z- V) ~! ]- TSDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
1 e/ v# ^. W8 ~) P) Z& @; T( |. r  {# |* ]. c! S+ J
  1. #define SD_TypeDef          SDMMC_TypeDef# Y( r; Q3 n; P4 G( n9 v% B
  2. typedef struct% a7 n4 u: Z. U: ?. |, ?
  3. {
    0 z# ~1 w: V$ M+ o: R
  4.   __IO uint32_t POWER;          /*!< SDMMC power control register,             Address offset: 0x00  */
    ' Z" W& Y, N; P2 ^
  5.   __IO uint32_t CLKCR;          /*!< SDMMC clock control register,             Address offset: 0x04  */. O! M. `* V, |# Y, D
  6.   __IO uint32_t ARG;            /*!< SDMMC argument register,                  Address offset: 0x08  */+ B$ W8 M) q* u2 B8 C; X- M4 b
  7.   __IO uint32_t CMD;            /*!< SDMMC command register,                   Address offset: 0x0C  */6 @5 c, E% s1 x9 b. P, u* c
  8.   __I uint32_t  RESPCMD;        /*!< SDMMC command response register,          Address offset: 0x10  */
    4 J" _/ m; |# F; l- ~5 [" Y
  9.   __I uint32_t  RESP1;          /*!< SDMMC response 1 register,                Address offset: 0x14  */
    1 k/ `8 w2 \$ g8 e( ?" V8 y& N
  10.   __I uint32_t  RESP2;          /*!< SDMMC response 2 register,                Address offset: 0x18  */
    7 q7 E6 ]" m1 k' V, c1 j% X5 B. X3 Q
  11.   __I uint32_t  RESP3;          /*!< SDMMC response 3 register,                Address offset: 0x1C  */
    8 Y8 \5 \/ @9 E
  12.   __I uint32_t  RESP4;          /*!< SDMMC response 4 register,                Address offset: 0x20  *// X( U! o/ ]5 c
  13.   __IO uint32_t DTIMER;         /*!< SDMMC data timer register,                Address offset: 0x24  */" [# R& ?* Q0 C% |) k# }
  14.   __IO uint32_t DLEN;           /*!< SDMMC data length register,               Address offset: 0x28  */, L8 S- F3 K+ M% ~0 Z/ l
  15.   __IO uint32_t DCTRL;          /*!< SDMMC data control register,              Address offset: 0x2C  */+ V% X5 p0 x" q
  16.   __I uint32_t  DCOUNT;         /*!< SDMMC data counter register,              Address offset: 0x30  */
    ' e* r- b3 R0 L  d1 Y
  17.   __I uint32_t  STA;            /*!< SDMMC status register,                    Address offset: 0x34  */" j5 ?, S0 A/ a" {
  18.   __IO uint32_t ICR;            /*!< SDMMC interrupt clear register,           Address offset: 0x38  */
    ! b, i& W  I8 V: s  F
  19.   __IO uint32_t MASK;           /*!< SDMMC mask register,                      Address offset: 0x3C  */; _4 Y( A) n* Y$ V
  20.   __IO uint32_t ACKTIME;        /*!< SDMMC Acknowledgement timer register,     Address offset: 0x40  */
    6 X8 y  i; E; s6 [" F
  21.   uint32_t      RESERVED0[3];   /*!< Reserved, 0x44 - 0x4C - 0x4C                                    */6 ~$ c  p+ D3 |$ z: T( S% I
  22.   __IO uint32_t IDMACTRL;       /*!< SDMMC DMA control register,               Address offset: 0x50  */, |) m# K2 ?$ c( y! \
  23.   __IO uint32_t IDMABSIZE;      /*!< SDMMC DMA buffer size register,           Address offset: 0x54  */
    % V% u( \; p8 |2 p6 f4 [
  24.   __IO uint32_t IDMABASE0;      /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58  */
    ! ]1 Z8 p2 m. M- s$ ?1 _
  25.   __IO uint32_t IDMABASE1;      /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C  */& j! ?( I+ [% z/ j5 ^
  26.   uint32_t      RESERVED1[8];   /*!< Reserved, 0x60-0x7C                                             */6 L6 m' {# v2 Q
  27.   __IO uint32_t FIFO;           /*!< SDMMC data FIFO register,                 Address offset: 0x80  */
    : [- V8 N% W4 q* C& G* S
  28.   uint32_t      RESERVED2[222]; /*!< Reserved, 0x84-0x3F8                                            */
    . \$ S+ F* L: f5 D' X, x/ u
  29.   __IO uint32_t IPVR;           /*!< SDMMC data FIFO register,                 Address offset: 0x3FC */
    9 H: P( {5 R7 ~5 Y) d0 M  u( t" _
  30. } SDMMC_TypeDef;
复制代码
, p9 r0 X, q" T7 {& o0 ]
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。2 U4 Q. j0 b8 d5 `5 j/ m
8 S  W2 I( s/ B  ~" C
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:3 G+ Q2 _( C0 e+ w* V2 |
3 c; m4 O( H8 t4 p: X) b
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    # }  q! Y) M$ J8 v
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
# K& t! z: N1 \- F; u  {; C
下面我们看下SDMMC的定义,在stm32h743xx.h文件。" V5 I% e3 w! r0 J' J; c- @
0 g1 r& K0 G2 x% m% F; t$ M
  1. #define PERIPH_BASE           (0x40000000UL) ; b. g9 M$ L' J' U
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000UL)9 u! G" _. q/ m/ H7 p
  3. #define D2_AHB2PERIPH_BASE    (PERIPH_BASE + 0x08020000UL)
    ' l5 K! f+ w3 l. s3 e0 e8 r& }
  4.   ^2 }. u2 L9 ]" }8 Q
  5. #define SDMMC1_BASE           (D1_AHB1PERIPH_BASE + 0x7000UL)
    2 U, w/ z" N" E3 C2 ^
  6. #define SDMMC2_BASE           (D2_AHB2PERIPH_BASE + 0x2400UL): H9 B' n- s' _3 L- D, a8 N

  7. * d7 x/ A3 A( t5 J* M( k
  8. #define SDMMC1              ((SDMMC_TypeDef *) SDMMC1_BASE)
    # J" ~4 s* d( T0 v. ^$ v
  9. #define SDMMC2              ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码
. u2 o0 s6 ^% d/ n9 w  q$ I
我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。2 d( J% R0 X5 T7 t' {5 C- V4 g

" ^8 _! g2 W# {1 J6 V% ~87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
: \; o. D9 e/ m" U# t( ~8 ]! W下面是SDMMC总线的初始化结构体:
  |1 B* o+ P9 O$ X+ T  g0 g  _: s) c& Q$ [) x6 J1 {& F% l
  1. #define SD_InitTypeDef      SDMMC_InitTypeDef
    % k: k2 r& M$ Q2 J
  2. typedef struct
    / ~7 |9 D7 F' t* E
  3. {
    ' R3 j7 @+ n7 r0 d5 J
  4.   uint32_t ClockEdge;            3 M% R- j- B0 h3 r
  5.   uint32_t ClockPowerSave;      
    8 k, o- C, }& q" X
  6.   uint32_t BusWide;             7 J- @% [5 J0 n5 t) k) P0 s! p: l
  7.   uint32_t HardwareFlowControl;  7 B+ ~& Y, D, m0 o" K
  8.   uint32_t ClockDiv;            
    0 h3 K5 W9 a" f6 J% ?# `
  9. #if (USE_SD_TRANSCEIVER != 0U)! Q/ s% |/ G7 a$ S: |8 X; K0 U
  10.   uint32_t TranceiverPresent;   
    $ p8 O8 N( ]9 D1 b. |( j. I* D
  11. #endif
    ; U9 [0 o3 ~" g8 U* Y; W$ [
  12. }SDMMC_InitTypeDef;
复制代码
, j! d+ n$ ]4 _1 ^% U* d
下面将结构体成员逐一做个说明:6 y: T- G' ~% ?; L4 N
0 ]# t# @  s- P* `1 z2 A( Y0 F  B! I5 \
  ClockEdge
8 O% [3 I4 Z1 q- r用于设置SDMMC的数据或者命令变化的时钟沿。
9 K% V6 @7 ~% v& u( u: H. S0 N' G( \# S5 _, m" L
  1. #define SDMMC_CLOCK_EDGE_RISING               ((uint32_t)0x00000000U)2 N6 p! z; p- z
  2. #define SDMMC_CLOCK_EDGE_FALLING              SDMMC_CLKCR_NEGEDGE
复制代码

" c- _  Y2 F/ O  ClockPowerSave
; X8 t" O8 o3 @0 T7 _- z用于设置空闲状态,是否输出时钟。" M, X( {* X& x) l* N! J$ ~/ d

! o+ Y/ ]8 c: I' M7 P4 o7 @2 j9 h
  1. #define SDMMC_CLOCK_POWER_SAVE_DISABLE         ((uint32_t)0x00000000U)9 |8 t8 G: s* }7 K6 s7 E
  2. #define SDMMC_CLOCK_POWER_SAVE_ENABLE          SDMMC_CLKCR_PWRSAV
复制代码

2 U4 I' v! e- E4 G+ ^; m8 t  BusWide
# f9 D3 ~. M6 b7 p& X1 w7 ^用于设置SDMMC总线位宽。
! |0 _; W1 F7 l: N  |: @2 ]  D0 }# n# @) ]  \8 w
  1. #define SDMMC_BUS_WIDE_1B                      ((uint32_t)0x00000000U)
    & s2 P( P" Y& I- a# i
  2. #define SDMMC_BUS_WIDE_4B                      SDMMC_CLKCR_WIDBUS_08 O  S8 u% y! q
  3. #define SDMMC_BUS_WIDE_8B                      SDMMC_CLKCR_WIDBUS_1
复制代码

; \) A# D2 {! ]; @/ v0 R& W  HardwareFlowControl& m, J7 \- A/ C+ m; ^
用于设置时候使能硬件流控制。, J; v# K6 e/ f2 t8 a5 U
" L, p% F: K" ?1 J: p' b4 ?
  1. #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE    ((uint32_t)0x00000000U)
      `* }0 y# ~# O% i, r) X$ t
  2. #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE     SDMMC_CLKCR_HWFC_EN
复制代码
8 _/ |. _3 j7 R( |* I5 E+ b
  ClockDiv) \/ `4 x$ T& D0 F2 H( \8 v
用于设置SDMMC时钟分频,参数范围0到1023。. b2 t4 Z! H/ J4 B
" P( V$ s2 [# o4 B$ T
  TranceiverPresent
# u  b% j. d# O  I# \* D8 N用于设置是否带1.8V收发器。
  1. #define SDMMC_TRANSCEIVER_UNKNOWN             ((uint32_t)0x00000000U)
    - P) m- q$ H% o; M5 S
  2. #define SDMMC_TRANSCEIVER_NOT_PRESENT         ((uint32_t)0x00000001U)9 v4 \$ Y. P6 j# D. f3 Z4 f/ T
  3. #define SDMMC_TRANSCEIVER_PRESENT             ((uint32_t)0x00000002U)
复制代码
2 ^  o# O/ p0 Z# m: X
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef

# b4 ?/ ?  X; E下面是SDMMC总线的卡信息结构体:
0 T4 ~& W/ d0 N- E
" `  D0 I# T# U( @/ i& P/ E! Y
  1. typedef struct2 t+ `; e4 W( Y9 J1 T9 P
  2. {+ Z+ z, P, W7 T. @* Y) S- k4 K
  3.   uint32_t CardType;                     /*!< Specifies the card Type                         */
    # x4 C2 z: C& B8 J5 }% X
  4.   uint32_t CardVersion;                  /*!< Specifies the card version                      */% }& ]( \! [" [" ~
  5.   uint32_t Class;                        /*!< Specifies the class of the card class           */7 e# j* o; E1 G1 S8 Q
  6.   uint32_t RelCardAdd;                   /*!< Specifies the Relative Card Address             */
    * D3 w0 L8 j5 S' L5 Q/ o" G" V- L
  7.   uint32_t BlockNbr;                     /*!< Specifies the Card Capacity in blocks           */
    3 }, Z4 w" {; I
  8.   uint32_t BlockSize;                    /*!< Specifies one block size in bytes               */
    ) d5 {, \" U# F! Z
  9.   uint32_t LogBlockNbr;                  /*!< Specifies the Card logical Capacity in blocks   */
    ; U4 I2 H6 J. t- P  \0 {8 N
  10.   uint32_t LogBlockSize;                 /*!< Specifies logical block size in bytes           */
      y2 z+ C8 k: e
  11.   uint32_t CardSpeed;                    /*!< Specifies the card Speed                        */) I7 a8 c$ ~1 D  s
  12. }HAL_SD_CardInfoTypeDef;
复制代码
( F+ V! G; F" [2 I, N$ g% ?
下面将结构体成员逐一做个说明:
9 S( }  r( R$ r# t$ f( I
9 n9 I; P) j! m$ y4 R: }( F8 V, G CardType
7 F4 A; Q! ^2 q7 Q& J) D卡类型。2 X  ^, P& X- Y5 T6 I

0 S$ Q! A& }+ Y$ I; X" p% ]
  1. /*!< SD Standard Capacity <2Go                        */! S/ j# T$ k6 ?8 i0 A
  2. #define CARD_SDSC                  ((uint32_t)0x00000000U) - L4 i9 B6 s4 f# v: ~
  3. /*!< SD High Capacity <32Go, SD Extended Capacity <2To  */
    / Z* R- j& p' L* R
  4. #define CARD_SDHC_SDXC             ((uint32_t)0x00000001U)  
    ( X1 D5 X0 O+ [. r7 |) \. c' J. M
  5. #define CARD_SECURED               ((uint32_t)0x00000003U)
复制代码

0 l$ B; |5 d* J2 c4 ~4 q0 Q  CardVersion
/ R  ~( A5 [, }$ N2 r
" m5 M; {) v# [* F
- J" ?$ `! P- k/ S5 ^卡版本。
5 ^( N7 ^8 S( X
+ e1 i) s) q% L
  1. #define CARD_V1_X                  ((uint32_t)0x00000000U); w) x/ z  ?7 C( Q+ q7 v# C9 n0 b
  2. #define CARD_V2_X                  ((uint32_t)0x00000001U)
复制代码
6 \& _/ R& w( b3 a9 H# K9 J
  Class6 m* v1 J1 `' j/ ~9 {5 H$ p
% G+ g3 @1 n  ]4 W, a9 M! R7 h
4 `2 N5 a: I  `. R
卡类型。
) H$ M+ _* {* s  a- d
0 k  \( w8 Y% {8 a: z( I+ F  RelCardAdd
# s/ }9 n, l5 w$ }5 |. G! G' e6 O% L3 u7 o, C
* O2 [& V$ C: C; B& P: v
卡相对地址。
6 |0 P: Q4 M" Q# Y: `& h7 B
4 U; K% D2 X; M" P* U  Y  BlockNbr
2 O* Y- i7 o: ]- [整个卡的块数。% w) F; }  b7 l2 S
4 h" `/ u- U3 W8 @2 i
  BlockSize
) K* t- v, B; r1 _  I0 Y* a# c' X. D% f, ?9 J' l
4 h0 M2 ~. U2 K# @
每个块的字节数。
* f+ w+ c! j: [' d! F/ z5 n. c( Y! Y7 T) D9 m
  LogBlockNbr
' |: u1 P5 x& y) I4 P- E+ V! O8 p$ S' @' T5 R) Z  h1 S6 J( q
% ^! @& N+ s- b" D
整个卡的逻辑块数。$ j3 j8 s# o  d  |

* |4 D& A9 w- x' G$ ]  LogBlockSize
$ X* K6 Y( a' i+ z7 z% \" D( G  ]& F' l5 Y, y( W- F2 u
5 N* U6 t, _3 u$ ~5 B2 ~0 Y5 H
逻辑块大小
. g1 {+ Y  |! {) Y) e+ A2 {% K8 v4 K
  1. #define SPI_FIRSTBIT_MSB                              (0x00000000UL)) ~' q" ?% l% a4 u; X" S2 H
  2. #define SPI_FIRSTBIT_LSB                              SPI_CFG2_LSBFRST
复制代码

. B7 I2 ]5 e/ Q6 a4 y' K+ _ CardSpeed
  |/ V' ?3 c" k9 P8 K" p用于设置是否使能SPI总线的TI模式。& g; E" A$ _4 z- M5 k2 x, P( U
* ~7 q: I% T6 j" C0 V
  1. /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01    */
    , o" m* J7 E3 k9 Q" `
  2. #define CARD_NORMAL_SPEED        ((uint32_t)0x00000000U)  # X9 q2 |  q( {  A

  3. - {( F( f4 P" x* a
  4. /*!< High Speed Card <25Mo/s , Spec version 2.00        */
    8 z' r6 e, m- X' P9 S
  5. #define CARD_HIGH_SPEED          ((uint32_t)0x00000100U) / X8 }* L7 ~, u* b/ T0 V
  6. 4 E. b% E) B' t4 k: ~/ G( i" E
  7. /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards3 ~* m7 g; |  c( ~+ u* \& X
  8.      and <104Mo/s for SDR104, Spec version 3.01        */0 @4 f' v7 U2 v. g5 w
  9. #define CARD_ULTRA_HIGH_SPEED    ((uint32_t)0x00000200U)  
复制代码

* y& C$ f- B) b$ Z87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
/ a& [% R- A0 W) U3 A9 U* X下面是SDMMC句柄结构体:
& h$ I: e+ A1 N! Y( r1 L% m# X0 g( p
  1. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
      ?1 u; w3 |# E' u1 ?. j; s
  2. typedef struct __SD_HandleTypeDef
    " x0 d% [1 \3 D4 ?- l) m( T" o7 S
  3. #else
    $ c$ _6 }. w0 d' p* l) L
  4. typedef struct% n" b) C2 t4 o
  5. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    / e! H( g$ P8 e- G
  6. {2 h$ g, \5 s. v/ q
  7.   SD_TypeDef                   *Instance;        /*!< SD registers base address           */: W+ c) M3 f0 U
  8.   SD_InitTypeDef               Init;             /*!< SD required parameters              */
    $ ~+ Q$ M0 G6 y; i8 P  ?8 F, E0 f0 p
  9.   HAL_LockTypeDef              Lock;             /*!< SD locking object                   */  a8 J8 v# g+ ]/ V5 ], l
  10.   uint8_t                      *pTxBuffPtr;      /*!< Pointer to SD Tx transfer Buffer    */6 M) Z9 {: u  `" e" u  E
  11.   uint32_t                     TxXferSize;       /*!< SD Tx Transfer size                 */: H- o; k' N* t8 b: B& I5 G3 p
  12.   uint8_t                      *pRxBuffPtr;      /*!< Pointer to SD Rx transfer Buffer    */0 Q/ |( Z6 L! k; P
  13.   uint32_t                     RxXferSize;       /*!< SD Rx Transfer size                 */
    9 B& ?* ~) u2 S+ v+ p6 ~: }9 o
  14.   __IO uint32_t                Context;          /*!< SD transfer context                 */
    . G& C1 ~  B* d  F- T
  15.   __IO HAL_SD_StateTypeDef     State;            /*!< SD card State                       */1 {3 s6 \5 W# O, r5 ^9 G) K: N
  16.   __IO uint32_t                ErrorCode;        /*!< SD Card Error codes                 */
    6 z+ @9 f" X( J4 S# o  t
  17.   HAL_SD_CardInfoTypeDef       SdCard;           /*!< SD Card information                 */
    + }" B: Q$ y/ e$ Q5 R2 a/ |8 e
  18.   uint32_t                     CSD[4];           /*!< SD card specific data table         */
    0 F& Q( z" N: H' d
  19.   uint32_t                     CID[4];           /*!< SD card identification number table */
    , M8 Y" Y3 w  D' ~6 h7 R$ f$ [, i, r, ^

  20. & W7 J4 G. J. ]4 ?% `9 V5 [! @
  21. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)/ u+ b3 j1 a0 q) {4 E' v5 U
  22.   void (* TxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);
    ( N2 {3 u* j. ]1 k
  23.   void (* RxCpltCallback)                 (struct __SD_HandleTypeDef *hsd);6 {+ h2 E$ j! D
  24.   void (* ErrorCallback)                  (struct __SD_HandleTypeDef *hsd);
    9 }) r# L8 S/ f4 n# ]/ T% {9 U
  25.   void (* AbortCpltCallback)              (struct __SD_HandleTypeDef *hsd);
    : [) t2 L& a4 M1 B$ q$ }+ A% b+ b
  26.   void (* Read_DMADblBuf0CpltCallback)    (struct __SD_HandleTypeDef *hsd);0 g  W5 h+ Q. g: \  @
  27.   void (* Read_DMADblBuf1CpltCallback)    (struct __SD_HandleTypeDef *hsd);1 x" A5 p7 H5 w3 l4 B% J! u; z
  28.   void (* Write_DMADblBuf0CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    , Z! [4 ~9 ~1 }6 i
  29.   void (* Write_DMADblBuf1CpltCallback)   (struct __SD_HandleTypeDef *hsd);
    ( s- T) [" W6 V
  30. #if (USE_SD_TRANSCEIVER != 0U)( ~6 N% v, @/ }  i4 O6 P& @
  31.   void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);# i8 O. h! g, x0 t0 i; g* T
  32. #endif /* USE_SD_TRANSCEIVER */8 c* d# z( r' R# I/ G" {& m
  33. ' t* f/ y# _4 J- V+ U0 D: T( D# C
  34.   void (* MspInitCallback)                (struct __SD_HandleTypeDef *hsd);
    1 k% S- X7 l* S' x) X0 M2 Q& G& a
  35.   void (* MspDeInitCallback)              (struct __SD_HandleTypeDef *hsd);
    3 R7 N, J9 B$ Z3 d
  36. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    - [$ B0 ]) R& H& I; \" C( B; ~
  37. }SD_HandleTypeDef;
复制代码

' w' Z  V# E5 c. j! x' e/ m# }注意事项:& Z' \1 g0 [- [" W
; {, V. a1 G! M( l
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:8 Y! S  L3 |9 B8 ?7 h* w" a  l

! l- o& L: o: R/ \/ T9 K  #define   USE_HAL_SD_REGISTER_CALLBACKS   1
& e% j7 ^+ a9 `: @9 P& _. D# R: T5 h5 U: t- \
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
) I) S; z# ?. x( C
7 i& E1 W/ O% L+ [, L' Q这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
& j" x8 d  z; w2 U( _6 `6 k/ B) J  D2 H- F$ E& V
  SD_TypeDef   *Instance
5 o+ a0 z! m9 t: ]6 `这个参数是寄存器的例化,方便操作寄存器。* [9 \3 M3 z  r# ?' d2 A) |
- w; a$ n  N9 J6 K/ R
  SD_InitTypeDef  Init
3 X6 @! \/ ?! ^$ E6 H这个参数在本章节3.2小节已经进行了详细说明。3 a+ f9 L. K) i

9 l* R  }+ w4 U4 d% }87.4 SDMMC总线源文件stm32h7xx_hal_sd.c
- l. B3 r# r! b- |* G* M此文件涉及到的函数较多,这里把几个常用的函数做个说明:/ H; n9 T8 S: K. O

9 t% I1 A( L* ^* z% H5 |  HAL_SD_Init+ X0 R% g* }) `1 C# ]3 w
  HAL_SD_DeInit. {5 z3 q5 ]* ]9 K% w
  HAL_SD_ReadBlocks
; b- P) _# w4 H2 ~; k$ M, \  |  HAL_SD_WriteBlocks$ w5 g1 ]7 f6 D2 `' ~1 L6 Y7 \
  HAL_SD_ReadBlocks_DMA
* b( s6 m0 B3 z* a( Q  HAL_SD_WriteBlocks_DMA+ }' L! z! Y  s7 g
  HAL_SD_Erase
  I5 W( N6 p$ \8 I
4 d- S3 h- f& R4 @; v1 p87.4.1 函数HAL_SD_Init8 v9 V  @, u8 n) v: }9 G+ M2 d
函数原型:* i* e" @: k( b5 ?

, M$ W/ E8 B2 ?: E- I4 n5 X
  1. HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
    6 E& r6 j* {2 S. \0 ~# e& D7 i5 Y: @- E
  2. {+ d" R! b' F  O2 ^; j7 G# S, l
  3.   HAL_SD_CardStatusTypeDef CardStatus;+ S8 q/ O4 T8 c5 x; k3 x% \
  4.   uint32_t speedgrade, unitsize;# b* ^0 k5 j, {! m" u) O1 K3 B! y7 ?
  5.   uint32_t tickstart;
    ; {" m  Y8 u0 I, c" l
  6. & M: N6 v: e; a3 y8 g4 w/ J) l
  7.   /* 检查句柄是否有效 */1 Q$ C- W( B! |! i! ~0 G+ C" D
  8.   if(hsd == NULL)
    & i2 E) w% o' `0 K4 }
  9.   {3 W! D( h" e* Y! D
  10.     return HAL_ERROR;
    . a6 t* h; `# c0 F  R. ?
  11.   }
      a) D4 K' e. g/ h1 f: s

  12. ) E/ u3 D) M* l$ E( C  w- p
  13.   /* 检查参数 */
    ; R+ u5 Y- X3 [% F
  14.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));' ]% d5 L9 N) y+ W7 i8 D
  15.   assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));' O' C6 v' }& a* ?  I2 [' y9 N
  16.   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));7 i9 P" e7 U) J
  17.   assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
    % G" i0 v. h# c' o9 l
  18.   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
    2 m" U4 J, {2 `; p% ]
  19.   assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));! U: R2 |$ R6 S. V* p& \0 F  _) [# }

  20. : E) ^# R7 h2 e: z
  21.   if(hsd->State == HAL_SD_STATE_RESET)! o  e4 c" ]6 n8 K% U! U$ @9 n
  22.   {; c0 c# e% L8 Z% _) m; P4 i) j$ n
  23.     /* 开锁 */
    # ^" }2 Y# k: d' f8 D0 S5 l: R
  24.     hsd->Lock = HAL_UNLOCKED;7 }* P. k9 F+ y, m3 X, W

  25. , f' }( ^" R. Y
  26. #if (USE_SD_TRANSCEIVER != 0U)
    + w% l/ l* i4 B; E
  27.     /* 兼容 */
    + D; I- V) A! l$ \1 n5 ]3 J' p
  28.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN): F7 g2 \$ o: b% Z- y* o: p
  29.     {0 f' c% H+ O; w6 F5 J& h$ i5 I
  30.       hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;# q  g# ~2 K  d
  31.     }- ^. c9 }( m( T' M9 |8 L6 o/ M! N
  32. #endif" H, |% {7 K; h+ S5 q: |
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)! @7 L8 ^4 G2 t- V; Q
  34.     /* 复位回调 */  y2 e1 z7 J+ l8 L" y  |8 R' }
  35.     hsd->TxCpltCallback    = HAL_SD_TxCpltCallback;
    * @! Y$ B$ j( q+ I- U( a
  36.     hsd->RxCpltCallback    = HAL_SD_RxCpltCallback;
    5 j6 U4 r9 L. v8 s3 `' b
  37.     hsd->ErrorCallback     = HAL_SD_ErrorCallback;
    ( `) g( b3 Z' Y$ H2 J: z, O
  38.     hsd->AbortCpltCallback = HAL_SD_AbortCallback;
    " @! |, R* v4 S" {5 H8 J, Y
  39.     hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
    & L" Q& M& ~( m8 x$ }' d# ?
  40.     hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;  @" x/ a# i2 f) K5 N
  41.     hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
    " X' f1 L& y# O
  42.     hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
    * H9 d6 m) e' g% J% L7 G
  43. #if (USE_SD_TRANSCEIVER != 0U)
    0 A* B$ R5 }( L8 p6 ]
  44.     if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    ( p- |8 I6 i% x/ ]- n
  45.     {
    . X  w  B7 R8 X5 M! R6 d% V
  46.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;* h5 O# N: l  P
  47.     }
    0 T/ O: }) D) P( T( P) Z
  48. #endif / L' d/ E, h. u, T3 E) R5 Z
  49. : T+ t! {1 E# N: o* H- ]
  50.     if(hsd->MspInitCallback == NULL)( i: Z1 B% l. D2 j( m# h
  51.     {3 B4 K; m& X5 G% M7 ~2 J- d
  52.       hsd->MspInitCallback = HAL_SD_MspInit;. J' s# I7 A7 @, Z% x7 t
  53.     }% U1 c8 _1 ^! z6 J# f
  54. 6 j+ c  A! ?$ N2 L5 d8 W
  55.     /* 初始化底层 */
      B, a# B5 D+ I
  56.     hsd->MspInitCallback(hsd);
    ; j2 @. ]0 ]" W9 i- }! {% O$ f
  57. #else4 _4 I: e. }9 ~2 O8 g2 j
  58.     /* 初始化底层硬件 GPIO, CLOCK, CORTEX...etc */( X" O  E5 S" H+ b9 S+ r5 o
  59.     HAL_SD_MspInit(hsd);( |1 i' k* r, v" `7 g+ V
  60. #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
    : U  |. W. C: U* N$ w6 C6 L
  61.   }
    . [+ y. E5 F; }' e7 `* a4 O8 G

  62. & e2 z3 C& k+ ~$ K
  63.   hsd->State = HAL_SD_STATE_BUSY;1 D/ v% L* s1 g: g5 t, s
  64. ) ^' Y) {5 @% h& O( S0 H: q" O' J
  65.   /* 初始化卡参数 */" p* A+ N! \$ Q
  66.   if (HAL_SD_InitCard(hsd) != HAL_OK)
    ) i9 z) E( V+ O. z
  67.   {7 \- ^8 [/ \+ ^& R. S
  68.     return HAL_ERROR;3 F3 g$ K9 `( v, M1 j9 W
  69.   }0 l/ l0 y$ g; m+ D* c

  70. 4 [/ x5 h  ]( _# l9 j
  71.   if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)" a3 Q- n1 E! ^5 z" [$ @* g
  72.   {
    ! h& a2 Z) V0 `& M4 n, l
  73.     return HAL_ERROR;
    " y( g2 \+ K) K, ~
  74.   }
    * H( c( S; d7 L" m+ D! K( A( B
  75.   /* 获取卡速度等信息 */, g. I5 _; b/ r6 O0 x
  76.   speedgrade = CardStatus.UhsSpeedGrade;
    4 b% o% c+ {* @3 r9 I% d/ J$ A& _
  77.   unitsize = CardStatus.UhsAllocationUnitSize;
    . j+ u+ X* W) a" Z) ~# x
  78.   if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))) Q% R: `* n" H7 m/ f5 u1 n
  79.   {, H6 u; h& L; l
  80.     hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
    9 H! T* ~% E# A( F! {
  81.   }
    + X, M& d( F) Z, s0 g* W- Q; V5 D
  82.   else
    % C8 n( f; x% M1 }7 R! q; c' s0 @
  83.   {
    9 B0 r" c: F0 W& Y
  84.     if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
    # ?  R/ N) C. J/ P7 T* \0 M2 _/ @
  85.     {
    % J! a2 c1 j, H% @, ~: V! X
  86.       hsd->SdCard.CardSpeed  = CARD_HIGH_SPEED;
    ( u7 ~4 a7 P* _: J6 D
  87.     }
      s) k8 H, f! t( u  _' V3 m1 C
  88.     else9 c3 g9 R2 a. C) S
  89.     {
    9 e. x" a# W& b% {8 \
  90.       hsd->SdCard.CardSpeed  = CARD_NORMAL_SPEED;* u2 X8 I1 G1 }7 ]  B
  91.     }5 v7 d1 v9 P( P5 A
  92. $ z& K1 i: Y( S6 v' R
  93.   }
    " A' ]' P/ U' g: o
  94.   /* 配置总线位宽 */
    8 [% R; s9 b- V; x1 {8 A& B$ V
  95.   if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)1 @8 M% C, p# S. j% r, b2 E
  96.   {
    0 B7 B( X7 |1 Z5 \
  97.     return HAL_ERROR;1 D9 z0 G) C8 U
  98.   }6 v$ f& U/ k& R0 ~* u2 H4 ^

  99.   F* ]4 h& T6 `1 d# T
  100.   /* 验证卡初始化后是否就绪 */
    + Z" {) j) q2 J  D& J* Q
  101.   tickstart = HAL_GetTick();  `! Q" e. v3 m
  102.   while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))- o1 I9 M4 f) m2 u
  103.   {8 I, X9 \$ l9 J9 z/ A
  104.     if((HAL_GetTick()-tickstart) >=  SDMMC_DATATIMEOUT)
    / C3 j4 B7 i: l  i. c( x9 Q. f6 m
  105.     {
    ! w* E5 z( |! C  O( r1 v4 ^6 k7 i
  106.       hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;, g* v5 L1 S1 G$ Z( ]
  107.       hsd->State= HAL_SD_STATE_READY;( T2 @6 d, T1 F6 k
  108.       return HAL_TIMEOUT;
    ' P5 z$ [5 i% R( a9 c
  109.     }
    5 s6 O$ d& d. F  E! z
  110.   }
    ; [/ O( ^1 ~* r1 U  c3 o1 y

  111. : [! P1 L2 j0 w6 [3 q/ d
  112.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    % L' @) Y/ M7 H" N! Q
  113. 8 `! ~/ c! k! Q- @$ S$ P4 C) l( g
  114.   hsd->Context = SD_CONTEXT_NONE;" Q5 m9 K$ G+ Y. @

  115. 1 r* R* V4 q3 H' w( g
  116.   hsd->State = HAL_SD_STATE_READY;
    + F0 n% Y+ P4 ~2 p5 ]
  117. . ?; X+ |2 E, }+ o4 H+ q0 z
  118.   return HAL_OK;
    8 |+ o- r+ G& ]1 t0 M* W- n
  119. }
复制代码
- \4 x5 d7 t9 M) y
函数描述:/ G; [6 Q! L+ }
3 T2 V2 H0 ]/ |% k, G
此函数用于初始化SD卡。3 Q  ^) w' ^: t& X

: E5 \" n' s  t) X( @/ u函数参数:
% D3 j+ m2 X1 d
' @6 k! m3 \! W& o  第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。1 X8 O; b/ r& b8 y6 g! D0 z
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
  X: u; h# e( [  q3 ^- N) u7 N
( G& z8 c: a1 n1 x0 ^# c2 m5 ^9 L0 u4 ]$ D% L
注意事项:
1 A" T/ c; W* s% L2 E  H函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
' i. W/ Y" a0 B8 _1 j4 F$ P9 e  d# c如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
( R: P+ Y, h5 B$ Z对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET  = 0x00U。) v; J5 g( g+ O2 |9 ]$ Q

( f( e' `4 {# [2 a$ [0 O2 x解决办法有三, Z1 @* i- ]$ K/ y3 x
# w" B- s: o' o
方法1:用户自己初始化SD和涉及到的GPIO等。
+ r! P( C2 w* X" Q+ E: L8 }0 X9 C7 r5 p
方法2:定义SD_HandleTypeDef SdHandle为全局变量。' @: D1 [9 K; I$ q/ {

( O( `2 \3 x; l7 d: P5 F+ ?3 U方法3:下面的方法; Y2 K, a7 E5 N

3 J; C. J7 r4 d. T/ S
  1. if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
    5 [. \$ R) G: ~4 x  X: i) H
  2. {
    1 {& R# e% a- k6 j$ {# a
  3.     Error_Handler();1 e/ @1 x! D8 R
  4. }  
    2 h, v9 a$ \9 O. e5 _! P
  5. if(HAL_SD_Init(&SdHandle) != HAL_OK)4 }& R" g  C4 M: }
  6. {
    9 K0 ~7 z) t  ~/ J& {
  7.     Error_Handler();
    * E, G3 `1 ?/ D3 D; }, ?7 ?" g
  8. }
复制代码
" f3 j! d/ S+ n& N
使用举例:& v0 \* A; ^9 n" ~
% N) l0 e' d9 b0 a7 F
  1. SD_HandleTypeDef uSdHandle;
    6 R/ ?- S2 t8 p6 v

  2. 0 U2 [! h' F: N+ n6 q
  3. uSdHandle.Instance = SDMMC1;
    : Q% [. S0 u7 P: t# H) x9 o
  4. 6 u+ _) J+ r( p1 ^# U$ {
  5. /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock. I) r. Y0 B; V; r+ k9 L, L2 }6 Q) ^
  6.      else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].1 J- y& q5 r( k; s3 u9 Z8 p- ?
  7.      200MHz / (2*2) = 50MHz, ?# O. ], Z0 Y( G
  8. */! }1 M1 q, P1 w5 F
  9. uSdHandle.Init.ClockDiv            = 2;
    , W! U8 V5 [; V4 C
  10. uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    ! ]% R* P* R2 \1 K  G
  11. uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;+ T' J% M9 u* Y) j1 l1 N
  12. uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    5 ]2 g5 ~# ?  @6 J* l6 h7 i6 T
  13. uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_4B;
    3 n2 R$ p$ G5 z/ {8 M
  14. if(HAL_SD_Init(&uSdHandle) != HAL_OK)- m+ R3 g& X0 h- {. W( G
  15. {! S3 L9 l7 Z. A/ b0 c
  16.    sd_state = MSD_ERROR;: v+ w6 E) X4 }  t, b
  17. }
复制代码

* t3 K. p) ]. O87.4.2 函数HAL_SD_DeInit

1 @* w) W% ~8 X3 I+ P  t函数原型:( c! s8 |9 A: t0 v3 e6 T

% q& K/ k2 _; L! H' T
  1. HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
    $ x) x* i! K3 p. J
  2. {+ U2 J! b) P' @; S/ k( r& l5 @
  3.   /* 检查SD卡句柄是否有效 */0 m/ h- q2 @& `5 ~( [
  4.   if(hsd == NULL)
    ' C# Z$ p! ]3 H3 w/ D6 G- `
  5.   {
    5 ~* T4 v: c  N, n6 |+ w- ^- W
  6.     return HAL_ERROR;% S8 A( m! a# s' ]
  7.   }' x( F1 P% E, L8 u' M! O' L6 G
  8. - x7 S& P$ r. z/ x1 Z/ V" O/ ^3 \
  9.   /* 检查参数 */
    . D( v* S( p: [7 s" K: }! y
  10.   assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
    1 ~4 L' v9 E: q5 q  X/ B% T! s

  11. $ S: H8 V* c$ D6 E# t4 _
  12.   hsd->State = HAL_SD_STATE_BUSY;* G: Q  g& S# c' k. ^1 k; K  W

  13. 1 w% n( X% X' P+ x
  14. #if (USE_SD_TRANSCEIVER != 0U)( ?6 y' i0 T7 a( P  m' \* _- S8 g) B+ L
  15.   /* 关闭1.8V模式 */
    7 v- l9 r' I6 p) _( @5 ^# ?
  16.   if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
    " s/ Z! `; U- }! ?5 l+ r
  17.   {8 H5 m# n' e* d& n5 o; r, R) J
  18. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    8 @! w8 k) O- |" }1 w  x# Y5 s' Q
  19.     if(hsd->DriveTransceiver_1_8V_Callback == NULL)# r- u1 k! @; X
  20.     {
    4 j+ c0 J5 L3 R3 D5 A5 h
  21.       hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
    : x/ [& Y) B: F8 M) i+ ~- e
  22.     }
    & u4 u/ _& ?. G+ o; x. e" R
  23.     hsd->DriveTransceiver_1_8V_Callback(RESET);5 s* D+ F9 ~$ d( i; Q+ ~
  24. #else
    + V6 G2 y& p- O2 Y8 _  i
  25.     HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
    ( W4 _. s) I2 e6 H; \- K% K/ E
  26. #endif
    0 f6 _3 m" F5 P7 M
  27.   }                                                                         ( ]" [( x% o# S+ ^# @2 d1 P- V
  28. #endif
    / G6 W2 ~# |8 `3 U
  29. 3 C9 N9 W+ Z, X* d& S. g
  30.   /* 关闭SD卡电源 */: ^* |5 s' w' {9 ?& c) o7 U. K
  31.   SD_PowerOFF(hsd);
    , B' h3 Z# A5 ~& ?0 v1 K6 y
  32. 6 V  D* n" d, B5 h9 X* o
  33. #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
    1 c6 H1 E8 Q  Q& H$ Z; B+ ?
  34.   if(hsd->MspDeInitCallback == NULL)1 Z* H# u+ P* K, Z
  35.   {5 m" R# k( h9 u# }4 q: y: R
  36.     hsd->MspDeInitCallback = HAL_SD_MspDeInit;
      k- }; b. F. ]+ ~
  37.   }' o2 U' c- i& H
  38. + E) _0 k% S- k' ]; N3 o3 s& ^
  39.   /* 复位底层硬件 */
    7 x3 w/ e! e% ^4 q
  40.   hsd->MspDeInitCallback(hsd);% o7 `- O5 E+ @( h& {
  41. #else9 a0 [" U+ @2 q1 R5 W& Y
  42.   /* 复位底层硬件 */
      P7 v9 U+ g4 Y" N
  43.   HAL_SD_MspDeInit(hsd);
    & E- O6 |7 N  X+ z7 P6 R
  44. #endif
    , k7 O0 {  s  U, Y) q( [7 R

  45. ' A+ ^* X" M6 D0 L% Y& s
  46.   hsd->ErrorCode = HAL_SD_ERROR_NONE;
    : m6 u1 l9 x# T5 |" l/ ]
  47.   hsd->State = HAL_SD_STATE_RESET;- ~7 S) C8 F! g, h4 ^

  48. # }/ c5 T4 E$ g: G: A3 n
  49.   return HAL_OK;5 Q5 N7 M' [  [
  50. }
复制代码
# d$ g9 r( n, T  i# ^7 ]1 o  H
函数描述:
/ R- x2 F. ~# y; T2 J/ y# j, a
" W, K! a- M: \4 X4 n5 {$ i用于复位SD总线初始化。
4 l4 w/ K1 z* w1 s* W1 a2 {/ R# K9 c  B! g( y7 x/ P. l
函数参数:4 @+ u. \2 ^' i, l( _$ U

' W3 ]6 @( Z4 B 第1个参数是SD_HandleTypeDef类型结构体指针变量。
. @* h3 H! P- x 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。  ~& d4 ~2 A3 e
! d, ]$ d* Y* O4 @7 R, H
87.4.3 函数HAL_SD_ReadBlocks# C8 L0 U6 {9 l  }; X$ Z9 o# g  C
函数原型:
, C3 Q" O6 S! ]8 L4 j
* P0 N! v; ^  @3 z- f) R
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    1 h" S; \) ?6 q: C% ]' B. |" Q5 Y
  2. {3 X  F7 q8 M& d+ K
  3.   SDMMC_DataInitTypeDef config;6 w+ _$ X+ E* J3 q( W
  4.   uint32_t errorstate;. t3 C: G$ ]! \9 c5 B& j( ]
  5.   uint32_t tickstart = HAL_GetTick();
    1 k( V/ p! b* D  w! d5 `2 Q% ~
  6.   uint32_t count, data, dataremaining;+ G, j. F6 K, L' A) n' O
  7.   uint32_t add = BlockAdd;: k; z0 J, t' r2 s0 T: F; r
  8.   uint8_t *tempbuff = pData;
    * o" |/ I5 n  z
  9. / }! `+ `* v% b
  10.   if(NULL == pData)+ {  c% {) n* e- e1 |3 p
  11.   {2 X4 W% N3 l$ J2 o7 F& k8 \. C
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    ! e/ \/ ?3 E1 l$ b: w
  13.     return HAL_ERROR;
    & S% ?4 b* r/ a4 A' f+ i
  14.   }! L  \  U! b5 T+ Q, L. S$ x

  15. ) b( m3 N0 d4 ?" V( O
  16.   if(hsd->State == HAL_SD_STATE_READY)
    6 Z7 v4 j6 T: f1 k. u
  17.   {
    # P& a5 g/ x8 e+ t& Z- ]& y
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    7 l* z4 K' N4 I, F( \
  19. 0 ~5 e7 O  E" V2 `3 m8 W0 L+ M
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
    4 C6 ^3 v' m5 @1 x' s
  21.     {8 C4 |) l$ L% v9 @
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;' Z- |- T: t  m# ?* Z/ `
  23.       return HAL_ERROR;/ A6 B5 K; Z* a! f! L
  24.     }
    * M$ E5 t, X6 w/ W

  25. 9 z6 e$ G$ `' _* R- d
  26.     hsd->State = HAL_SD_STATE_BUSY;8 g4 Q1 d! z9 t. j) y* t
  27. : C; w8 q! Z/ `+ u$ F4 Q. l
  28.     /* 初始化数据控制寄存器 */0 o5 X# @; e  [$ b( N/ R2 H' E; f
  29.     hsd->Instance->DCTRL = 0U;3 A5 v7 I; ^3 x0 O/ j, ?6 B5 e. Y
  30. 1 K: [3 ]* K, l; q, T; [
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)' \( }* t5 n- S6 Z- m9 h2 }0 W
  32.     {8 x: Y) m3 C4 y4 y- C6 i' J8 u: a
  33.       add *= 512U;
    ( H) ]$ ?( F) E6 F5 x
  34.     }
    : f+ H) F1 l9 r; L8 I/ I- |1 I
  35. . F1 P* |* N1 w1 O0 w; r8 B2 r/ z
  36.     /* 配置SD DPSM (Data Path State Machine) */
    . P; L  S' J3 Y: B# e: m
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;8 l7 r: e" }; r6 M  c: I
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;# L9 J, q" e  F1 F
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;2 p+ k! u4 W2 i5 [" P
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;2 {3 P- e& P! Z( {; L% ~
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    $ @6 L$ e/ A! U9 i* ?; {7 a
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;& n( H8 N" e( u! d
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    ' s  N" h2 _8 o; w4 [# u; b0 R& i- m4 a
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);8 T' c1 v- ~+ [! X
  45. / l4 _1 L) ]+ A% {$ I9 Y
  46.     /* 查询方式块读取 */) \9 F9 H( M' H: J% {
  47.     if(NumberOfBlocks > 1U)4 v* V" D) h7 L' F
  48.     {
    9 c- a' h5 V* K9 c' {& O# _
  49.       hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;% e* h& G0 C. x' k8 W  h

  50. / t3 Y: N# l5 ~# z2 E9 V
  51.       /* 多块读取命令 */) i6 O+ h5 Y+ f6 {# s6 ~1 F3 S' {- {6 b
  52.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
    + j8 ?) ^  U: J4 W$ }
  53.     }- {" y" F4 b& e+ z5 }3 T# [7 j
  54.     else
    6 G8 ~4 H2 \+ j' g; b4 Z
  55.     {
    / |9 x; B7 }; L' \& G/ G0 g$ C, T
  56.       hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
    ) M- q' A) G( }6 g
  57. ! n5 S7 J# B) A+ X; l. w$ \- A3 e
  58.       /* 单块读取命令 */- S0 n  I0 l+ V  |) A6 G
  59.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    , N3 W# W3 Q" Q! z5 D0 j8 g) f
  60.     }
    6 @4 Z; p+ y' J$ a
  61.     if(errorstate != HAL_SD_ERROR_NONE)3 L. H- S: M+ i+ ^
  62.     {+ [# X+ }3 h1 x0 |
  63.       /* 清除所有静态标志 */$ H. ]# i! K; q" ~4 v( T
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    4 e8 b( {% V1 z
  65.       hsd->ErrorCode |= errorstate;$ a% M, |3 [1 o3 f# N7 Y
  66.       hsd->State = HAL_SD_STATE_READY;7 _9 q3 E6 c. d3 Q# i) H
  67.       hsd->Context = SD_CONTEXT_NONE;  j5 k7 o1 A" s$ F, D, C( m
  68.       return HAL_ERROR;
    * t  Q) X$ ~, M2 g, s6 U3 b
  69.     }* _' [5 m! w1 T% b6 r
  70. 2 k- G$ E2 k0 m: b0 X. I' z3 b
  71.     /* 查询SDMMC标志 */
    5 ^' Z! a: O( Z& Y0 {1 l
  72.     dataremaining = config.DataLength;& b4 m- K  Q2 a' L. O: g- L# a, A. V
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))9 z- p9 p+ E5 [, P* |' r8 @0 q4 S
  74.     {- @3 ?% q( V. h
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
    ( J9 A9 T+ ~& M; v1 k& L3 ?
  76.       {
    ! r, [, B' B6 ^& t/ h- X
  77.         /* 从SDMMC Rx FIFO读取数据 */, e, h$ y" g0 |% t* k9 Z
  78.         for(count = 0U; count < 8U; count++)# r3 L5 A* L4 Q( ~. L1 P
  79.         {
    8 m7 v$ c% V& ~- \/ W. t
  80.           data = SDMMC_ReadFIFO(hsd->Instance);8 ?9 Z* u7 Z6 J  B3 X$ _/ n
  81.           *tempbuff = (uint8_t)(data & 0xFFU);2 t/ G1 ]" v3 m, s1 t
  82.           tempbuff++;
    0 n  b& u7 |7 ?( p1 k% S6 J9 D0 U
  83.           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
    ! o; w% n; _$ l/ t" P5 ~
  84.           tempbuff++;9 }7 P5 {* R( {2 M$ w/ l5 c; c
  85.           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);2 o! @0 u9 }$ {2 A( g' B. E- K
  86.           tempbuff++;! d1 C" f7 F8 B8 R! Y/ d
  87.           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
    % s) o; H/ Y- }0 c0 m8 p$ ^$ }4 {
  88.           tempbuff++;' _' E5 d9 o# q2 t
  89.         }
    : n$ y9 Q, @' F* u7 G+ t0 L
  90.         dataremaining -= 32U;1 y$ o7 T* }( h. g5 J
  91.       }5 ^  i& k; n' X7 R0 O* x+ G# B

  92. & L" T+ S7 [* q, A2 I4 y7 F
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    , z, J# j" |+ I8 G4 P
  94.       {% \0 p6 Z6 @* i9 F+ N4 _5 D2 q
  95.         /* 清除所有静态标志 */
    - v& D4 a) s# L/ x7 k9 }
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    # m' ?6 C" G0 n  J: w9 Z
  97.         hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;8 r3 i0 @# Q9 H
  98.         hsd->State= HAL_SD_STATE_READY;1 h& d( L1 m. r  I6 N) ?
  99.         hsd->Context = SD_CONTEXT_NONE;1 e; O0 _: `0 n! w0 p+ |! C; e
  100.         return HAL_TIMEOUT;
    3 P5 ]& t9 F3 P! R* Y
  101.       }) u; }  e' E. h3 [# u
  102.     }  @# W! W5 a  J, T7 A# F
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);$ E* K. N5 N5 C) }* |6 C

  104. . @+ z  R1 w- N4 s+ n8 Y- b: h
  105.     /* 多块读取发送停止传输命令 */
    / b$ q6 q( _5 K0 G' O+ S- b6 R
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    % X) b* R; |) Q1 T* V" p3 g. _
  107.     {% E2 c; q2 w/ r( v1 D& }# _* b
  108.       if(hsd->SdCard.CardType != CARD_SECURED). ]8 L7 T. e4 m5 ]8 i& P4 S
  109.       {
    # S' f4 b, ^, [" P% X$ ]0 i
  110.         /* 发送停止传输命令 *// q9 |; b0 I! q3 Q
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
    1 n8 L8 e( Z/ X
  112.         if(errorstate != HAL_SD_ERROR_NONE)  d3 \- i5 @/ H- h
  113.         {
    % c! T/ F2 Q- v5 I: {! p
  114.           /* 清除所有静态标志 */) ?4 ?, g8 T0 W# I. S4 I
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    , [! Q% }9 Z9 w  ]5 G2 G
  116.           hsd->ErrorCode |= errorstate;3 F( q( }. K$ k4 g' A
  117.           hsd->State = HAL_SD_STATE_READY;3 k; z& Q' ?9 [- e* ]) a
  118.           hsd->Context = SD_CONTEXT_NONE;
    + [5 F- C6 R% u% g
  119.           return HAL_ERROR;
    : u! P  {" s  S6 z+ U: B. C' {
  120.         }% F0 U) p! X( m/ F6 W0 l7 D7 t5 R
  121.       }
    ( h4 C( x+ F. G: J
  122.     }
    & s$ u( x6 e. y9 O1 j
  123. ) Z8 W& l- B, Q0 W6 V2 B
  124.     /* 获取错误状态 */
    ( z) P2 b- z/ y! g' Q1 q
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
    ! w7 Y: e9 D/ x3 o
  126.     {( w' O) l" ]+ @  X( ~* I
  127.       /* 清除所有静态标志 */0 O' x6 d& A. a9 Z: j
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    " A. P6 g/ I: c1 T; I# r8 |1 _$ K
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    4 O- }( z+ h6 I" K2 p6 k2 |
  130.       hsd->State = HAL_SD_STATE_READY;
    ( ?' t. d, i- m3 R/ ^
  131.       hsd->Context = SD_CONTEXT_NONE;% I5 c1 s3 q* j$ X  {# j
  132.       return HAL_ERROR;2 N/ p4 W$ D* x# _" U  o
  133.     }% m. q/ m$ X( M1 s0 o8 d" h
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))3 h# q6 f6 i' p; p- w! F( ?5 N
  135.     {
    ' K3 h' V- |, j; E, R# N" R4 O+ K
  136.       /* 清除所有静态标志 */
    3 |/ P6 ]2 G8 ^, h
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    9 O" c/ p3 ]6 i! X+ h9 c1 j' U
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;/ d: V3 u( z4 l" s. C
  139.       hsd->State = HAL_SD_STATE_READY;" z# p( W- B8 a; d! F" m2 N
  140.       hsd->Context = SD_CONTEXT_NONE;! ~; P0 `- W# ]) q2 {  v6 o; K
  141.       return HAL_ERROR;" U3 q$ S4 c7 E" Z" d. X% n0 @& z
  142.     }% w3 p" B  o" k1 b/ {8 @% Y
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
    ! T- |1 ]3 ?! N7 S1 W
  144.     {
    5 G3 B5 l* d. r; E( G: \
  145.       /* 清除所有静态标志 */
    ) s5 R, @+ n7 S8 J. Q! C/ {
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);9 k9 C" L. {9 S) g2 B
  147.       hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;: z1 p. c, b" F, b
  148.       hsd->State = HAL_SD_STATE_READY;  U; @- @& b- |4 z9 @7 L) L
  149.       hsd->Context = SD_CONTEXT_NONE;& I3 a, S7 r7 F, e% m! j( f
  150.       return HAL_ERROR;
    . h5 i- a8 v$ P1 b" ~
  151.     }
    2 k+ L$ g, V3 X3 F
  152.     else
    ) u- q( Z# `- K$ r% X5 h
  153.     {8 x1 A1 U$ }; X9 T) }: K' B
  154.       /* 什么都不做 */8 y7 H& x$ l# P/ \/ h) I" F: A7 l! T
  155.     }
    0 B" p7 b* E& Y8 l6 n2 l8 X# n- Z4 p

  156.   k9 T( @' L+ E  J, M2 K
  157.     /* 清除所有静态标志 */. X. X. e5 H7 r  X; ^, @+ f; ~
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);9 F) P( D$ Q/ A9 `

  159. 2 ~0 a5 a  K6 P4 o
  160.     hsd->State = HAL_SD_STATE_READY;/ ~/ J5 g: Y. o; M, M% S* ?( m
  161. # U- c8 s3 ^& X' E- W. @# `0 q
  162.     return HAL_OK;
    & O7 ?* K% w" z5 v0 o2 m
  163.   }
    : K7 O9 ~5 E% n$ F' p/ r
  164.   else
    6 j, _+ }  {# |* W9 c! F+ Q6 Q3 B
  165.   {
    + r; ?# _7 T' _1 Y+ [/ @2 ?/ F9 N
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    8 I' X0 Y7 F4 J0 G' Z' J0 F, E
  167.     return HAL_ERROR;
    + C+ g4 o! @# X
  168.   }2 v7 s( g; I, ^
  169. }
复制代码
7 r2 l, M/ ^3 ^2 J4 j- \
函数描述:4 a% i! R) D( P9 S
! d! h3 D8 a0 z4 e  [
此函数主要用于SD卡数据读取。
: Q1 F  f7 P0 T* G* i
" e: ?5 l: ?5 M- p; ]3 {1 e) d函数参数:
$ i# D! g5 [5 j4 W* j' r" @9 r5 H! j2 W* C
  第1个参数是SD_HandleTypeDef类型结构体指针变量。+ [' U; d; P* K& ^9 L
  第2个参数是接收数据的缓冲地址。4 b* C  r/ _: h( ?) w
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。' Z' u' Z( L3 H- e: A/ }
  第4个参数是读取的扇区数。0 v! \8 f- ^* ~( Q* G* z* O% R
  第5个参数是传输过程的溢出时间,单位ms。& y. K, b1 J7 N' h7 s( W
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
; N: q# J5 e8 H0 \6 t
9 k& P0 W" p% j
  m: O& R7 [: u8 |9 K7 j使用举例:
8 h; X/ c1 C" l0 l& n  A4 ]: j% Z+ @4 Z3 ]' |1 e# `
  1. /**
    8 m4 N% ~+ W. u# c$ i
  2.   * @brief  Reads block(s) from a specified address in an SD card, in polling mode." B2 l; S2 S" N5 l+ |# y* N
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit1 t& A7 i* F0 K9 r" l
  4.   * @param  ReadAddr: Address from where data is to be read
    - A& r4 I" }! q5 t# e0 S0 X1 r
  5.   * @param  NumOfBlocks: Number of SD blocks to read
    ! f* ~' L3 V% z9 {. t& Y% N  E
  6.   * @param  Timeout: Timeout for read operation! N- r6 d1 Y% X: u
  7.   * @retval SD status
    3 ?5 l) ~8 s: B- W" P2 R
  8.   */2 h9 ~, ]" e4 b/ Y
  9. uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)9 R% Y) |+ ]: L* G4 S+ l" p
  10. {
    9 \. ]( s* e! S( k0 e; }

  11. ) b# t) M, `! |
  12.   if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
    * U& o6 r+ W6 D# M7 L8 H
  13.   {
    / Z+ _, _3 h, D" }! W
  14.     return MSD_OK;
    9 E9 ]; K& R* M* p$ X% F4 M; k
  15.   }& r5 {* a: b1 k: L: J. F
  16.   else- F% R: G  L9 A1 a+ j' ?
  17.   {0 l5 w$ E* F3 H1 B3 e, T
  18.     return MSD_ERROR;
    ! {$ y4 g- C$ O% B9 d* e
  19.   }
    * s; V4 D9 y4 z: Q& b0 g/ T: W
  20. 8 T( G+ g, l' ~  e
  21. }
复制代码
6 ^9 g6 d8 g: j! M& H
87.4.4 函数HAL_SD_WriteBlocks( K) H- _# W0 }, z" }
函数原型:
8 F  c, X) ^* U* o1 R- a7 \
( |( Q- ]# z$ p2 L. ^2 ]4 E- @* _. u
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)- ~$ N5 T2 P+ E6 i, v3 x: |
  2. {
    8 ~* x. E$ O$ B. c! E2 a4 Z0 K
  3.   SDMMC_DataInitTypeDef config;
    : s$ Y8 r6 W9 f) t
  4.   uint32_t errorstate;3 N5 a/ u# T1 D" r
  5.   uint32_t tickstart = HAL_GetTick();3 {2 f0 f; `6 u3 _% r. s
  6.   uint32_t count, data, dataremaining;
    0 L3 t5 C6 h; u# ^. F: o$ ?
  7.   uint32_t add = BlockAdd;
    8 H; x- j$ W9 b- i5 D. U5 f; @5 P
  8.   uint8_t *tempbuff = pData;' I/ W2 B4 F, k2 j: c

  9. 0 ?+ Y3 J/ t+ q7 J
  10.   if(NULL == pData)
    2 P9 H; o9 O, r' A" I* R0 R2 l
  11.   {+ }' m6 r! d. b" a
  12.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;3 u# \" @$ w! H& r/ Z% }# R3 X8 I# ]
  13.     return HAL_ERROR;
    / u+ ]: o% D1 `
  14.   }
    $ t0 g$ }% @, K# a8 ]- }5 k7 O
  15. $ o) |, M2 B" ^7 J
  16.   if(hsd->State == HAL_SD_STATE_READY)
    : x& M* [4 y3 Z8 {
  17.   {% k" ^5 U2 ]) p. Y; ?: S& ^
  18.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    + o3 i1 _9 U3 @  B

  19. ' Y1 b* a8 a! {6 Y/ |  `
  20.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))3 [( |0 }) N! ^$ r' u3 `' a0 L
  21.     {
    ) Q9 i: {0 W/ Y3 {* q' {
  22.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;+ h5 k2 I5 C" Y! c" e
  23.       return HAL_ERROR;, i- `4 x% f3 h- k
  24.     }
    7 N' y% s  {5 `0 i/ }: ~
  25. 6 z" ^0 k2 ?! @1 d) _9 q
  26.     hsd->State = HAL_SD_STATE_BUSY;" m! q1 n6 w0 v" o, J3 ^0 j

  27. & u( i1 S( S0 r! k
  28.     /* 初始化数据控制寄存器 */
    . N( P6 c+ ?# W0 k5 C- R" l! T
  29.     hsd->Instance->DCTRL = 0U;: G$ {* k, e' z  U# z+ g6 U

  30. + s4 O" M0 a' Y) G
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)* H( V" q  H4 P9 e, F) U5 t
  32.     {
    " ^. o2 k. U6 M" G7 Z% L- t
  33.       add *= 512U;. f: I( }; Q7 s
  34.     }
    7 o4 T) F: }6 V' G; u3 q5 x
  35. $ Q. `6 `4 m5 ?" m1 [5 n2 s
  36.     /* 配置SD DPSM */' C1 ]2 l6 h) C3 c# W3 A- z
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;! A: m- G1 a$ J" }  m. k
  38.     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
    . X4 h% w" p9 i( V$ ]
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    0 i. g7 ^. Y' a+ G
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;8 r8 z7 v0 ^6 p0 m, ~7 U' U
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    % a3 k: Q' V/ F  [' Z
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    - \' Q! T+ ]' |6 M6 X5 H4 ^+ D
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    5 R$ ]5 n* b# v. Q7 O( Z9 ^% h
  44.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);, x3 D# e) l# Y+ g4 P/ H6 x! N* ~

  45. ' G$ y% {' k3 y: T8 p9 g
  46.     /* 查询方式块写操作 */
    : L1 e0 [, S9 K* n2 L
  47.     if(NumberOfBlocks > 1U)# w/ V( D8 P; c) _6 Y* a- v4 t
  48.     {
    5 t1 S2 q$ ]. a" H: a  f
  49.       hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;3 ^. q6 F6 N# A5 Z$ p
  50. / k) S4 d% R, w# l: `
  51.       /* 写多块命令 */
    7 X( y; T8 s; d! j
  52.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);* U, a( |# l! P5 a8 J; U
  53.     }8 S0 v$ s: J$ H
  54.     else, t( {+ i6 ?! [8 @7 s% i* P# M
  55.     {' e) Q3 A( Q5 P' i! Y
  56.       hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
    . S1 Q  X& B, d2 A! P( d# u) |

  57. " z. b: s, Q* E0 P
  58.       /* 写单块命令 */
    * `. `) f9 M) v0 X, B1 q
  59.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    3 `/ q5 d, @. Q* V. d7 V9 Q' D* {
  60.     }; ~+ e. X3 E1 F& {# M0 g+ G% U
  61.     if(errorstate != HAL_SD_ERROR_NONE)# S0 B5 m! q9 X0 H
  62.     {
    , t8 p' B/ F+ Z' r; V8 c! D
  63.       /* 清除所有静态命令 */
    / N. N: q4 x' y. G( D& t+ x6 s
  64.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);4 Y! z6 ]" d6 E! D
  65.       hsd->ErrorCode |= errorstate;
    : M/ e+ f0 I+ Y+ d. q/ V5 b
  66.       hsd->State = HAL_SD_STATE_READY;
    0 S' p( b6 g9 v* w1 x/ T
  67.       hsd->Context = SD_CONTEXT_NONE;& q7 i) s6 J" l5 @
  68.       return HAL_ERROR;/ m) l) F1 x# H; Y# q% E7 k& o8 ~8 H
  69.     }' [# ?( N! W9 N+ o5 V- F

  70. # F% U/ q* D4 L0 S; z! N
  71.     /* 查询方式块写操作 */. a( V( Z7 \4 K6 l
  72.     dataremaining = config.DataLength;
    1 Q9 R. w, Y7 w  Z* w8 Q
  73.     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))$ [/ n1 s: |+ X( u, r- S
  74.     {& ?) s2 b4 B$ t! }+ S
  75.       if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
    % h# t" B+ C* h3 ]
  76.       {% |7 G: ?8 w3 i/ x0 }# W" {1 F: I
  77.         /* 写数据到SDMMC Tx FIFO */' ~3 I. c' J) L/ j) O, [( s; U
  78.         for(count = 0U; count < 8U; count++)
    ! P" \, o/ A  V' {
  79.         {1 Y! [) H+ `4 l! ^1 E# ~3 P0 `# l
  80.           data = (uint32_t)(*tempbuff);
    2 K2 z" k( L* s
  81.           tempbuff++;
    9 n" Y7 Q( [( C* c  e
  82.           data |= ((uint32_t)(*tempbuff) << 8U);/ r' t0 [( g$ a1 Q4 T
  83.           tempbuff++;
    / z% X* d. S; W( j' f7 N
  84.           data |= ((uint32_t)(*tempbuff) << 16U);
    % v0 c& r8 X# _  q4 c, A8 D, i8 k
  85.           tempbuff++;
      \3 y' t5 Y& x  a
  86.           data |= ((uint32_t)(*tempbuff) << 24U);
    $ B& N% O+ h: D
  87.           tempbuff++;! i3 V$ s0 i. B5 G' v4 k
  88.           (void)SDMMC_WriteFIFO(hsd->Instance, &data);- p9 q8 u& H& ^' P/ V' v; f
  89.         }
    % U, g3 U0 [& V$ Z! U0 i8 C
  90.         dataremaining -= 32U;! ^; u2 T5 m* a$ |. u* h# F" _
  91.       }
    ! B0 ]  p: B5 l, y: I' \
  92. 1 m$ O7 d6 F! N
  93.       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
    5 r/ s- m$ j9 O8 T$ |8 d3 m* N: }; E
  94.       {
    ; R6 Y5 h6 j% w
  95.         /* 清除所有静态标志 */! l! e2 d. J- `( E$ B- f
  96.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" Y1 W0 ~  J) b, K0 o; j
  97.         hsd->ErrorCode |= errorstate;
    3 d. ~5 I0 R' e1 i. A
  98.         hsd->State = HAL_SD_STATE_READY;
    0 x8 z) r( Q9 A2 w1 E0 U
  99.         hsd->Context = SD_CONTEXT_NONE;
    1 }+ v% H; z3 I! @; h
  100.         return HAL_TIMEOUT;  y' D( o! A$ k
  101.       }' t* f3 z* K6 s1 v/ n6 r9 y+ g
  102.     }0 @4 R+ c/ \$ V* {; d2 @
  103.     __SDMMC_CMDTRANS_DISABLE( hsd->Instance);! L+ z5 h2 r3 N/ n
  104. " v) ]# L7 u+ {5 c4 L' L  m
  105.     /* 多块写操作,发送停止传输命令 */
      d2 I3 i6 ^* G% G$ a, {4 o# t
  106.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
    ( p$ ~4 X: w' q- O9 R3 T' m
  107.     {
    8 k9 P4 Q) }. j8 E
  108.       if(hsd->SdCard.CardType != CARD_SECURED)* S8 _- S% d- Z1 f( T
  109.       {3 Y" L" [% i- r' e
  110.         /* 发送停止传输命令 */
    2 _: c6 T# v7 |# s' W4 c
  111.         errorstate = SDMMC_CmdStopTransfer(hsd->Instance);$ v0 w9 C1 `- o( I& P4 I
  112.         if(errorstate != HAL_SD_ERROR_NONE)) V$ S, E1 H9 C' T
  113.         {
    - e4 `; u$ `) ~) d0 ?6 E+ R
  114.           /* 清除所有静态传输标志 */) J) B% m0 `( j5 ]
  115.           __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);" m. s% `% ?: H% G* ^3 Z
  116.           hsd->ErrorCode |= errorstate;
    " h) C& ]; h2 V! v! ~8 i
  117.           hsd->State = HAL_SD_STATE_READY;0 ?1 N. X5 p5 J# }% v( L
  118.           hsd->Context = SD_CONTEXT_NONE;3 H7 w7 Y9 X3 g1 k! z
  119.           return HAL_ERROR;) ]  }) b% B% z9 @( G& o1 i
  120.         }, e8 a7 T$ k1 x  d
  121.       }
    6 s6 j8 Z$ n' E7 u+ Q0 Y5 P7 M- w% \
  122.     }
    6 Q3 i+ |3 p6 s  {) g
  123. ) _1 A, ?: x$ h1 h/ E9 w' w6 m
  124.     /* Get error state */
    : l; I2 H3 w$ l
  125.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))' Z; {( a6 @( D4 D& b
  126.     {
    2 b1 Z& p) d' }+ ~1 g
  127.       /* 清除所有静态传输标志 */; V/ ]5 C0 {" a& U$ k" D& _7 {
  128.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    6 `- z4 a0 z0 T8 W$ Z
  129.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
    ! o9 f- w9 [3 v0 a
  130.       hsd->State = HAL_SD_STATE_READY;7 ]  Z* K1 ?4 `1 `7 F
  131.       hsd->Context = SD_CONTEXT_NONE;& t% ]; ]$ p: h  l( K( e* F
  132.       return HAL_ERROR;
    / w9 C9 z9 Y; J" E
  133.     }
    / W5 w# _( B5 l1 T" p8 a3 f
  134.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))0 K1 W. `1 t8 u2 c5 ?% T
  135.     {
    $ U6 D# K2 w8 `1 P) j
  136.       /* 清除所有静态传输标志 */- G1 y- {' s, }8 a' @+ E
  137.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    3 m! F+ D1 R  M8 z
  138.       hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;2 l3 u* W9 _4 y
  139.       hsd->State = HAL_SD_STATE_READY;( [7 Y- B% A; B9 a  g' k+ }% f
  140.       hsd->Context = SD_CONTEXT_NONE;
    + Z, }, i& w# E* S8 k
  141.       return HAL_ERROR;2 M6 `/ N! B: Q
  142.     }
    6 m: i  p+ w7 g# d3 M$ r% B# k$ o
  143.     else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR)), ]% q2 B1 V+ S% n1 _' ]
  144.     {
    1 [% ^3 ?+ v- M
  145.       /* 清除所有静态传输标志 */) f5 R. f! Z7 m* k; {: T* Y
  146.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);* A7 Z* \* `$ u6 V
  147.       hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;5 ~6 P7 X5 v1 ?) o6 [5 e
  148.       hsd->State = HAL_SD_STATE_READY;! I8 d: Y( M' M, S' N, B
  149.       hsd->Context = SD_CONTEXT_NONE;
    ! N! [. C# _' G' g1 X- f6 z
  150.       return HAL_ERROR;
    # C5 |# n$ ^# s- P+ J7 \
  151.     }4 b, O5 L2 I$ s0 M8 A' I1 [) `3 L
  152.     else
      C( _% l' ?- x
  153.     {( z, H. l* ]9 Q; J# q
  154.       /* 什么都不做 */
    ; _$ T# `+ A  W, ?7 j8 g& b" M) _8 a
  155.     }4 t& U! l- o* d0 @9 G/ k) z/ W
  156. + M8 J7 w  E  j0 ^
  157.       /* 清除所有静态传输标志 */
    . K5 r5 _% H: F* ^  @$ Z+ k8 `# P
  158.     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);3 k& J2 j! |; t. R6 s& Q7 T7 _
  159. 3 b# l9 y& G+ m9 c8 K
  160.     hsd->State = HAL_SD_STATE_READY;
    1 ~1 @% }# V4 S) I4 v% ^9 P
  161. 7 K+ ?  S7 U$ V' ~1 i( A
  162.     return HAL_OK;
    9 K1 e7 i: O! m' A9 B6 l( n
  163.   }0 v5 {  s/ {& a! C' M7 x2 C
  164.   else
    6 E2 C% U" O( c9 Y( U$ q, m
  165.   {
    3 W7 ?( ]+ u' D" d0 j8 e
  166.     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
    + H; r+ r8 ~' q6 U) f" K( C. ]
  167.     return HAL_ERROR;
    0 p9 {$ G" C0 ~+ v4 l
  168.   }
    9 o0 T5 n+ ]0 l7 W
  169. }
复制代码

* I- Y  C/ b' c( A1 r, _3 s函数描述:1 f' _& F' @! W& c/ s2 E( R

; q! I' c/ I+ S3 M0 p. t! k此函数主要用于向SD卡写入数据。
6 U% Z' B7 u1 q' |6 s6 P. a5 r' c
: v2 v$ W2 d& c# ^+ J7 s2 g函数参数:
( x% \0 {$ B1 P% v' S5 B* }6 H
- V' d3 G5 q" V  第1个参数是SD_HandleTypeDef类型结构体指针变量。
( I7 P4 |. |% p5 Q4 }- S& I  第2个参数是要写入到SD卡的数据缓冲地址。% A, e. A9 Y2 Q
  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
/ W4 G& [9 |% i2 `1 k' b  第4个参数是读取的扇区数。
7 i  s. j4 [- Z  第5个参数是传输过程的溢出时间,单位ms。
1 J& ^- d  K) J' q% [4 d  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
1 O  i1 O) F5 v% r
0 m4 w: Z$ l( G
' A4 x+ D0 o3 x( v0 p0 \' A, t使用举例:
/ V1 ]" V# l9 Z  k# {! q9 P" ~: d4 q6 P3 Z' Y, M
  1. /**4 P- T( N% R3 I/ {& L- L% T
  2.   * @brief  Writes block(s) to a specified address in an SD card, in polling mode.
    ( L9 a  T0 ]4 K" T/ m
  3.   * @param  pData: Pointer to the buffer that will contain the data to transmit! Y! Q( [5 B1 p0 h- X* |" c0 u
  4.   * @param  WriteAddr: Address from where data is to be written
      U1 u# L! g) K3 {- T0 y1 d. B" B
  5.   * @param  NumOfBlocks: Number of SD blocks to write* _: H% o# T; h9 e: s7 e! x
  6.   * @param  Timeout: Timeout for write operation
    6 D; I% k! O; u! h5 Y
  7.   * @retval SD status
    $ B: F3 A$ H$ f3 x. K6 u
  8.   */5 u2 |: R) B/ X' W
  9. uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout), @4 F% y  n& J& [
  10. {( R' r+ s5 H0 d: h+ @5 C
  11. 6 w( g2 e7 w" N# I
  12.   if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK); F1 K0 G, v. W! f6 m- }
  13.   {
    9 Z* N  y* S' b( b
  14.     return MSD_OK;3 ~  w8 z2 h0 t' C" {, X9 `7 p
  15.   }; _0 N4 L9 }8 h0 Z( n! c3 L
  16.   else
    * A( \" O2 w5 U, a# J! [6 S' `
  17.   {8 d% m4 G6 u! |2 _' W! H
  18.     return MSD_ERROR;2 U' [/ c9 d3 V# h
  19.   }
    % e) w4 F; g, J( N2 h$ Q" f
  20. }
复制代码

; m+ L. Y2 M: q1 d2 y87.4.5 函数HAL_SD_ReadBlocks_DMA

  ~1 e1 I4 x5 `7 }- I  O函数原型:
# ~) y- Y! x- T4 o4 P5 Y/ S: t6 f/ x1 y
  1. HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    9 b* [) {9 F% j, s
  2. {/ }- R1 w, n7 r2 G( l! w
  3.   SDMMC_DataInitTypeDef config;
    7 c2 _) v$ E2 \7 G" A* e
  4.   uint32_t errorstate;
    ) K1 c* |, P5 e/ G* N; c6 w. k
  5.   uint32_t add = BlockAdd;9 s* h6 i# f3 S

  6. - n7 o( D2 N5 l' E- E" W) X' w) z
  7.   if(NULL == pData)
    + w1 }, q6 o+ Z7 y1 L* \4 d
  8.   {
    4 h2 I; \) s' F; `7 a( u9 w  A
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    ' o2 \* r- R: p( Y8 d' Y: O
  10.     return HAL_ERROR;) L% M6 z: E" q* m0 P' g* y: P: ^6 Q
  11.   }, n' b2 ^2 u' @) i4 e! h

  12. % h1 Y. e7 K1 a2 B7 @9 E
  13.   if(hsd->State == HAL_SD_STATE_READY)
    & }( d$ N7 v$ }$ r
  14.   {
    + S& L5 i/ M# r* o
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    % `9 y/ @# c( M: I* V# j1 X% A3 I5 k

  16. # d) [, @& L, V2 x$ ?* a
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))2 ]4 M' d0 L4 Y6 r9 ?1 A1 d
  18.     {
    * b( G' R1 O* I, U# Q5 f
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    0 M% j* z9 t  P* d, Q
  20.       return HAL_ERROR;
    * m% p" e6 y, D  A3 C$ D
  21.     }
    , O* n6 a2 J, i3 Q
  22. 9 @$ L9 L# O5 |7 `
  23.     hsd->State = HAL_SD_STATE_BUSY;
    * W3 [+ T4 B* y* Z9 `+ ?7 M1 B6 D

  24. # A; @) ?8 o0 Q: `1 p" {' b
  25.   /* 初始化数据控制寄存器 */
    , ?1 V" A8 e# N+ n; r# c% O" z
  26.     hsd->Instance->DCTRL = 0U;) f2 q- {2 W/ A9 U

  27. 1 @+ ^6 T) t# g) g# C
  28.     hsd->pRxBuffPtr = pData;
    ) a4 g; j7 n& X0 g9 {8 X" J; |
  29.     hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
    8 G8 e4 H, f' u6 c/ Z! \; t
  30. 1 p6 M0 l9 a; t1 d
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    ' `6 y* R4 o# j. f$ w8 i
  32.     {
    ) b! i; \7 ~2 l  i; \: T
  33.       add *= 512U;
    % i4 z! k8 [/ d( ^/ k
  34.     }
      m8 \9 N2 Q: k* ?( e3 \. A% F- O
  35. . W5 K; T: t* @; ^/ J
  36.   /* 配置SD DPSM (Data Path State Machine) */
    , e, g/ x  Q9 l  k
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;: m9 r& ], o# R+ u: v. Z
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
    7 c9 {. Z) H8 q5 L; l  E8 U7 ?, }
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;( K2 F+ q' V) E+ j
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;- ~6 i" o$ i, C( ~8 I4 L9 \8 s# M
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
    4 @2 H1 y5 ~7 [" Q0 ]3 n- ?
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;
    4 t& [1 a) H  K
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);* Q+ [/ V  J# U. H- B7 F5 q

  44. 9 R9 T: P# L- ~) T' }/ H' J
  45.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);& s/ g8 i; S* W* r* x
  46.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;& r' f8 ~  o0 Q7 }6 [
  47.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;+ B, M# A7 N, l% h" `# ~

  48. # }; i# X. i7 \1 `! k
  49.   /* DMA方式读取多个块 */
    0 V" m. C7 O% X' t, ]% e' r& S' B, s
  50.     if(NumberOfBlocks > 1U)
    6 M+ d( w: }: o& ]  \& E
  51.     {
    * C+ b. E" u' S8 h+ \* o8 N" V  n
  52.       hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);. z+ q5 C) q9 H3 e
  53. / `- ?$ ~+ t6 t
  54.    /* DMA方式读取多块命令 */7 t3 B* g0 S4 v# n8 l  L
  55.       errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);4 T, |% p3 Z& r' `4 X( L
  56.     }
    9 u. c" ^. A% q
  57.     else
      P" T3 f) T4 x( b' \
  58.     {) h7 J  k) \2 q; w  }' a7 ?
  59.       hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
    0 h7 [# y/ l+ O& S8 ?7 i# V
  60.   @! h" u5 n! i/ i4 P  ?$ e
  61.    /* 读取单块命令 */1 S8 W9 D8 a+ ~8 n
  62.       errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
    : J% S2 L1 u  a2 y- _
  63.     }
    ! X) P, O+ j9 J1 e
  64.     if(errorstate != HAL_SD_ERROR_NONE)8 [# R2 x/ B! L' d, C, h, |7 C
  65.     {
    7 A8 L( P" ]* R- E, S' l
  66.    /* 清除所有静态标志 */- u: a2 {( n. E1 _
  67.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);: \( |+ p0 p, }+ V* X7 B
  68.       hsd->ErrorCode |= errorstate;5 c, d" a  w1 x" [% |
  69.       hsd->State = HAL_SD_STATE_READY;
    , @: Y& t: @- u& ?3 y
  70.       hsd->Context = SD_CONTEXT_NONE;# A, i7 y3 o8 ]$ n. }! G0 }0 R2 G, N
  71.       return HAL_ERROR;
    7 @6 Q3 i" x+ N8 [& B6 m
  72.     }
    / ?) V- x1 z/ e

  73. * |3 y; {9 \9 ?6 K& f
  74.   /* 使能传输中断 *// k" \2 U/ H6 K
  75.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
    * b5 [0 x7 F$ d& R% |. N

  76. 8 M% R' S. `5 g3 ?% j  M
  77. ) J( y8 |3 _* k
  78.     return HAL_OK;
    " C' o) h8 Z. M& y
  79.   }
    $ l' y  t$ j$ s; P( ^$ Q
  80.   else
    8 X0 M9 [1 `0 J3 n* Z+ n; D: g
  81.   {
    9 @6 `2 e( b% n0 p) C) p+ x1 u! j9 x7 _
  82.     return HAL_BUSY;4 }$ R+ R1 d8 f/ X5 ?# n: {3 J# j& {
  83.   }! {1 }" K# u# T2 W6 _" C$ z
  84. }
复制代码

0 j# e5 V$ o% t& D函数描述:
3 N* i% t3 E! @( z$ D8 h) u+ e3 ?' ?
此函数主要用于SD卡数据读取,DMA方式。
( u  t$ P3 ~" W. S! L$ J+ ?1 C4 T# D: c: {# F
函数参数:
1 d8 t5 x/ s: p# r4 q* v5 _& [6 {/ t' ?& A! [; K
  第1个参数是SD_HandleTypeDef类型结构体指针变量。% E( m; y! q: `$ K
  第2个参数是接收数据的缓冲地址。5 P, h% G; V% p2 B2 p) N
  第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。: }( A- R- I$ M
  第4个参数是读取的扇区数。
- q3 |" H- x& }4 I7 B& i0 L  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。+ s- C# z- Y$ J  R% h
& m+ @' z7 w$ J8 ?2 [8 c8 B

! ^6 @& M4 _2 n& g使用举例:/ G7 p* j& j  D- V1 R

) T) i* G7 I& {& [
  1. /**& a9 V6 o0 e$ e4 ^8 z9 R9 [( m( H
  2. * @brief  Reads block(s) from a specified address in an SD card, in DMA mode., j2 F2 H/ B8 Q$ A6 Y8 J4 v" t
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit4 g( e' i! h6 \6 O! e3 C
  4. * @param  ReadAddr: Address from where data is to be read
    - q+ r. ^7 B2 Z. G2 q0 k- a
  5. * @param  NumOfBlocks: Number of SD blocks to read
    3 l2 }1 h6 A7 x, T# F) x
  6. * @retval SD status3 [2 ?7 @7 A4 C  z3 u
  7. */) }3 m" j1 p" N; k# y, f* x
  8. uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    - s' D9 \. s6 z% W
  9. {. ~% b. o  \. a) \% n7 h, j: w
  10. , O% r0 w9 V' _3 V" o6 i9 Z
  11.   if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
    " _8 P( ~  o8 l4 J6 H7 z. X+ Y3 }
  12.   {) Q5 t. _8 h/ [' \
  13.     return MSD_OK;$ z( |4 X5 x4 e
  14.   }3 _  J$ o' @' F/ v$ ?5 e
  15.   else
    , f! i( ]5 O/ W
  16.   {! h3 }- X( C: v; }. \8 [
  17.     return MSD_ERROR;2 O* R, P( |1 W/ N8 B
  18.   }
    ; g) b( o/ u6 ?; q" n5 D
  19. }
复制代码

" A3 _9 r; d. \' z87.4.6 函数HAL_SD_WriteBlocks_DMA: b9 ^3 H7 A; e, Y) D
函数原型:8 ]% F' W: q8 x- F0 M
" O% g6 y! u0 N7 i! |
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
    7 x: X1 n8 r, w  a& M
  2. {
    4 k* C" u7 k2 u7 f+ ^  F& M5 i' N
  3.   SDMMC_DataInitTypeDef config;& M" ?6 y! n# S8 w  E+ M$ ~/ r
  4.   uint32_t errorstate;
    0 z! ^0 K2 P, h/ a: ~' ?
  5.   uint32_t add = BlockAdd;  [  b4 x3 \  @2 q# @& D
  6. / ]) O: C; [7 E2 L, s7 E
  7.   if(NULL == pData); U& {: U' S5 B
  8.   {
      e+ i/ c8 C/ D7 k2 L7 Q5 p3 U! d
  9.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    % W% N! I+ J. q3 N* y. Z
  10.     return HAL_ERROR;
    : \! s% L) y# _9 j& H
  11.   }
    , P- V. {' G/ @+ G4 [, s; ^" {

  12.   E) s+ f% X' N. M
  13.   if(hsd->State == HAL_SD_STATE_READY)* Z) h' R3 R1 k6 M8 |
  14.   {
    $ Y1 X3 M! U1 V
  15.     hsd->ErrorCode = HAL_SD_ERROR_NONE;7 i: e5 A. T2 L) O

  16. 0 e/ c! w* Y. [( G
  17.     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))) r# P  F( \* C
  18.     {
    , Z  r9 }2 P7 G' ?! p
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
    ; f0 P" z7 @0 ^0 Y3 T. Z
  20.       return HAL_ERROR;
    / N! Y, q% K( o" g" W9 [; J
  21.     }+ H8 N$ [; ^+ K

  22. + R; t; V' f0 `9 a) ]& C8 E
  23.     hsd->State = HAL_SD_STATE_BUSY;
    $ A; k& q. z  \5 i- ]6 j

  24. 3 A6 h; k  W  [- X& b
  25.   /* 初始化数据控制寄存器 */
    - e; U* g# M7 s% p% N" v5 a
  26.     hsd->Instance->DCTRL = 0U;  t# ?: \6 \3 ?+ X2 e

  27. & g' Q) k# u+ e5 n1 V0 x; V
  28.     hsd->pTxBuffPtr = pData;: R- v) p$ L+ `5 C6 P6 K8 b1 G
  29.     hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
    8 A+ \' ~2 A; G* K; z, R" }! I$ n
  30. ! f4 S8 {! Q0 ^, W
  31.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
    3 E6 ~9 @# o" L9 P
  32.     {' z0 b7 u9 p0 v: O0 n' I
  33.       add *= 512U;
    6 A) I* j) B5 G7 H! P$ b
  34.     }4 u. `# N1 ?6 y  |& t

  35. & M2 q: A& s6 }0 M# `
  36.   /* 配置SD DPSM (Data Path State Machine) */
    4 X3 y* H/ P+ n7 K: q
  37.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
      n: ?" ]2 G3 W* u* Y8 q
  38.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;/ o4 \' J! g& r* [
  39.     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
    % v, w. v# c6 X+ k. K, ?/ b& m
  40.     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
    * y" V% f  q) _, b( g. B% o
  41.     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;5 |5 \. |6 f  |" ^- p
  42.     config.DPSM          = SDMMC_DPSM_DISABLE;  n& O% A+ f( {* _% M; B+ C5 r; M
  43.     (void)SDMMC_ConfigData(hsd->Instance, &config);
    : Z  `! B$ X, P5 {. B

  44. * h! Z& J/ O* U' j
  45. ( G- y7 s! `# w8 }; c% m- T. Y
  46.     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);# U% J9 e* v1 u
  47. 6 c1 y3 T1 U5 f2 Z
  48.     hsd->Instance->IDMABASE0 = (uint32_t) pData ;
    1 m* X; `3 w& i, ]8 U' x
  49.     hsd->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;6 d7 I5 H3 ?/ v+ C( G( {3 \
  50. / P9 J) {& g1 Y& m
  51.   /* 查询模式写块 */' c; T; u. v% g9 d
  52.     if(NumberOfBlocks > 1U)
    8 \! S5 Z; G/ t# w5 j" @
  53.     {
    ; Y2 s1 @5 y8 e0 X- ]+ ~% z8 C! A
  54.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
    / }4 {" n# P( k$ f0 j6 Y6 m$ v# C; O
  55. : H$ @3 r5 A4 G1 t8 C
  56.     /* 多块写命令 */
    9 X6 n( X2 f  E; J2 I, I: x
  57.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);& f0 _& I$ w& g% i4 K& M$ Z/ l2 f
  58.     }
    ' y9 J# E2 H4 e: Z, b/ N
  59.     else
    5 j% t. G* T6 {' }# f
  60.     {
    + i+ z6 G! {' g% q$ U& D
  61.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
    5 U9 A7 r3 J; t+ J0 N$ C( t; @' x

  62. ' m2 Q1 ~+ ]) ?( l+ w
  63.     /* 单块写命令 */) {9 Q5 F' d+ \' _* x' a+ J" `) {
  64.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
    ) c# \- r8 R2 N/ M' n' `( t
  65.     }& {3 N* m+ `& D2 ]
  66.     if(errorstate != HAL_SD_ERROR_NONE)
    5 P% @! ]1 c% E0 T- _) [
  67.     {
    1 Y' f$ _, _5 R( s7 M
  68.     /* 清除静态标志 */7 v4 n1 G! `+ w) S
  69.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    + a9 A7 r9 y4 x! @# E9 h8 b( e( |' K/ E
  70.       hsd->ErrorCode |= errorstate;! b: d8 g% |$ s" X7 H
  71.       hsd->State = HAL_SD_STATE_READY;
    5 A" i# O: s6 F" e: B
  72.       hsd->Context = SD_CONTEXT_NONE;  D4 v- c# L( W3 }) g# Z9 d$ K
  73.       return HAL_ERROR;
    0 ^& M. ?1 C$ D* p9 a
  74.     }* f0 a4 J5 G4 q% R2 C, l

  75. 0 W$ y4 N% Q& n4 C
  76.   /* 使能传输中断 Enable */
    6 }/ {. C) h6 u) H( e& y/ s% g
  77.     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
    # `% f. {2 x! \  L
  78. ! J1 L( a' ^. W
  79.     return HAL_OK;
    # v3 w- f, P, F& ~
  80.   }; s& l/ h- g& S/ v
  81.   else: B* b! w: o, o7 ^0 a% E
  82.   {
    4 i7 Z  u. [. ^1 O
  83.     return HAL_BUSY;
      }( L4 b5 Y9 K  l0 J9 X8 _$ [7 T4 J
  84.   }+ M. L; _7 T' u4 ^& S
  85. }
复制代码

. g( ~" }. Y! x& R7 c函数描述:9 Y6 t3 k! D3 d
/ k, K+ a" c) N$ T! E
此函数主要用于向SD卡写入数据,DMA方式。
+ F' Q% k+ q  v2 |0 }, z2 t" r& V8 r9 @, N& }& `6 B! o
函数参数:/ R, `& x) h' a( N+ S) c- g- K4 K

5 b6 O2 u: Y6 q1 U$ h) ^  第1个参数是SD_HandleTypeDef类型结构体指针变量。+ U! n, I8 H- Y$ t# A
  第2个参数是要写入到SD卡的数据缓冲地址。
1 {4 {! \- j( O# X$ e  第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
$ h* `7 w: ?( f  第4个参数是读取的扇区数。
& E: R+ @! [1 w  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
( H2 P: W8 b1 v" n- O. _. r* e
6 [( v; Q& ~, K) v( c" x3 k; C3 q4 Z- a' ^8 A- j# u4 T. m
使用举例:
: D4 {% g5 z( n& w# m: T& g2 L; H0 W: Q- I
  1. /**
    : w; J& }. y! E
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
    % `0 w$ q& b( r6 K+ p1 O' f# G
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
      I( l) m' Z1 k" a1 ?. f
  4. * @param  WriteAddr: Address from where data is to be written$ ^: a' o: @  B) @/ B1 B
  5. * @param  NumOfBlocks: Number of SD blocks to write" N" G  _' t% f, d! @
  6. * @retval SD status4 {. W# S! h! Y/ E
  7. */
    . v9 p7 o$ R/ @) H
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)- b1 C& V9 P# [, q
  9. {- p% R; x4 x: k* Z: a1 g  R
  10. " p: f- @# m, z/ A' [
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    2 z3 e6 I( w) @# l* u1 C. z- M
  12.   {
    9 c- `/ [1 A5 m
  13.     return MSD_OK;
    / k7 p2 L. }5 j
  14.   }: ]/ c! k7 B' o& W: H6 d1 M
  15.   else
    3 G! {# g3 d- j  ]1 M+ B' @
  16.   {4 c  J2 t" x& i
  17.     return MSD_ERROR;$ a: |7 r# i8 q
  18.   }
    & h: _7 u9 K' B& v4 M* J. K
  19. }
复制代码
, U- r9 ]" r( g$ i' D5 @
87.4.7 函数HAL_SD_Erase1 W/ F2 x, K0 W2 M& ]2 \
函数原型:
) y/ {# m1 w% i* Q/ S$ \  K" E+ L3 j0 f, ~* A2 z' b: P/ B- E- G
  1. HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
    ! }8 t' m9 v. M  Y
  2. {
    % m; C) Z5 n9 ~% G/ q
  3.   uint32_t errorstate;
    % P9 Z# E, j; H* o7 T6 a! m
  4.   uint32_t start_add = BlockStartAdd;/ Y8 P$ |* d( J$ h6 M& V* e! F* E
  5.   uint32_t end_add = BlockEndAdd;  B9 I4 v+ |$ O  Y5 m" q: [

  6. ' P$ h* G9 D% ~' W# S2 S; T
  7.   if(hsd->State == HAL_SD_STATE_READY)
    5 Z$ ?3 p8 ?) b8 I' i* Y
  8.   {
    9 i2 N: Z8 m+ ?& ~
  9.     hsd->ErrorCode = HAL_SD_ERROR_NONE;
    % @3 K' s0 u% e6 L9 c2 d' E- g

  10. 6 D* J3 s6 a$ F1 V
  11.     if(end_add < start_add)
    ! L" A4 u8 s" D/ y
  12.     {
    7 p5 N9 n  J; V* [( ^, K
  13.       hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    / h; s7 B8 E- B, W: @  O$ u
  14.       return HAL_ERROR;
    % @2 }( ^5 K9 ?( J& ^: r( H; H
  15.     }7 t, v  J0 c4 M$ P; [2 o' p& |

  16. 9 V/ \3 t7 s" O/ w5 \3 u
  17.     if(end_add > (hsd->SdCard.LogBlockNbr))
    - y6 D% V: V+ [
  18.     {+ g* e$ O4 K2 e
  19.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
      m/ p- Y7 V2 D) a7 ?" {4 {& h
  20.       return HAL_ERROR;# q! h" f  B, E  W( `% H' [+ r
  21.     }
    8 V( D9 S9 y0 T
  22.   |" X3 ~$ i# d& P
  23.     hsd->State = HAL_SD_STATE_BUSY;/ X; i' F# W* k9 i8 D

  24. 7 x3 E) `5 J( C( a1 ]! I  z9 U9 \
  25.   /* 检测是否支持擦除命令 */' {  I1 K: C8 A5 |' s  i
  26.     if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
    6 h% {, s2 @2 {6 M$ z0 B8 _& k
  27.     {1 B! R5 r# C6 q$ w
  28.       /* 清除所有静态标志 */9 s3 V/ f* I: U. Z0 O- {2 r( {# g
  29.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);' R5 s4 W& o4 ~8 p. C; x- E
  30.       hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;% W6 o% W8 c  g: T! |# [
  31.       hsd->State = HAL_SD_STATE_READY;  Z& i' a3 f: ?2 r
  32.       return HAL_ERROR;
    / J  K* j! U  w$ f
  33.     }+ c$ s! O$ o! Y' g+ N

  34. % M" ]0 l. C+ P+ Z1 [& E
  35.     if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
    + j4 d: z0 N& \7 C) u% c
  36.     {
    " j& g% g8 T0 H
  37.     /* 清除所有静态标志 */* @1 x7 V3 {9 n5 ~
  38.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);) Z7 t1 e. }8 h+ u2 }% R
  39.       hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;" h1 s" x7 x+ e
  40.       hsd->State = HAL_SD_STATE_READY;  ^+ I: L: l) s  i
  41.       return HAL_ERROR;
    1 _+ x# B  C. W) T2 Z
  42.     }
    $ `- E0 b* _  O( q6 i9 h0 T1 l
  43. 4 X+ m3 h: u2 R- S8 m
  44.   /* 对于高容量卡,获取起始块和结束块 */1 j  e+ _) s/ ?/ a
  45.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC): ]% r5 T! x4 z( w  i7 \# ?
  46.     {
    % t& U/ E8 M" f  B& r- y7 r: v# k% j
  47.       start_add *= 512U;
    ! M1 W9 D9 a8 Y+ Z7 q2 j! j( C9 y
  48.       end_add   *= 512U;9 B9 G( x0 F/ k4 [+ P# o# [
  49.     }
    ' V/ l4 x1 P# R
  50. $ {" y; {* E$ \, H8 R: T5 G" w
  51.     /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */; s3 w( _4 x* R- I) C
  52.     if(hsd->SdCard.CardType != CARD_SECURED)
    , S! x) r0 Q" {: K8 s
  53.     {5 j: n5 m' D( Y4 O" Q5 w
  54.     /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
    $ i% m: |; c5 t  j5 J- i+ o
  55.       errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
    7 T( h6 F; m+ R+ H# F
  56.       if(errorstate != HAL_SD_ERROR_NONE)+ {2 d/ l) D, |0 D, z4 A: b
  57.       {
    $ e- @, m, c" e8 Z7 @
  58.         /* 清除所有静态标志 */" q* @$ @/ ?1 i# U8 _  \
  59.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    & C7 E# v* Q4 ~
  60.         hsd->ErrorCode |= errorstate;
    - B: s  N  M- S! {2 T' i* U8 l/ E2 S
  61.         hsd->State = HAL_SD_STATE_READY;
    * R( h7 C+ y# d
  62.         return HAL_ERROR;
    . D: `9 S3 R- v; z
  63.       }7 {& A! G- B2 ?- ]
  64. " V& N4 d, a, @9 N) x
  65.       /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
    + C; T, z6 R) g' C7 H
  66.       errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);& b/ h/ i" I) ^1 b9 l- ]+ @7 x
  67.       if(errorstate != HAL_SD_ERROR_NONE)5 d( v. M" _9 f, Y& w
  68.       {
    # a1 y$ J/ T9 f; m3 R" [
  69.         /* 清除所有静态标志 */( z: J; i& E5 \: j+ k8 h& h
  70.         __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);) b9 b4 f0 S% d# O" d
  71.         hsd->ErrorCode |= errorstate;2 c7 T1 ?0 I% c$ |+ `9 b
  72.         hsd->State = HAL_SD_STATE_READY;
    ! j5 w$ P/ @$ P' |) M& Y3 ^
  73.         return HAL_ERROR;
    " L  D1 x. M3 C' W( i- d
  74.       }
    ) v: e( C5 }- y! A2 c# e
  75.     }' f3 W$ f: C, t4 u

  76. & V  W; m' E4 l) ?- E
  77.     /* 发送CMD38 ERASE命令 */
    2 c/ p& L1 y. p1 u& n$ p, Z' Z' n
  78.     errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
    ) N0 p( d+ G1 Z* s5 b; S, I
  79.     if(errorstate != HAL_SD_ERROR_NONE)
    - S1 g; a; G9 Z: ~) ]! ~# d
  80.     {
    1 ~" T$ ~8 c- n9 t  V
  81.       /* 清除所有静态标志 */: P+ I; b+ }/ \2 t. v5 G8 h
  82.       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
    0 J1 a) U7 k( r( I4 u* x$ z, X' H' {
  83.       hsd->ErrorCode |= errorstate;
    & H" n) q2 r9 K/ b) e
  84.       hsd->State = HAL_SD_STATE_READY;2 F/ f, W$ S- N* y+ N6 r
  85.       return HAL_ERROR;
    5 F" Q2 P# A0 ~' F( k6 Q2 K# n, M5 u4 \
  86.     }, I0 _+ ~, L: }  |4 O8 K9 e
  87. " X8 @, [5 C0 H. m0 t
  88.     hsd->State = HAL_SD_STATE_READY;
    + A7 J2 h2 o* U, ]4 _9 w" _
  89. $ u/ U; a3 `# G, O* i. D
  90.     return HAL_OK;
    ; s8 X, G. F) R1 o4 H
  91.   }8 \4 ]$ @2 V+ ^, R% {9 M5 Z
  92.   else
    5 \! @4 {, W% u( e
  93.   {
    / Q4 @8 T" I. V
  94.     return HAL_BUSY;) M, E8 ^) K4 e
  95.   }
    # C# Y% A* L3 ?; q  h7 P* g7 E
  96. }
复制代码

! B9 ~  _0 w, D: }" s函数描述:
* e8 E  r- i4 G! Y) z
1 n  H4 S4 ^7 `' y此函数主要用于SD卡擦除。
! C7 G, c/ c2 P% S/ j+ ]5 c( K: ?" s" L+ M8 h. ?4 L: Y
函数参数:
5 K5 w7 A$ e) K( S  F$ }" W2 u: i' v
  第1个参数是SD_HandleTypeDef类型结构体指针变量。
4 h# h4 O2 _, n# {% n( z0 v, M  第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
/ I3 G0 R. j( l5 M' [4 m8 _  第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。  |1 ^' M# l1 a& W  b
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
) V. K' Y4 p6 b% A* P  p& q9 Q使用举例:
, y% Z+ q3 B, [  T. g( W
7 J6 G  r7 b( `$ A) P, s1 {
  1. /**
    * H4 `+ y5 e5 D8 G1 q% h2 i$ v* B+ C
  2. * @brief  Erases the specified memory area of the given SD card.3 h; B- X" Z- j, P
  3. * @param  StartAddr: Start byte address
    + s- H' o5 d6 m1 B
  4. * @param  EndAddr: End byte address, f2 G9 y# w2 F
  5. * @retval SD status
    ! T- I8 }9 k7 g* A) U: a2 Z, H8 u
  6. */
    2 v; ~* W& |$ x5 b( P
  7. uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr), t' t: L$ b6 X7 Y$ y# H9 L! S0 d
  8. {6 p/ Z1 a. T4 R: B$ G7 r3 Y. \; A
  9. - ?) W) }8 c% [+ p* z' ^
  10.   if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
    6 j1 S" U+ }: h% r8 T+ g
  11.   {4 J$ i# S; n( J
  12.     return MSD_OK;0 L* j! \0 T: o9 J4 p0 J4 B  k
  13.   }
    5 e& @$ ]8 _  U4 H
  14.   else8 I  \6 m# p' ]# h
  15.   {
    ' _( {* c0 W4 F! c, C( z
  16.     return MSD_ERROR;
    ( q6 o+ {$ s: H8 [% }, K5 ^; u
  17.   }
    ( E; h! e, |. {) u- z# s
  18. }
复制代码

$ D( Y8 s/ N3 `/ X4 _87.5 总结
% z+ A% s7 x( _! t5 P9 C5 U( y本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。
0 N5 P$ H* `% }8 @* R" u. b$ a; M4 u2 a& J

& o. u1 C7 F8 r! d; |1 ]4 z: i: u: t0 P1 t/ q# i3 }

7 e8 s! B4 Q* I; b8 b( I% }" U7 _& o! U, Y

$ |$ g+ S5 V7 C9 T2 P! H, y
收藏 评论0 发布时间:2021-12-26 16:43

举报

0个回答

所属标签

相似分享

官网相关资源

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