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

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

[复制链接]
STMCU小助手 发布时间:2021-11-1 08:00
61.1 初学者重要提示. t9 Z4 P( |% R- T
  MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。$ m! X2 t" a0 q! x  J0 G
  对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。6 R: m1 n+ K. {. f, h4 {$ m& w
61.2 MDMA基础知识
- I: \7 m: f0 E对于STM32H7的MDMA了解到以下几点即可:0 o- y" t% l0 n- W* B6 E' O
% n+ n+ r3 N  \
  由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。
5 [: ]* c) [( Y& u: _0 K  MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。9 o" i, N) w" D, Q
  有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。- g# x" r; u! B; d! S3 ?9 E& _
  16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2
* d5 }- H* `1 s  L: ?6 V  MDMA具有一个256级的DMA空间,被分为两个128级空间使用。' }, ?$ _) @, f
  MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低
) r& M3 e! _, m+ _' d  数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
5 D8 g6 y& n3 o6 K& m  m  源地址和目标地址的大小和地址增量可以独立选择。# r' i3 \  u4 z7 R$ w9 u, g4 `
  数据的打包和拆解是采用的小端格式。
  a' U* s- k5 U  支持突发模式,最大可传输128字节。/ X4 O  Z5 A! ^1 v5 k$ `
  当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。. j3 t$ C8 F6 y3 \
61.2.1 MDMA硬件框图
/ j6 d! P- d) }3 k4 M5 a3 A* N7 n6 ^认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:
" Y: J( y. a2 w: z/ P8 I) w1 R9 d6 [; @: r1 E! e4 E
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

* |# _1 B, @% P2 F+ X通过这个框图,我们可以得到如下信息:) {: ~- o- a% z% P

( ~$ g: H% I3 o" s! v, R# j  mdma_it! `* q) F. j! ?
mdma的中断触发信号。' g) w1 |* h( |9 g$ V9 t& K- z/ d: k

5 h+ ~/ E+ m( t2 _( i# \# N  mdma_str0到mdma_str31触发源
8 Y1 g0 Y  d5 E* @+ ^( Nmdma的输入请求。4 m$ P+ ]. u, s7 f. }* ?; f

$ Y- T/ t1 V4 Q' S* o+ M7 H" s  mdma_hclk1 i1 E3 @  {1 h& R: g
MDMA的HCLK时钟。
) }, m: _6 p! M2 ?& K
+ T& |% l$ z1 j, e) e) u3 Z: b# I% D& s61.2.2 MDMA块传输,缓冲传输和列表传输区别
$ C7 |7 P# ~5 k  N8 a初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。
- p$ g4 j* B* E: b+ i; b$ `: l; s$ e3 O- j! |# u
  缓冲传输(MDMA_BUFFER_TRANSFER)
- M3 j. Q2 b8 Y这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。9 N+ B+ ]8 h; ?: d

8 Y( j" j- Q$ M& k8 g
6 E( Q7 A" ^9 {( }2 @/ e  块传输(MDMA_BLOCK_TRANSFER)
1 m9 Z" \/ g2 K. c2 F% f2 E0 ^此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
! ?5 O/ K: k+ v$ |
% k* l7 c* v" D( [! v& `$ B: B( f# p/ w& B" z; r
  多块传输(MDMA_REPEAT_BLOCK_TRANSFER)4 ?  j) X) |; o, y& A
顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
6 U* _' H) I1 E: H& K3 r
5 P& y# H. D/ M. y. ^: s/ [6 X8 j
; l; R) _7 b. n5 \# l: S; O  列表传输(MDMA_FULL_TRANSFER)
& r% O" g4 I& |- [1 z0 R1 ?, z/ H这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),
& A% H2 w; K3 Q
( @3 F( e5 T  u3 k! |1 ~61.2.3 MDMA列表模式及其循环方式
# f! t% A$ \6 q: e! k列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。) l3 E  h, }1 ^- Z0 F
" b9 ]! x9 M) H
  使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。6 [; N, {# R+ T1 ^- K
  使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。) ^0 S, d" ?( C* E5 B, |" Q9 S1 }" p
  节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。
; r3 a0 f2 u/ B( B0 T  如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。% S! H7 v- J& D! O+ B
  通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。
" J( a8 h% Y. B. B( b. Z" s& x& w1 X/ }6 z61.2.4 MDMA的触发源8 M) p/ s. w7 @( @, E
MDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:. u& X5 L8 p& M) B* T% n! s, Y0 h
, X. D! b; f8 X0 k9 q; Z. U9 r
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)
    . _1 z) P( B5 f  M4 l$ v
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  . m! w7 l1 b* |$ ~6 ]; Y1 ^5 d
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) " \( j& e- Y/ t- h
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)
    * O$ m9 b9 j4 {: q' g- Z
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)
    * p: M, c5 y& s
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U)
    ( Y2 W3 G. @( b3 \  L$ G. z# z  W" y
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)
    " M7 E0 o$ D7 D
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U) 2 o5 m3 ^# |" |! \7 Q9 |
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  5 D" M% D6 P7 [
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)
    1 a' D( E  c$ ]1 j4 _1 P
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  
    5 U3 C+ P/ F  z& {0 J& H7 w
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU) ! J( E0 \9 J  l
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    + u& h& n, [  B/ N, [
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)
    0 v: i# G) c" j5 d; s
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  # z" I3 O# m5 r8 S$ G* x" L
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)
    ! `4 _2 {' I/ H+ ~  m- X: e* V- o
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  
    % l3 Z" @+ Y" a! V, C, Z) X+ Q% q
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U)
    1 P- n/ f0 i8 r4 b# T! }$ M, d
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U) ( ^, \! S9 t/ o+ P$ e$ U
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U) . S  n1 [! d# G6 w' @1 D) P
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  
    " ~9 G" d9 X1 Q. `' I) f
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  1 }  d6 z. i# l7 U1 r  G& |& v5 H
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  
    6 H. P% W6 S* s
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)
    ) x% `5 u/ h0 o
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)
    * z+ h, P9 I2 e; B, Y
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)
    0 Y: K' S& }- L% A
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)- \* L$ j" C* v: X. q3 E, w  [
  28. ; M- `1 _: k6 I6 b/ Z- f
  29. #if defined(DSI)4 a& m2 N* u' G/ |
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU) , J' Q( U4 \& ^; t+ E
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU) $ g' [* }* M6 I4 e4 Q
  32. #endif /* DSI */
    ( T9 M8 d: V; j! ~2 [7 s. W/ h
  33. ' t9 Y; z5 g# J2 N. H
  34. #define MDMA_REQUEST_SDMMC1_ED_DATA      ((uint32_t)0x0000001DU)
    / }3 G- a: I5 R  `1 o4 y5 X( y7 d
  35. ) V! _  [& z7 ~) B  d; C6 |
  36. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U)
复制代码

- D4 k& x% G' A$ F9 }/ H$ [# d6 G. v& ^
" D2 C% f3 B' i9 ~& r2 V
61.2.5 MDMA的软件触发方式0 _* N+ Y. w4 q. ]5 V
MDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:
. ^/ D9 K/ C* z7 Q5 F! B, ^
3 G; s. O) s  B' \9 d: k  如果传输结束或者传输还没有启动,调用此函数会返回error。
! J9 Z4 \- Y% o, |  如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。
5 ~+ M- g; ^/ p6 L9 i! p  X% R2 p
' `$ g; ^; S8 x
3 ]! ~- U  u) X7 {  e应用示例1:
- ^( P8 U- I0 i2 m2 o* A2 |$ C" v) |3 n% m1 x
  MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。
# Q! Q& z2 t* }" K( `! e  注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。' `: `3 K9 L. `) v6 s* B6 ~
  调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。
  q5 P+ s# t4 D" j  v  传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。
3 k; [, n/ B/ o# w2 p, l2 c5 s% p4 a$ h2 M$ [
' |7 ~- b  p% }8 X
应用示例2:( S+ C! H2 p# p  g
+ ]6 R* S! S9 V* Y  R
  MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。
, x! K, u0 B, \% p) d- O9 }; W  注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。
% Z+ f, _$ ^3 j  调用函数HAL_MDMA_Start_IT会触发一次块传输。
3 Q8 x& O2 @: y7 T4 U' d  传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。+ x! E' d/ T( A! C& a$ L5 |
61.3 MDMA的HAL库用法/ M$ o) t& G- V
MDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
: W( }( O7 a9 k. Y" X8 `, K0 U. c/ }" a0 V) I# ~
61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef
$ ]' ]/ G# J' I  I0 Z; mMDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:8 z6 v) M- L) S& h, [5 K+ H6 o: O
. t3 {  r1 S, |. `' L6 G/ u
  1. typedef struct
    7 K7 G. n5 \2 N3 T1 [3 D) |) j% }+ w
  2. {+ S. `$ W% p5 c2 o7 i) w
  3.   __IO uint32_t  CISR;      /*!< MDMA channel x interrupt/status register,             Address offset: 0x40 */; W; ^, ~5 A" N! x! M- U
  4.   __IO uint32_t  CIFCR;     /*!< MDMA channel x interrupt flag clear register,         Address offset: 0x44 */
    1 ^  e8 ?3 F3 y5 d
  5.   __IO uint32_t  CESR;      /*!< MDMA Channel x error status register,                 Address offset: 0x48 *// a$ s) o" Y0 P
  6.   __IO uint32_t  CCR;       /*!< MDMA channel x control register,                      Address offset: 0x4C */ 0 p8 `9 k6 M; J2 R- o  f2 k
  7.   __IO uint32_t  CTCR;      /*!< MDMA channel x Transfer Configuration register,       Address offset: 0x50 */
    7 S% c. c1 I9 m) y! n
  8.   __IO uint32_t  CBNDTR;    /*!< MDMA Channel x block number of data register,         Address offset: 0x54 */* G3 u& z/ m' {; Q2 i) w6 h3 K
  9.   __IO uint32_t  CSAR;      /*!< MDMA channel x source address register,               Address offset: 0x58 */
    . b5 Q1 h& i6 }& Y  K/ S
  10.   __IO uint32_t  CDAR;      /*!< MDMA channel x destination address register,          Address offset: 0x5C */4 N3 k" g" A& l
  11.   __IO uint32_t  CBRUR;     /*!< MDMA channel x Block Repeat address Update register,  Address offset: 0x60 */
    / [4 Q' |2 o0 S
  12.   __IO uint32_t  CLAR;      /*!< MDMA channel x Link Address register,                 Address offset: 0x64 */* w- Y. F1 C9 ~0 z9 {8 Y8 m
  13.   __IO uint32_t  CTBR;      /*!< MDMA channel x Trigger and Bus selection Register,    Address offset: 0x68 */
    0 X  B% {' J9 e3 N$ T- @9 x
  14.   uint32_t     RESERVED0;   /*!< Reserved, 0x68                                                           */  
    ! V( R* j  W& t: W$ d3 I) }
  15. __IO uint32_t    CMAR;     /*!< MDMA channel x Mask address register,                Address offset: 0x70 */5 I: l# _; O$ V9 X4 J1 \/ ]
  16. __IO uint32_t   CMDR;      /*!< MDMA channel x Mask Data register,                   Address offset: 0x74 */0 w- ~' @2 m% z: l8 E
  17. }MDMA_Channel_TypeDef;1 z" y6 B/ o( d/ w* u+ m

  18. 2 I' i) E2 N% G
  19. typedef struct' d4 r6 I% ?$ e* G3 E% h
  20. {
    . W# h& {- n# K$ @
  21.   __IO uint32_t  GISR0;   /*!< MDMA Global Interrupt/Status Register 0,          Address offset: 0x00 */+ k0 V0 z. d6 i8 o/ s
  22. }MDMA_TypeDef;  H) _, d5 {) B
复制代码
. K7 K9 _1 n' i& Z  Y" j; K2 v$ y4 }
+ i; B0 A0 W. _, e5 b  V
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:" m: E6 O3 P4 E$ x8 y
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */0 i1 R9 s/ w( K) S2 X
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

; Q9 [$ j5 r! w下面我们再看MDMA的定义,在stm32h743xx.h文件。7 N( r" f, o/ V$ P5 A# D
* o) z2 z6 M% c2 R9 x: P! ^- _
  1. #define PERIPH_BASE           ((uint32_t)0x40000000)
    # C' s" o: o+ K( y2 b) N
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000)2 D1 I; y$ D  V5 l9 P* h2 B; g6 J
  3. #define MDMA_BASE             (D1_AHB1PERIPH_BASE + 0x0000)
    & \- R9 K- g( o

  4. , R. f* s  y* R/ o( ~
  5. #define MDMA_Channel0_BASE    (MDMA_BASE + 0x00000040)8 s( z& M' a  `& b& L8 g3 U8 F8 j
  6. #define MDMA_Channel1_BASE    (MDMA_BASE + 0x00000080)
    5 H9 }: q. c3 X" K
  7. #define MDMA_Channel2_BASE    (MDMA_BASE + 0x000000C0)
    ) u$ U9 ~' G) \% l
  8. #define MDMA_Channel3_BASE    (MDMA_BASE + 0x00000100). Y% ?- d% ?: n+ n
  9. #define MDMA_Channel4_BASE    (MDMA_BASE + 0x00000140)8 r' L8 p* b# X2 |$ n. h5 k
  10. #define MDMA_Channel5_BASE    (MDMA_BASE + 0x00000180)
    4 C8 o" K  M3 o% U+ C; T3 {
  11. #define MDMA_Channel6_BASE    (MDMA_BASE + 0x000001C0)+ C9 ^' M) [# {3 b7 K- ^  `
  12. #define MDMA_Channel7_BASE    (MDMA_BASE + 0x00000200). P0 C' [/ t6 W1 _" E$ q0 @9 X
  13. #define MDMA_Channel8_BASE    (MDMA_BASE + 0x00000240)
    & u  T# O3 r7 z1 r$ m/ Y% i
  14. #define MDMA_Channel9_BASE    (MDMA_BASE + 0x00000280)* c8 N! ?7 ^2 m" Q& Z: q' E
  15. #define MDMA_Channel10_BASE   (MDMA_BASE + 0x000002C0)
    , f9 j$ m/ J/ F8 U& K, i' ?6 [
  16. #define MDMA_Channel11_BASE   (MDMA_BASE + 0x00000300)' l( w5 D6 D% Y# A
  17. #define MDMA_Channel12_BASE   (MDMA_BASE + 0x00000340)& B. n+ N1 T2 d# y, Q2 g# G
  18. #define MDMA_Channel13_BASE   (MDMA_BASE + 0x00000380)- Z# a" l5 y7 x3 `" [7 c; T/ u
  19. #define MDMA_Channel14_BASE   (MDMA_BASE + 0x000003C0)
    & ^- b/ Y1 h. B
  20. #define MDMA_Channel15_BASE   (MDMA_BASE + 0x00000400)( ]- I7 T* q4 f# a. N
  21. + q! I' m3 X+ }& c, e
  22. #define MDMA                ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000
    2 ]) H: }+ e6 }& A4 D$ D
  23. #define MDMA_Channel0       ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)- p/ X; {2 Q  S: m2 K" c: z
  24. #define MDMA_Channel1       ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)6 d1 N" G9 f1 ]1 d5 V% _/ ?
  25. #define MDMA_Channel2       ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)/ A4 C/ P2 c4 \3 G  t; [
  26. #define MDMA_Channel3       ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
    1 B/ V- Y9 b) \' E# |0 @  }
  27. #define MDMA_Channel4       ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)
    3 T/ G" y( J  s  u1 c8 A
  28. #define MDMA_Channel5       ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
    ' f3 P+ ^: \/ f
  29. #define MDMA_Channel6       ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)/ q: {' \/ T) l0 E- P
  30. #define MDMA_Channel7       ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
    " K) x6 r- }2 [8 `2 b( ~( R
  31. #define MDMA_Channel8       ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)
    $ g' D) w- ]- k# ?$ |4 y
  32. #define MDMA_Channel9       ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE). Y) W- C& g: l: L3 |6 O
  33. #define MDMA_Channel10      ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)! r0 U5 [, E" b3 a4 |, K
  34. #define MDMA_Channel11      ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE): E; ^% k( m0 V$ z3 `6 C
  35. #define MDMA_Channel12      ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)0 j' z4 x1 ^/ x' l
  36. #define MDMA_Channel13      ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
    $ X( l: }$ N9 u2 y# M# o* v
  37. #define MDMA_Channel14      ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)* p( `; T; V1 J6 E1 L0 w
  38. #define MDMA_Channel15      ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码
" a- W5 N# N0 o. ?. `! j, W
& y7 f1 Y' `" @1 o! d- Q( o4 Q2 ?

& x# T( V1 q0 n$ r2 M' r我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。  {, b' p; S2 V* |
$ P. j% J+ \1 h$ L! Q
61.3.2 MDMA的参数结构体MDMA_InitTypeDef4 l3 v: A1 O- b
此结构体用于MDMA的参数配置,具体定义如下:
% m1 }+ _; k/ ^) D* {- }9 E0 q
4 o1 Q; q& L+ R$ [: f
  1. typedef struct9 H  f  J+ ~: R0 j4 s
  2. {& M9 G4 I1 W' l( f& s% v0 n4 E& I
  3.   uint32_t Request;                                                
    % U0 w% i8 p1 W
  4.   uint32_t TransferTriggerMode;                                    : C& F+ D7 D$ I, l9 Y! v
  5.   uint32_t Priority;                                                     
    6 _" i4 q, }( ?) \! D0 u
  6.   uint32_t Endianness;                                                
    $ i2 W! h% Q; N+ U% I* \4 e" A
  7.   uint32_t SourceInc;                                              4 T" h$ Q5 Y7 W
  8.   uint32_t DestinationInc;                                       
    / \7 O4 ~/ D, b. I5 A0 s  W
  9.   uint32_t SourceDataSize;                                         
    $ K/ \; f# Y+ H/ m5 C2 c% z
  10.   uint32_t DestDataSize;            $ b9 {2 U& d& y) n, U3 J
  11.   uint32_t DataAlignment;          : \+ Q0 ?2 k8 G& o. W! f2 H; x% e
  12.   uint32_t BufferTransferLength;   
    * K% g3 W3 F) Y  ^$ P
  13.   uint32_t SourceBurst;                                            
    1 p  g1 V: A& l: m: ]
  14.   uint32_t DestBurst;               - d' _* @* O4 }& Y. K
  15.   int32_t SourceBlockAddressOffset;                                                                           
    7 O5 }. r7 ]: U& }
  16.   int32_t DestBlockAddressOffset;      
    & ^$ [. n- M) u, {( n) R* ]9 P
  17. }MDMA_InitTypeDef;
复制代码
, q' @4 k, l! n4 h' n
/ x* p4 h7 M% r; W

3 \4 }" |( r  v" w( H下面将这几个参数逐一为大家做个说明:
% h' f; d1 X+ b  X: Q7 }2 G/ [- m( T- e- k
  uint32_t Request" c. O" U# s% c) j8 U
触发MDMA的请求源,支持请求源如下:  Y* b( P" c/ |5 L' [+ X8 A2 v. l

* D* T8 |  T- o6 Y# @
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)  $ P  ]! ~9 F' N+ o2 t+ l1 K" S
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  
    $ k; w1 q' U2 E& _9 _; x
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U)
    % |9 i, V* O+ o9 `) S
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)  
    0 y0 H" D1 X( F: V2 q
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)  
    5 y2 p2 i1 d* _& a) H2 n# [# o, g
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U)
    $ l2 j+ F' M7 d+ ]7 M
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)  
    + u+ s/ o* [5 v2 H; X3 i. |
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U)  
    , ?7 ]6 W: v8 a7 N$ R
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  " C& p3 i- F8 A& R; Y
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)  
    . k! M; R# l  G6 T# E& `6 |
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  9 O, J2 j2 k& z2 J" r0 g2 L
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)$ n- m1 D! t/ X; |) [$ N7 S! {
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    / H+ e$ ?2 Z4 t* n0 U* a6 m9 _# V1 d
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU) 8 f7 N) x% ?4 k0 H
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  # O/ V, O& C9 y) X3 n. A
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)  % z: L0 r+ O, K, k$ H
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  ( |/ M6 n" [3 b+ K) l& Z
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U)
    " N1 k1 ]4 ?3 S
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)  ; x! G5 c* @# m% I
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)  2 ?5 X& k# t9 b5 L' v
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  
    4 ]. v3 B1 S+ q3 S
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  
    4 o' X8 ]" R- ^" c9 U- v/ K
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  
      m: k( M4 k/ c( c
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)  4 L, Z6 d  K3 T" F6 k1 y
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)  0 S& K$ Z& }: n' R3 Z
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)  
    : N  x7 M% b4 t" l+ ?3 v
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)  $ G- @" H" b3 f

  28. : N; u1 c% _" ~' E
  29. #if defined(DSI)2 Q* H5 x6 F7 S* j" p; n# G
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU)  
    4 L) r7 r0 T/ n* S# F
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU)  
    & I% {' h9 z: O5 t& x9 ^8 d, e
  32. #endif /* DSI */4 i- R& X6 F9 Y8 [5 x8 D! y! N

  33. ! c% R. m9 R9 N( @
  34. #define MDMA_REQUEST_SDMMC1_END_DATA      ((uint32_t)0x0000001DU)
    , A9 `% @: O) w2 c' q; ~- {
  35. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U) ) Q5 N3 n  f1 K+ o7 d
复制代码

3 m5 d7 Q0 ~5 Z& r& n( Y5 O, V2 K: {# T; ~/ _  `
  uint32_t TransferTriggerMode: a2 O$ S6 R7 b! c" Y. a& C
MDMA的传输模式,具体支持的参数如下:5 U/ g' S% y+ F8 R6 \8 }% k! x- s: k
2 _/ c6 k2 j+ @" |/ P0 H% T6 e
  1. #define MDMA_BUFFER_TRANSFER          ((uint32_t)0x00000000U)      /* 缓冲传输 */2 `3 e+ l9 P* ?( ?8 A1 \$ z) A
  2. #define MDMA_BLOCK_TRANSFER           ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */- p4 c! J+ e9 K* \
  3. #define MDMA_REPEAT_BLOCK_TRANSFER    ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
    0 j9 z" E6 R) U& n
  4. #define MDMA_FULL_TRANSFER            ((uint32_t)MDMA_CTCR_TRGM)   /* 链表传输 */
复制代码
9 m1 q' b# q) L. q. {- i( ?, d
4 o) m  N3 c. e9 n1 n; X

% q$ W* o* K* X# v$ U# N$ G3 I  uint32_t Priority  F- }/ D+ S3 f1 p9 l
MDMA通道的优先级设置,具体支持的参数如下:
1 }2 k+ p: R1 f6 E; }* H/ w
2 q+ U5 Q! u4 g& \: m# S8 g
  1. #define MDMA_PRIORITY_LOW             ((uint32_t)0x00000000U)     7 ]( a) O4 M' F% e/ z
  2. #define MDMA_PRIORITY_MEDIUM          ((uint32_t)MDMA_CCR_PL_0)  ! N* J) J; ~7 l( ^" e. P3 q
  3. #define MDMA_PRIORITY_HIGH            ((uint32_t)MDMA_CCR_PL_1)  
    6 f0 f8 p- v# ?- g
  4. #define MDMA_PRIORITY_VERY_HIGH       ((uint32_t)MDMA_CCR_PL)   
复制代码

, X  I3 J6 [% M8 ~9 z# g! M. E+ d6 o' J4 y

! e3 N2 z: M6 V7 K2 O  uint32_t Endianness! @/ w* H( k, I) q
MDMA数据传输格式,具体支持的参数如下:; h4 G$ F3 K0 X) k5 `; x, y
- M5 ~1 I. s3 u2 s; T
  1. #define MDMA_LITTLE_ENDIANNESS_PRESERVE          ((uint32_t)0x00000000U)  
    0 Y5 J, M3 o! ]! a( K2 ^% N
  2. #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_BEX)  6 k& m+ |, `! O; B2 X
  3. #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX)
    5 n4 h) T% y$ Y# @
  4. #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_WEX)  
复制代码
7 y# M6 v1 }7 H
: P$ a7 T+ `+ i0 y% T) E  q
MDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。( ^& l: Q) w2 q" D" V$ H
& V" K  @4 s# l" e  o
MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。# \% C+ q- G5 U  O
9 F. J: |) r# a3 w
MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。% q4 N0 q  y! d2 D
' q! V/ N0 n9 o6 o5 L: J; ^" Y
MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。4 s1 }( ]# f3 F* k7 |
; n* x8 t6 }" J" X4 j0 ~
  uint32_t SourceInc
  ]! e6 h* R3 y" m! NMDMA源数据自增或者自减模式,具体支持的参数如下:
/ [9 ], ?" w* e" }$ M( n# K

  1. ' J2 E  s# b( s! f
  2. #define MDMA_SRC_INC_DISABLE      ((uint32_t)0x00000000U)                                    
    3 Y4 O" v8 j; v) M# X/ d
  3. #define MDMA_SRC_INC_BYTE         ((uint32_t)MDMA_CTCR_SINC_1)                                5 t1 I& C  b& A+ w
  4. #define MDMA_SRC_INC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)% L# J6 a* d1 w8 L
  5. #define MDMA_SRC_INC_WORD         ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1) 3 I$ |* o' h% }, l% Y
  6. #define MDMA_SRC_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)  
    , U$ f& U) O, ~. L. h& r7 d) p- A
  7. #define MDMA_SRC_DEC_BYTE         ((uint32_t)MDMA_CTCR_SINC)                                 
    , Y4 t$ Z; P3 R3 M5 ?1 v
  8. #define MDMA_SRC_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0)   # h& S2 L! |/ @" t7 X
  9. #define MDMA_SRC_DEC_WORD         ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1)     M; ?7 F; I3 K( B6 {! @# X
  10. #define MDMA_SRC_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)   
复制代码
9 ]: }+ q; {; m9 c6 `8 N
. B, T1 r# @: n) s0 U) |. ]
4 p3 C- d$ }8 N6 l4 E9 f: ]
  DestinationInc
/ z  {! U: ^2 b4 Y* _MDMA目的数据自增或者自减模式,具体支持的参数如下:! Z2 ?, q: I% ^5 R- y
; c+ _7 R, i+ e+ t& ~
  1. #define MDMA_DEST_INC_DISABLE      ((uint32_t)0x00000000U)                                    1 P5 f1 Q9 L. ]' N2 R3 A
  2. #define MDMA_DEST_INC_BYTE         ((uint32_t)MDMA_CTCR_DINC_1)                              
    7 [, o! T0 ]* v/ d1 R; w
  3. #define MDMA_DEST_INC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
    ; O' t  x* M6 v" s. x
  4. #define MDMA_DEST_INC_WORD         ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1)
    # J9 E8 ^; S2 l5 \! S
  5. #define MDMA_DEST_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS)   
    " w' D' ~8 G# Q  j" W8 b3 \
  6. #define MDMA_DEST_DEC_BYTE         ((uint32_t)MDMA_CTCR_DINC)                                ; g+ ~( W! y! W% ~% h4 n( ?
  7. #define MDMA_DEST_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)   
    2 u! ]9 ?" [, O, R
  8. #define MDMA_DEST_DEC_WORD         ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)   + Q, I# p# c' v: r7 O+ ?
  9. #define MDMA_DEST_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)  
复制代码

) G+ @. m% i% {. }. b0 Q) Z- B+ u# G
/ F/ @5 z$ W, ]" S/ N! R; Y4 ^" ]2 P/ b$ q2 I  E+ `
  SourceDataSize# r( W6 V& q' l( E
MDMA源数据带宽,具体支持的参数如下:
4 ]8 F  d9 [" K1 L
3 z' E: d6 K" s" X' Y3 e
  1. #define MDMA_SRC_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    0 o$ s& J! X  r3 A4 y5 ]
  2. #define MDMA_SRC_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_SSIZE_0)     : u3 u0 a" L9 S6 z+ H
  3. #define MDMA_SRC_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_SSIZE_1)  
    ( J5 |$ f& z2 @! {( V
  4. #define MDMA_SRC_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_SSIZE)   
    " [1 W' r- y$ i! Z
复制代码

8 B2 ?. m7 O+ V  N- }' u0 E+ p* p
) c: F9 T* c$ O& h  DestDataSize
" [; Z" _2 d+ R) E! J5 q) BMDMA目的数据带宽,具体支持的参数如下:
' t. \: ]- ]2 n4 {3 t4 E1 H$ H% A# l0 I
  1. #define MDMA_DEST_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    0 t, _5 s0 @5 s9 N: N2 Q! f
  2. #define MDMA_DEST_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_DSIZE_0)   : t& j6 {# p/ u' D+ e5 i# Z
  3. #define MDMA_DEST_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_DSIZE_1)  
    2 j7 j; E0 u; X( ~2 I! I
  4. #define MDMA_DEST_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_DSIZE)     
复制代码
) H2 j. S/ a* ^% h' e% E' G) `% m& S7 v
$ Z8 L2 \5 T6 z( t8 ~" t
; ^3 ^% i$ @; R4 R
  DataAlignment
) p4 i, r. `8 Y. B( z; uMDMA的填充/对齐设置,具体支持的参数如下:
; G8 |' ~2 u$ k( A: v+ w3 }
  1. #define MDMA_DATAALIGN_PACKENABLE        (uint32_t)MDMA_CTCR_PKE)     ' f+ b" X& \. E8 y1 ~# @/ |
  2. #define MDMA_DATAALIGN_RIGHT            ((uint32_t)0x00000000U)     " ~) e. r$ p, C; I) x
  3. #define MDMA_DATAALIGN_RIGHT_SIGNED     ((uint32_t)MDMA_CTCR_PAM_0)  
    8 I! r9 X2 f8 \$ c6 P- H* \
  4. #define MDMA_DATAALIGN_LEFT             ((uint32_t)MDMA_CTCR_PAM_1)  
复制代码

. f- n: O/ X/ x5 e  ]1 ?
/ Y9 w8 G5 J9 H& D' `$ M6 {% T- \7 J, u- ?, c% ^1 `9 p( F
MDMA_DATAALIGN_PACKENABLE:
8 L( I+ j. v% J4 F7 M$ y- r+ f7 z: S6 d3 C/ t
将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。3 h/ v, d* _# P) g
, F+ a$ T: }2 q
MDMA_DATAALIGN_RIGHT
' X: o* X0 \8 C7 N1 N2 F
/ k9 L4 H6 U/ ?2 G6 |3 y( w右对齐,用 0 进行填充(默认值)
9 ?5 A# n: N7 U+ _8 ]
: [5 w) g3 n7 J' HMDMA_DATAALIGN_RIGHT_SIGNED! p2 I6 {5 L1 x( o2 {/ K& r

, }4 M# q8 }8 r! o. \右对齐,符号扩展
) L; \5 b  F  n  P. r+ X% S8 E3 Z, W) R( e4 K9 k1 J
MDMA_DATAALIGN_LEFT
1 h9 ]5 I9 C5 A5 z
+ g" B' Y& J  K, I左对齐(用 0 进行填充)/ ?0 G: `$ G- ^( g" v1 ^5 D: C9 {  l

# h7 B" {( t; N$ w  BufferTransferLength, r3 L4 D- |4 E6 U2 ^1 \# W8 J: a
单次传输长度设置,范围1-128,单位字节。
/ R& d/ ]/ X9 S0 m' g" Z
) b& G. Z; N* h/ ^  SourceBurst* R5 v3 Z) f/ E
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:' [) @: `6 q3 I4 ^$ ]7 J
! l- Y! g/ F; }' O) Y2 T
  1. #define MDMA_SOURCE_BURST_SINGLE        ((uint32_t)0x00000000U)                                      
    6 t; b1 r( |9 R7 U; R% ~  ^4 A
  2. #define MDMA_SOURCE_BURST_2BEATS        ((uint32_t)MDMA_CTCR_SBURST_0)                               #define MDMA_SOURCE_BURST_4BEATS        ((uint32_t)MDMA_CTCR_SBURST_1)                               #define MDMA_SOURCE_BURST_8BEATS        ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_1) # L. {% W( a" O4 a. u
  3. #define MDMA_SOURCE_BURST_16BEATS       ((uint32_t)MDMA_CTCR_SBURST_2)                              
    - n5 ~6 Y2 H7 i6 V
  4. #define MDMA_SOURCE_BURST_32BEATS       ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2)
    $ w; L# t) E' L- e: R. Q
  5. #define MDMA_SOURCE_BURST_64BEATS       ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2)
    8 p" ?6 Q, W: ~! r9 A
  6. #define MDMA_SOURCE_BURST_128BEATS      ((uint32_t)MDMA_CTCR_SBURST) 0 ~$ M& a& u+ R, T# Z) m. z
复制代码
8 |7 r' s: ^% F8 {( F
4 D; j# [' a4 H. k
  DestBurst4 n: W7 F6 L3 d$ u% @# b# j
目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下, q: M, E$ y; o6 A  M( ~
  1. #define MDMA_DEST_BURST_SINGLE        ((uint32_t)0x00000000U)                                       4 @$ `" W/ L0 I* [) k/ r( m
  2. #define MDMA_DEST_BURST_2BEATS        ((uint32_t)MDMA_CTCR_DBURST_0)                                 
    % h: O/ T  T8 o, ~# T' O
  3. #define MDMA_DEST_BURST_4BEATS        ((uint32_t)MDMA_CTCR_DBURST_1)                                 #define MDMA_DEST_BURST_8BEATS        ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_1) , B7 V$ O8 K: n
  4. #define MDMA_DEST_BURST_16BEATS       ((uint32_t)MDMA_CTCR_DBURST_2)                                 
    ' ~& Q4 S1 V( h
  5. #define MDMA_DEST_BURST_32BEATS       ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)  & w* d& w+ ^6 {5 P8 l, f
  6. #define MDMA_DEST_BURST_64BEATS       ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
    - K0 \. w6 p' ]# ?3 v# G% T
  7. #define MDMA_DEST_BURST_128BEATS      ((uint32_t)MDMA_CTCR_DBURST)  
    ' W+ U. q; C# P- n+ C: b3 [* a  X
复制代码

) P! ]& s4 f, X, ~* U  x3 H  SourceBlockAddressOffset1 ~9 t/ B2 U" l) u+ L0 ]
用于设置源地址端数据偏移。
( k2 Y. M% ]$ d& U& T
# D; e, F3 X5 ~( ^  DestBlockAddressOffset9 @+ d! D- l5 |$ I
用于设置目的地址端数据偏移。2 d. B: r/ O, `0 W& P) c2 a
* x# R" n0 k$ q$ ?
61.3.3 MDMA结构体句柄MDMA_HandleTypeDef2 ^- j+ C& }, J7 V" K8 `7 U
HAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:. ]/ T" n" U% }/ P

' F5 g' I0 D3 s4 F, M) B
  1. typedef struct __MDMA_HandleTypeDef
      t* O. R0 \9 r2 @$ s$ Q
  2. {
    + C  C" J' w2 l# ~( a
  3.   MDMA_Channel_TypeDef *Instance;                                                                                                                                                                                              & S+ r" G$ X& ?; B$ V# V; Q
  4.   MDMA_InitTypeDef      Init;                                                              / z  X/ u) x) R: W
  5.   HAL_LockTypeDef       Lock;                                                                  
    + C. \6 b) m. B. W( l( E! C8 P
  6.   __IO HAL_MDMA_StateTypeDef  State;                                                           7 l. ?) i5 ~* z  V$ o8 B
  7.   void                  *Parent;                                                               
    . ~- s2 V) J/ O" N7 Q  `1 h" [. |
  8.   void                  (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    . Q* |9 P) d  X; ]9 M, C
  9.   void                  (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     
    ! f1 @4 y( d8 {" g9 ~
  10.   void                  (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);      
    6 D; m, P) j& k" ~* ~4 Q# K' y  {& O( ?
  11.   void                  (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
    6 n% j6 U" w' M
  12.   void                  (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    4 a$ C- X. V# U# l8 i( j& [7 I
  13.   void                  (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    5 i. ~: A8 b3 w/ D2 O
  14.   MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;                                             5 W) i) {) }8 H/ T
  15.   MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;                                             * M; R9 O3 G+ D, S4 E, |8 ^$ Q8 |
  16.   uint32_t LinkedListNodeCounter;                                                                                                                                                                                      6 x( A" Z8 `3 d& [
  17.   __IO uint32_t          ErrorCode;                                                            : H# Z; W8 {& [( k
  18. } MDMA_HandleTypeDef;
复制代码

6 B, L8 V6 W1 W下面将这几个参数逐一做个说明。/ W2 `; u4 Y4 i1 c
9 G& @% e+ U/ J
  MDMA_Channel_TypeDef  *Instance, e$ v) b2 o- z) Q# I
这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。
, R/ w- A6 N; E+ G5 Z
4 u1 U0 O9 h& D5 z: n6 o+ |  MDMA_InitTypeDef      Init
& y. L4 `" `! \' |这个参数用于MDMA的通道参数初始化,详见本章3.2小节。
' I$ E- q9 ^5 b. P/ k* O7 E, L6 P. g- F: o$ ^  a# N( [
  void   *Parent
4 D, L5 {' W% K* v1 o" N, A用于记录MDMA关联的外设。
" b2 w, ~% a* E
$ w/ a. a  P2 v% k$ ?  B1 O/ \    void   (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);         
, Y: v: Z0 u7 ~. i8 j/ ~$ z    void   (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);    1 {( B9 N! c% K  e
    void   (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     
# z; D: t4 ~5 m% }! M    void   (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);7 N% t1 Q) U% v* R5 P$ U  R5 ]- y* n6 x8 }
    void   (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);          : |) r6 E* p( i: e! }
    void   (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);   
1 f8 w* r$ V$ }. G" n# WMDMA的各种回调函数。   
' G$ d- y- f# l5 s
' Z: T1 q8 }7 I) x+ N, I: n  MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;
, s# O+ |% L  k- B3 z  MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;
" ]8 Q1 j- d5 k/ c  E+ z- [* ~" ^  uint32_t LinkedListNodeCounter;
- Y+ l  G3 v3 v8 E用于MDMA的列表模式。; T# \9 p) _) }! O! ~6 d

' K/ m3 j3 r5 _  HAL_LockTypeDef          Lock           
# Q7 g/ E/ V6 v1 Y; O  __IO  HAL_DAC_STATETypeDef  State           
( e- {& j  s6 t2 B; r1 D( V  __IO  uint32_t           ErrorCode      ( p* C$ [0 P) X$ n, s! N
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。$ |" u+ P( M, ]4 c( e) w5 K6 q
7 \( y  F/ Q7 v( e* b. j
61.3.4 MDMA初始化流程总结
2 h) H' g' P$ |. e; u6 Q2 Y6 B使用方法由HAL库提供:3 F5 I+ D% V2 y

/ w1 D; c; M9 c& J  第1步:基本的初始化。
: w0 v+ B7 h2 W+ M; q- b8 z" \4 ~4 @3 s+ y
  函数HAL_MDMA_Init配置MDMA的基本参数。7 k0 b6 J: `$ w/ V# W8 @$ i2 |) w
/ F  h* |2 E6 ^& h4 P6 x! @+ P
" a0 h7 K# A# n5 i8 V$ l5 b" I2 \
  第2步:列表模式。8 V* J" F, c3 k* \) g/ T

! s, K" ?" v* D: s- a如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。, a0 M8 I. t& E% T& W

5 r( s; j$ R: Z" u$ A$ a4 P" y7 W) Z
8 h# `* y& q5 q  T) m9 a- W  第3步:查询模式。
: E; ^# B( A, j6 N# y/ G) y; W# Q
  函数HAL_MDMA_Start 启动传输。2 ?# W( ?5 ^# q1 X' N3 L& H
  函数HAL_MDMA_PollForTransfer 查询传输完成。( p' A7 G/ V& m; {
  函数HAL_MDMA_Abort 终止传输。; V7 g: p+ g3 X) H

5 t* a2 Q8 C- i3 R; j, Z3 {$ B' z: U/ e1 x* s; s  [
  第4步:中断方式。
/ d6 ~! G  v# [7 |; Y+ W# O# X4 }+ P' [
函数HAL_NVIC_SetPriority设置MDMA中断优先级。
; r8 w( j/ Y. @8 q 函数HAL_NVIC_EnableIRQ使能中断。
0 a8 v8 `& T) {3 X( w. R; D 函数HAL_MDMA_Start_IT启动中断传输。
0 J* J! h; R) T; H1 ]1 R: [# Y MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。2 q" N) G' i( R, e
函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)" U+ {8 F5 i; X% M

* [; K& l' X5 Y1 d: S5 ^
- T7 F4 S8 x) c. Q  第5步:中断回调函数。
% r- ]6 y% m7 `4 `/ Z% P7 k
% Q4 m) p+ I8 c4 W  i8 {函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。
" j# ?5 t4 ]3 x9 x
4 f& u: O" {" t, o& T3 S8 o) V  XferCpltCallback            : 传输完成回调。1 M* @. J" D" Z$ b9 ~6 g) V
  XferBufferCpltCallback      : buffer传输完成回调。3 c  L5 H0 o+ X( d* E0 L8 ?
  XferBlockCpltCallback       : block 传输完成回调。* J8 I& b" `! ]$ S/ V  V( i7 O* \* |( V
  XferRepeatBlockCpltCallback : repeated block传输完成回调。
2 E/ a/ X" G: E+ U  XferErrorCallback           : 传输错误回调。
- m  `3 z& S' G4 v  z0 p1 N5 {; R4 o  XferAbortCallback          : 传输终止回调。
  O+ J/ O7 h3 S) L) `; o( e. h( I5 b( H) l$ O8 Z

- d0 e) J: Q, g, u5 Q# ~' Q1 j61.4 源文件stm32h7xx_hal_mdma.c
( `6 {, B  ]5 C这里把我们把如下几个常用到的函数做个说明:* Q" [: ~, ^* i2 z3 E: l
$ N% ~, J; `$ b. D3 R  q/ p
  HAL_MDMA_Init$ T5 d' w! O) V% A  e
  HAL_MDMA_Start_IT$ n, K- n4 q1 C
61.4.1 函数HAL_MDMA_Init
; `7 p- I4 |) R6 f  k. k函数原型:
8 @9 z: o# F8 E2 v' U" ^* X2 a: t2 A* w# q/ {) j
  1. HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma), `7 s% g7 ?9 m; D1 {9 {  T4 o
  2. {
    % S  P% \/ P( s
  3.   uint32_t tickstart = HAL_GetTick();8 d5 E! w; C) N8 H, O+ h
  4. / Q3 l" O! S; G( e+ t
  5.   /* 检测句柄是否有效 */
    $ C. ]* A& O8 `" W0 L& Y
  6.   if(hmdma == NULL)$ l* ?  ~6 [9 Y. E  N/ Y0 t) k
  7.   {
    4 j* O4 M# e* E/ q2 |  \1 ~' g: m  t
  8.     return HAL_ERROR;
    * y* J7 U) a$ g6 @, d- F8 R! l! k- w
  9.   }
    1 a& C) w* ?$ G* K
  10. " s0 W' W: Q# P3 a$ X2 F
  11.   /* 检测参数 */2 Y6 C; b9 t9 ?% P
  12.   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
    ) X! [" Z# g; m4 \1 S
  13.   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));7 _+ f' k" o+ Y6 R0 U. A
  14.   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));" g& H6 r. `3 g+ X% p7 i
  15.   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));) ^1 D: e( S3 O" ~' \
  16.   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
    8 M( a# k" K( ^- p. m
  17.   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));; T) l3 ]/ h0 ?4 ?
  18.   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
    ! u/ l' i* U2 E. H* ^! T
  19.   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
    . \1 Y0 Y" H/ Z( \2 P, o- K
  20.   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
    / e5 }' ], q- W' ], _
  21.   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
    # U' M: a/ k" n: h+ D% Y
  22.   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
    3 Y$ R9 {4 E# W/ V9 c' |" O
  23.   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));" g6 j' M" ?+ Y9 x6 v9 q$ T5 ~
  24.   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));5 A0 e- U" O: |& h
  25.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
    " X0 n% _; f6 a" ?
  26.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
    9 _- a" L* X. t2 j& R2 c

  27. ; W4 p1 a0 M& P% K4 X: L

  28. ) W: \  j3 l9 i0 M! ?3 D/ W( v: @
  29.   /* 解锁 */
    ' x- S& g4 c- d7 {, P
  30.   __HAL_UNLOCK(hmdma);# U/ u- L, D8 Z1 g

  31. 9 w+ [) |4 n% C/ M: `
  32.   /* Change MDMA peripheral state */" a2 M1 l: o& q) }5 N
  33.   hmdma->State = HAL_MDMA_STATE_BUSY;* w, B, S6 L: B5 |% M; I

  34. 4 o/ L# o( [: z6 X3 n( W5 f! c$ Q
  35.   /* 禁止MDMA */0 i, P! ]+ k: m) O" H
  36.   __HAL_MDMA_DISABLE(hmdma);
    ! V& o2 N. S4 |! i2 P! @& v& M9 r8 h
  37. 0 i0 [* q8 n. |$ n# w( U
  38.   /* 等待禁止成功 */* f! @, m5 l8 I4 F
  39.   while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET)
    5 E( r  |! L0 c* I2 h. H
  40.   {7 b: s. }8 L0 k
  41.     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)1 m4 r5 |9 o. J# A/ Y
  42.     {
    8 w9 t. c/ [- N3 p- S; x. D
  43.       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
    + E# w( {' g8 Y# \7 Q! J& I4 d8 j! }
  44. * T9 F" @/ V' n0 y+ r( L" ?
  45.       hmdma->State = HAL_MDMA_STATE_ERROR;& @. @5 }* {/ V- }
  46. # v0 c7 t& ^  `* [& c
  47.       return HAL_ERROR;5 c- I' v* e1 @% i* w
  48.     }
    ' k8 }8 D& |1 A. A% K+ D+ W7 L6 |- v
  49.   }, k" g. ~# {2 x0 i9 D/ l- u" Q$ l

  50. 2 _% H3 W4 T9 x8 u( m7 e
  51.   /* 初始化 MDMA  */
    0 o( C0 T9 R% p( O% V7 V) w1 i. {8 G
  52.   MDMA_Init(hmdma);  \! A$ R8 |) a) b
  53. ' q1 o( t: l9 E3 O1 H5 P
  54.   /* 复位列表模式相关设置 */$ c1 G; \, q0 A
  55.   hmdma->FirstLinkedListNodeAddress  = 0;
    ; N) h2 M& ~4 O: x
  56.   hmdma->LastLinkedListNodeAddress   = 0; + K3 v, E) p, Y7 J4 d
  57.   hmdma->LinkedListNodeCounter  = 0;  
    # W1 N. N4 J+ H( O

  58. ) B) @& W0 r* O
  59.   /* 设置无错误 */! G2 J4 s) M0 j. _& i' n
  60.   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
    1 U/ |  y- n* T

  61.   b. T2 m3 B! P* E
  62.   /* 设置就绪 */4 `9 |8 Y+ ^. N4 ^
  63.   hmdma->State = HAL_MDMA_STATE_READY;9 R5 A% v  w9 X0 D/ B# m9 v$ u

  64. ' N9 h+ Y( H. G/ l, S
  65.   return HAL_OK;
    ( z! ^) O4 s* [* Z! @7 g1 y
  66. }
复制代码

8 x) l* p7 p9 t- L
/ f" F- ?! J1 b) {+ k& [7 P* F2 r: ^- T# r
函数描述:
4 I) M. P( I$ Y! R% l" \8 [4 ]6 X
此函数用于初始化MDMA。
) H$ B# j6 m9 A2 L6 K' p) `6 `$ B0 f$ ]& o0 M+ r& E
函数参数:6 ~' c: z( [/ Y
- t/ Q0 b* I6 L$ q" o
  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。6 K: I2 M& e; ~6 A3 N# p3 V$ V- `
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
; |& `1 \. S) T# c使用举例:
% s8 Q( r& A/ y: J' d+ E9 q' W+ G# z" D. `' H
  1. MDMA_HandleTypeDef  MDMA_Handle;
    $ i' o0 F% \1 R. B3 b( O
  2. 8 L) j8 v9 e0 F$ ^4 r+ u
  3. __HAL_RCC_MDMA_CLK_ENABLE();  1 n' L( ]  A4 b3 H$ r
  4. # e1 z* N7 L1 z
  5. MDMA_Handle.Instance = MDMA_Channel0;  
    / q0 ^1 x6 q& X

  6. 3 k# |  ?/ F9 V4 _9 ]+ h
  7. MDMA_Handle.Init.Request              = MDMA_REQUEST_SW;         /* 软件触发 */
    " q# Z( _. r; Y- n7 e
  8. MDMA_Handle.Init.TransferTriggerMode  = MDMA_BLOCK_TRANSFER;     /* 块传输 */: o( [+ K' e5 J8 C( c, g3 w
  9. MDMA_Handle.Init.Priority             = MDMA_PRIORITY_HIGH;      /* 优先级高*/
    8 w7 N$ @6 N! X9 u' M: y
  10. MDMA_Handle.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */; c1 {+ F8 S5 ]% O. l
  11. MDMA_Handle.Init.SourceInc            = MDMA_SRC_INC_DOUBLEWORD;         /* 源地址自增,双字,即8字节 */
    % ~$ _' R- {  v: z8 V& j
  12. MDMA_Handle.Init.DestinationInc       = MDMA_DEST_INC_DOUBLEWORD;        /* 目的地址自增,双字,即8字节 */
    + f4 y& W6 Q: F' O, J8 e! H
  13. MDMA_Handle.Init.SourceDataSize       = MDMA_SRC_DATASIZE_DOUBLEWORD;    /* 源地址数据宽度双字,即8字节 */& U( }; I* c8 e  Q
  14. MDMA_Handle.Init.DestDataSize         = MDMA_DEST_DATASIZE_DOUBLEWORD;   /* 目的地址数据宽度双字,即8字节 */1 O: R; v$ a9 K5 v  I
  15. MDMA_Handle.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;       /* 小端,右对齐 */                    - E( I% }3 W$ y! k
  16. MDMA_Handle.Init.SourceBurst          = MDMA_SOURCE_BURST_16BEATS;      /* 源数据突发传输 */- _/ M2 M9 w+ p. U6 r% u
  17. MDMA_Handle.Init.DestBurst            = MDMA_DEST_BURST_16BEATS;        /* 目的数据突发传输 */: i" g& ~9 @3 i; e9 S  t! s0 R6 I

  18. ; ^+ @* {) d5 N8 B
  19. MDMA_Handle.Init.BufferTransferLength = 128;    /* 每次传输128个字节 */6 L9 f- ^- K! E! j: V, S. C4 [

  20. - w- n# \, Q+ E8 i1 a
  21. MDMA_Handle.Init.SourceBlockAddressOffset  = 0; /* 用于block传输,地址偏移0 */
    % G  n; C1 x) j, L7 }; V6 f
  22. MDMA_Handle.Init.DestBlockAddressOffset    = 0; /* 用于block传输,地址偏移0 */
    , ]$ o" h+ o- O/ x" ?% z, Z: q7 f
  23. $ J# p! G* d3 k
  24. /* 初始化MDMA */" d9 u0 v1 j8 u& I) J" o
  25. if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)2 B; q. G1 ~  _0 o- r$ _; Z
  26. {
    7 h# V4 }. @# p6 G+ J- u0 k- M3 b
  27.      Error_Handler(__FILE__, __LINE__);
    9 p5 _  S- N+ _% w& u
  28. }
    7 t5 h! |5 Z/ L. z% ]

  29.   j8 e4 a! {9 b; e( @( H" I: `
复制代码

. v) a' W6 H: N3 H+ K61.4.2 函数HAL_MDMA_Start_IT3 Z. X2 J1 W2 ]# O) l
函数原型:
5 M# B: {+ x" J/ ~/ x
. E5 j9 ~! _. h, g4 ?: _
  1. HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount). V8 s# k( `- d
  2. {
    - t' ?2 B6 S, F& F1 ^0 Z: w8 s9 v- l
  3.   /* 检测参数 */
    1 E% [! C6 {6 G! G/ c  U6 v
  4.   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
    ; Z2 t3 G/ B  t' o
  5.   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); 6 l) q  m$ @2 w7 w6 Y, T
  6. 0 a7 ^' _! F7 G/ b" ]: P9 Z
  7.   /* 检测句柄是否有效 */! F2 {/ ^% W5 i9 [/ e4 A
  8.   if(hmdma == NULL)0 U& k. |3 ]( b8 ?: D2 t
  9.   {1 H. I1 b0 ~3 G
  10.     return HAL_ERROR;
    % Z3 d" R& x5 A0 }
  11.   }
    # Z$ q7 s& w# p! b0 }' ?9 i
  12. ( L& D/ ^* z' M7 {  x" S2 V
  13.   /* 上锁 */6 y' K% Q2 M$ L6 B/ M# _
  14.   __HAL_LOCK(hmdma);& D9 K& E$ q; g

  15. ( d( j  M3 l# ?) K9 M1 A
  16.   if(HAL_MDMA_STATE_READY == hmdma->State)
    5 O& ]1 F6 E$ j+ Z" T% V
  17.   {5 K+ J  q" x( l9 R: ^5 R( y) W
  18.     hmdma->State = HAL_MDMA_STATE_BUSY;+ a! p& N  a% E: N* f

  19. 6 k4 a* c0 S1 r6 O; t& d% R; R
  20.     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;     $ I2 V6 N$ f. K3 r# j, D' j+ S
  21. & h: k3 ~0 m  \$ J6 S/ |" G1 H
  22.     __HAL_MDMA_DISABLE(hmdma);
    . J( R1 e2 u+ G# H; x, ^9 w& @1 B

  23. 2 e- _' M0 {7 v9 z, Z6 _3 H
  24.     /* 配置MDMA */
    , t% \# o- D0 Y8 n
  25.     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);, q# f( G0 E: l- a& V/ b

  26. 2 Y3 J1 ~2 w# f4 D( L9 Z7 e
  27.     /* 使能传输错误和传输完成中断 */6 C8 L3 t+ y8 y% H
  28.     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
    + b- P$ c- j. I! n
  29. 7 C4 C! K+ `8 x' f
  30.     if(hmdma->XferBlockCpltCallback != NULL)
    1 h9 C8 Z8 n  v2 q& d+ U# _
  31.     {
    ! l1 e+ |" _9 n0 g
  32.       /* 使能块传输完成中断 */' }" P' Z. H. q" \$ E' Y. E
  33.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);   
    8 l* U( B5 c9 \% e* u& Q# d; c8 y
  34.     }9 e# X' o$ |3 `+ C9 L
  35. 0 p. q( V# [5 ~- q2 x
  36.     if(hmdma->XferRepeatBlockCpltCallback != NULL). A8 f! C: r0 E& d$ a; @9 A6 Q
  37.     {
    . p& W6 T4 o( ?5 w
  38.       /* 使能多块传输完成中断 */      / ^( @) x6 j6 b7 e  H8 D
  39.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);    / @0 n3 V  ~7 ]9 F
  40.     }  
    : P# g, s7 ~5 b( e- }( J$ j1 s

  41. 3 W- b2 ]1 e* \, c
  42.     if(hmdma->XferBufferCpltCallback != NULL)
    1 a+ h- e$ x* ]+ ?
  43.     {: M/ b" C; X# l& j5 K. ~2 @9 c
  44.       /* 使能传输完成中断 */
    ; m0 R# G) I# j, Y0 p
  45.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);9 u; [) H( k- L
  46.     }
    ; `1 W& ^. m( @5 x" J
  47. ( `+ B7 f5 {2 w. Q2 n
  48.     /* 使能外设 *// x  O# f+ K0 |! t. a
  49.     __HAL_MDMA_ENABLE(hmdma);& x5 z* i3 j7 p5 x7 H+ T

  50. : J( y8 ~4 X+ _  D7 W# s/ |
  51.     if(hmdma->Init.Request == MDMA_REQUEST_SW)# p9 r+ i1 @# W/ k! ^
  52.     {
    8 W# N) w1 @4 S/ m: I; ^# N
  53.       /* 使能软件请求 */
    4 w9 B, u; A; h0 b
  54.       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
    / H1 {& F9 U7 E  s5 z  A2 W. B. c
  55.     }  2 G# |, f0 G* k5 P7 l. V4 Q7 B
  56.   }
    , a: D* W6 ]" r1 [6 I* C
  57.   else1 |) f1 l+ [9 j+ ?5 P
  58.   {
    - {9 K7 Z. o  O1 M; x
  59.     /* 解锁 */
    - `8 X$ d  W* g7 |" ~: W
  60.     __HAL_UNLOCK(hmdma);
    ! U7 f& q! u, d" @

  61. ) D% X: m5 k2 ]+ i4 c. j- d3 k9 f/ |
  62.     /* 返回忙 */; H1 @8 F) b  j1 ~1 R5 g
  63.     return HAL_BUSY;
      w7 K9 d$ o! F- A+ l$ v/ S
  64.   }: g6 p8 u9 s! V2 G" n

  65. 2 p/ |) M- S% o- z! r; g: w- [
  66.   return HAL_OK;9 P( K6 f; y& x' S& D
  67. }
复制代码
3 [6 G+ Y& Y! R0 o: t
7 o- q: w' N5 g1 I5 Y) J/ b

8 Z3 Q# c# V/ O, `函数描述:
3 `& l& p4 ^- Z( I/ k% Q9 }
1 F% O8 R& r; |% J! k' S此函数主要用于配置MDMA的中断方式传输。" Y' Y% L- \; M8 v
: M% w1 ^9 y- L" v  P
函数参数:4 v% L- L4 |, H9 E: }0 r" u

; ]" `3 S6 _: U: z' S1 Z; W  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。: l0 Y+ u% I3 i% w7 L. Y
  第2个参数是源缓冲地址。
! I! q0 x6 Y' {6 f! x0 X  第3个参数是目的地址。
5 d+ N  O3 q8 j- B  第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。
: h$ O2 A4 x* `% ~4 N0 e  第5个参数是传输的块数,范围不可以超过4095块。- B2 l& C1 B+ ^- t
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
- {% y& y/ o' ]6 h使用举例:
5 V- A) b4 K% f( i% h  c1 A
! c; @% A+ ^' D1 h
  1. /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 *// S& d. i7 K3 w9 m/ }
  2. HAL_MDMA_Start_IT(&MDMA_Handle,
    + K2 H, I: d% M6 m% V
  3.                   (uint32_t)0x24000000,
    / {. u0 k* M) g; r/ h$ o
  4.                   (uint32_t)(0x24000000 + 64*1024), . [3 W5 m! W0 X7 P. o
  5.                   64*1024,
    $ `) n; q+ a  M* S/ m- _
  6.                   1);
    ' l; h- `0 U' _5 x4 Y$ l
复制代码
6 h- U5 P, m1 Q

/ b: M4 T' P% _- K) t61.5 总结
* N! t7 p1 F8 W本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。
" M  }9 ~8 g/ I& H  P& v' G5 F, u$ I! M  M

3 |9 G5 F7 D# A8 P7 o
收藏 1 评论0 发布时间:2021-11-1 08:00

举报

0个回答

所属标签

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