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

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

[复制链接]
STMCU小助手 发布时间:2021-11-1 08:00
61.1 初学者重要提示# n* T% a3 q$ Y$ I/ X& [2 H: e8 E( V
  MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。. s7 J) s, Q% K6 w: w3 H
  对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。
( _# @0 a8 Q- j# ^, s+ e61.2 MDMA基础知识
* H# B0 c5 i1 }4 O4 b) O( }) A对于STM32H7的MDMA了解到以下几点即可:
: U6 {2 t2 K" c- m3 B) n- b# Q( n3 I
- D3 O9 U9 r# f5 Y6 m; e  由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。
0 s4 _5 }) `' v4 k$ F2 |  MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。+ j; k( R* v; r* ?
  有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。
2 r; y& _9 ?" R/ P  [8 j; \  16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2! Y- z) K0 @. u) l! E2 z  h
  MDMA具有一个256级的DMA空间,被分为两个128级空间使用。
" Q& Q$ i0 [+ Q. k  j0 C) Q  MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低
1 Y6 j; q- X; i+ {/ ]7 V  数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
7 d+ w" N5 y# S1 G, n) s: M  源地址和目标地址的大小和地址增量可以独立选择。* M% q" w( m& j8 ~& x* k; E, o. v) H
  数据的打包和拆解是采用的小端格式。( J( K: s% `% L2 E8 A2 H
  支持突发模式,最大可传输128字节。
: o3 L1 {" j! z' X* x3 W+ k  当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。) {; V- ?! H5 g+ x+ x5 P3 B; Q& w0 K! D
61.2.1 MDMA硬件框图
7 _9 {. r/ h1 K+ n, L$ k. P1 B认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:5 [& [0 ~! g7 i

! g$ M9 _% }( Q
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
9 o0 n5 t8 u, p# [
通过这个框图,我们可以得到如下信息:! R, v& p4 n7 \5 r
5 t2 d" N2 P; _3 ?
  mdma_it
- I, Z/ g" P. c% M7 k7 C; _' c5 nmdma的中断触发信号。; r# n7 Z- Y& C$ f. d

. c: ]/ `* j2 o$ N% u4 U: e) w/ c  mdma_str0到mdma_str31触发源
" C1 w, Y0 E7 v# r" Omdma的输入请求。: M: J/ C4 Q# E' V: @5 g

$ g7 R9 i0 V) ?& N4 A  mdma_hclk* g" T  {, c6 L6 j
MDMA的HCLK时钟。1 v$ o" h; s& @
! T9 A- q4 O- V
61.2.2 MDMA块传输,缓冲传输和列表传输区别: p( A/ s& t* z/ {( G+ M# ^! _
初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。
* r7 {( C% H' U% K# q9 I  R& W# Q% j$ f
  缓冲传输(MDMA_BUFFER_TRANSFER), i2 ^* A8 j1 G% Q/ _
这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。6 g4 V$ H" Q* e1 w

, Q0 V$ l0 R! X% |: Z5 T4 o9 W- D- L3 C
  块传输(MDMA_BLOCK_TRANSFER)0 `; r5 N  y4 h8 Y
此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。5 p& j- ^; Y: s1 E$ }: _

' X4 m# w1 G4 |# I$ h3 w8 m% o, t2 Q
  多块传输(MDMA_REPEAT_BLOCK_TRANSFER)4 r% }- t+ [+ R: n
顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。8 L) h4 Y' m& t
/ v! p' E8 k% v1 ?
$ N$ d( ~7 y0 j6 C( f9 T
  列表传输(MDMA_FULL_TRANSFER)
' N4 g5 K2 _) x这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),
' S% b4 ~  i) e% z- [# b
5 x' y  h$ Y7 u+ R61.2.3 MDMA列表模式及其循环方式
3 H3 E& |* \8 x+ t4 c* ]4 C( F6 F列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
: o4 |- x: g% P- B
! R3 N' s4 y0 L( p  使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。
  Q2 J1 S. Q# ]4 e9 `- p6 ]  使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。" E2 D& M) E1 P2 @5 n6 l( I
  节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。+ r: |. [# x4 u/ }( c: T: {6 d
  如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。% m' D0 w3 W; \# q4 M4 F
  通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。
5 t  M5 Z8 [# t7 q" @/ @61.2.4 MDMA的触发源. D" V: p5 {- X, l6 w2 E# J
MDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:+ Z3 o0 ~, }1 Y, l+ _9 Q/ R
2 x% `% x2 }! K% j5 E/ Q+ G- ]: O
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)
    ! w% }- g! ]* D8 }; I8 D
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  
    ; B" e: j0 {3 l; J: r
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U)
    * N; v& I; _' W  U. V
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U) " o" X& ]1 j+ d& V6 r
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)7 R7 K5 V" j7 ^( B- n  q9 t
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U) 9 [) [0 G1 x* V/ H1 i# y1 H. K3 _
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)
    6 K+ e+ {4 c0 r
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U)
    . a2 ]# h( b8 F  ]+ t  ^; f
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  3 S  q4 @: U' K* _$ p
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)
    1 W/ n2 X  L8 M
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  $ B( g/ E2 T" |' L' `3 ^
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU) ( v; }/ l. Y2 ]
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    / M9 g: I9 ?. A' k
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)
    4 A2 r, i/ Y2 x: r# \; C" l! T/ @. c* u
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  
    - Q( G# v) ^: }( t; @) q
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)
    3 q6 b+ @- m" T( g& c( _- ?
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  ) @' v# {1 e% V6 D2 \
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U) 4 D& E& d! L$ l1 `
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)
    2 R# M& Z) V) _
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)
    ' g4 I! M" k$ Q( G: w9 W+ K
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  2 Y3 E; ]- a1 B& M. L
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  
    8 a  i4 C- x2 H/ W0 u' v
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  6 ^$ W' O- b2 t# h
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)
    , t) Z1 @, \1 H* C
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)
    ; Z- K4 `0 {2 p* g
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U) / H( ?% `3 j$ W9 n, ^
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)
    & ~! Q9 K" f- e( H: A

  28. & x4 ^9 N0 v% I+ c1 [( ^% k
  29. #if defined(DSI)
    - p- |; r$ f/ f/ x% \' [
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU)
    5 v7 n/ o$ M' u& D
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU) 3 V6 B6 P1 d* j* h0 a
  32. #endif /* DSI */% L$ W8 M# X/ }# e
  33. - B- I  g( i/ |' v$ x
  34. #define MDMA_REQUEST_SDMMC1_ED_DATA      ((uint32_t)0x0000001DU) 1 i* w  B* U( k3 R# p0 I& U) l0 s

  35. / [; Q7 M; n. m1 u
  36. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U)
复制代码

1 @0 i6 u. ~" W
1 L8 N3 p& R! B* |
! N; i7 U9 c6 q) K5 i0 h6 F% C4 @6 X61.2.5 MDMA的软件触发方式
. [* J+ w! }( _  Q: `2 Q2 nMDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:
* O- \$ K% Q4 t) K3 w0 Q
7 N8 r% _4 H1 k  如果传输结束或者传输还没有启动,调用此函数会返回error。
  Q1 s, O, c5 G  如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。3 I8 Y" Y* `6 _; x! ^" i

9 A  A8 ^5 M; t. Y) Q/ k, e0 G" `8 [. ^! O9 G# K
应用示例1:/ I# I3 x: v# i/ z4 a

1 R5 x" q2 j7 S5 p: `  MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。
/ n! K& y# ^3 _: u+ |0 Q/ }  注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。" k7 f. C' e& a1 W) x3 ]
  调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。! s7 i1 f5 C) f2 v# m2 b8 O+ h
  传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。0 f) p1 e1 I  k) N/ Z

! t  s  p$ O% m0 \7 d; l9 }
; c, C1 Q" W& f! g: L2 ?  ?( V应用示例2:1 D/ b: d/ C3 s3 B/ ~" G

4 h! ^8 Q5 E4 l$ l$ E  MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。' H* d/ F5 x. Q' r' \, K
  注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。
/ T, [' n* ^& U  调用函数HAL_MDMA_Start_IT会触发一次块传输。
; F' y7 I# F! }3 y/ o' _  传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。) C" K' z# g7 N- f
61.3 MDMA的HAL库用法  @2 i# Z! ?5 {0 U% [  i4 R
MDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。& D5 u/ X( n4 n+ n; _

1 f% b7 q; V, p7 N! i' x3 p9 m% O3 ^( }61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef
1 k: m: q( n) F$ M; W$ m  i) s% Q5 SMDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:
  A7 G+ C3 m3 T7 U  y0 h
8 [# q) R: p9 U, o
  1. typedef struct+ b: Q4 r+ F: T+ W! r5 w  b
  2. {  z* g$ k8 F$ f, s4 {0 T
  3.   __IO uint32_t  CISR;      /*!< MDMA channel x interrupt/status register,             Address offset: 0x40 */
    . Y$ W) A9 w' \/ d
  4.   __IO uint32_t  CIFCR;     /*!< MDMA channel x interrupt flag clear register,         Address offset: 0x44 */: D# r. p! B* }5 D0 b+ ^" G
  5.   __IO uint32_t  CESR;      /*!< MDMA Channel x error status register,                 Address offset: 0x48 */1 [. X+ [1 O  ~. I' P
  6.   __IO uint32_t  CCR;       /*!< MDMA channel x control register,                      Address offset: 0x4C */ ; x2 D) D2 r0 Q! {( |
  7.   __IO uint32_t  CTCR;      /*!< MDMA channel x Transfer Configuration register,       Address offset: 0x50 */
    0 h7 {  g8 O. M: Z: x8 F
  8.   __IO uint32_t  CBNDTR;    /*!< MDMA Channel x block number of data register,         Address offset: 0x54 */' f3 y/ N! D6 E) ~- e: u9 }, _
  9.   __IO uint32_t  CSAR;      /*!< MDMA channel x source address register,               Address offset: 0x58 */
    + P& \7 D$ [" M
  10.   __IO uint32_t  CDAR;      /*!< MDMA channel x destination address register,          Address offset: 0x5C */: `  ?4 Y! ^+ ^- M" N+ o; N
  11.   __IO uint32_t  CBRUR;     /*!< MDMA channel x Block Repeat address Update register,  Address offset: 0x60 */
    $ g$ m6 J7 z" `
  12.   __IO uint32_t  CLAR;      /*!< MDMA channel x Link Address register,                 Address offset: 0x64 */& Q5 M$ ^6 X5 B
  13.   __IO uint32_t  CTBR;      /*!< MDMA channel x Trigger and Bus selection Register,    Address offset: 0x68 */
    / f1 o7 ^/ N( G* I+ {* i/ V
  14.   uint32_t     RESERVED0;   /*!< Reserved, 0x68                                                           */  & y; C# n+ D; |# X4 {% U- D
  15. __IO uint32_t    CMAR;     /*!< MDMA channel x Mask address register,                Address offset: 0x70 */
    ( z3 Z* ~4 p2 \+ E( w! R
  16. __IO uint32_t   CMDR;      /*!< MDMA channel x Mask Data register,                   Address offset: 0x74 */
    . n7 Q1 L8 K4 _% \& {
  17. }MDMA_Channel_TypeDef;
    6 k7 S5 P" _3 h) j' H0 j
  18. 8 m0 b4 c! o8 _
  19. typedef struct
    , Z% E; ]( a* u' k) R" |7 D5 M
  20. {* O* v7 r: N8 D9 D9 T: v- D
  21.   __IO uint32_t  GISR0;   /*!< MDMA Global Interrupt/Status Register 0,          Address offset: 0x00 */* z' f$ F" v0 A
  22. }MDMA_TypeDef;. S# R8 }3 H& P
复制代码
2 s5 ]) Y& V# w- ?" @! r

8 k' m. T; B' @/ |9 u2 L__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
$ R* W* v' ^, o6 y8 c
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    + q: N: i/ p1 m& q8 g  [
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

" w+ V& j& Y3 s. d* m4 ]2 L下面我们再看MDMA的定义,在stm32h743xx.h文件。
2 l* _( l/ |' d. V7 F& c$ _- d& d( o1 T8 \/ {
  1. #define PERIPH_BASE           ((uint32_t)0x40000000)
    9 }! k6 M- D7 P" s* N2 \9 \# T$ F
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000)
    - `5 O: N% M) H* w
  3. #define MDMA_BASE             (D1_AHB1PERIPH_BASE + 0x0000), d  e0 ^, ?, v, C- y$ D2 G
  4. ' z) s2 j" Y! d; i5 t
  5. #define MDMA_Channel0_BASE    (MDMA_BASE + 0x00000040)( w' n4 \8 x, ^
  6. #define MDMA_Channel1_BASE    (MDMA_BASE + 0x00000080)
    ) S0 c5 `6 U% f) v$ F
  7. #define MDMA_Channel2_BASE    (MDMA_BASE + 0x000000C0)- ^3 p$ j! [  r5 u
  8. #define MDMA_Channel3_BASE    (MDMA_BASE + 0x00000100)# J9 I& _/ Z. \# z" p
  9. #define MDMA_Channel4_BASE    (MDMA_BASE + 0x00000140)2 O6 h: z1 K8 w( F9 u
  10. #define MDMA_Channel5_BASE    (MDMA_BASE + 0x00000180)
    . W5 n: k/ F: [* h0 G2 E3 C0 s  D$ e
  11. #define MDMA_Channel6_BASE    (MDMA_BASE + 0x000001C0)! ]: d! c6 b: k  E2 Y, O6 t
  12. #define MDMA_Channel7_BASE    (MDMA_BASE + 0x00000200)
    2 s8 Y9 W) X3 W
  13. #define MDMA_Channel8_BASE    (MDMA_BASE + 0x00000240)
    * D, n; s2 z! `; L6 A% ~/ z
  14. #define MDMA_Channel9_BASE    (MDMA_BASE + 0x00000280)2 H  v# S& G( f  j
  15. #define MDMA_Channel10_BASE   (MDMA_BASE + 0x000002C0)
    / s6 O9 O1 @, L! O' v9 y9 D
  16. #define MDMA_Channel11_BASE   (MDMA_BASE + 0x00000300)& C5 s* c) @6 [7 _/ I
  17. #define MDMA_Channel12_BASE   (MDMA_BASE + 0x00000340)" n& p- E7 w% P- _/ R
  18. #define MDMA_Channel13_BASE   (MDMA_BASE + 0x00000380)# P) w0 e4 b! M2 Q8 v1 Z* H
  19. #define MDMA_Channel14_BASE   (MDMA_BASE + 0x000003C0)
    . H( a) [7 z  D0 M% ]& R
  20. #define MDMA_Channel15_BASE   (MDMA_BASE + 0x00000400)
    $ S6 j$ b! o& S
  21. # N/ {6 q; v3 U
  22. #define MDMA                ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000
    . F* D! A4 N) W8 U
  23. #define MDMA_Channel0       ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)
    / C- d; K! U) |4 Z5 \& Y, q
  24. #define MDMA_Channel1       ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)" w! L5 ?, A: O4 g( a
  25. #define MDMA_Channel2       ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)
    ; F: `% {! _: S! C4 j/ M
  26. #define MDMA_Channel3       ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
    + p- ]) O7 e, Z7 H9 U
  27. #define MDMA_Channel4       ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)7 e9 O7 K" O2 W
  28. #define MDMA_Channel5       ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)- J& x' g% W$ R6 O
  29. #define MDMA_Channel6       ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
    3 u2 V0 \, n' s  T) ^+ f, H
  30. #define MDMA_Channel7       ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
    , b0 B) y& D2 T7 k* t: W
  31. #define MDMA_Channel8       ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)* q) p: R5 r/ t0 ?5 z
  32. #define MDMA_Channel9       ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE). M* u6 \$ y) f  j2 g. j
  33. #define MDMA_Channel10      ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)
    + B9 l" b" T* N: {
  34. #define MDMA_Channel11      ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
    1 _+ ^: E& `& s/ R) {7 Z2 I
  35. #define MDMA_Channel12      ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)
    : g5 a$ \0 D& }& E$ I8 P2 Q8 r6 r
  36. #define MDMA_Channel13      ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
    " t6 Q: M* ~! R  ^9 R" q/ R
  37. #define MDMA_Channel14      ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)
    % ]+ w) _- w9 T& t/ H
  38. #define MDMA_Channel15      ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码
% x1 t5 t) e  n# ]% ~% J. W
( n0 X, ~  s! i1 g0 y

2 p9 @/ {, {& M+ s) ^* c6 F我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。
; F7 a% x1 H6 ]& N% [+ m7 S7 x
* _. j7 p: J1 ^61.3.2 MDMA的参数结构体MDMA_InitTypeDef
6 x7 g% ~6 I& F: a此结构体用于MDMA的参数配置,具体定义如下:
* A5 h8 j9 ~7 T; ]1 t9 a3 |( E$ U& i; _
  1. typedef struct) [6 b6 S1 k, }6 l7 Y. d
  2. {0 d4 k- v1 m+ @: o
  3.   uint32_t Request;                                                
    ' h& Y- r# T) a& ], ~
  4.   uint32_t TransferTriggerMode;                                    5 d: X/ F9 d3 }! I6 p
  5.   uint32_t Priority;                                                     
    - C) _: Y' G: _$ B2 \5 n
  6.   uint32_t Endianness;                                                
    4 x* e( K. z8 t! Q, Z2 c) z
  7.   uint32_t SourceInc;                                             
    / X+ x. L6 I5 x
  8.   uint32_t DestinationInc;                                        6 g6 E4 Z3 z8 t& p4 P
  9.   uint32_t SourceDataSize;                                         - m) E8 l: D& ~9 u. A0 \
  10.   uint32_t DestDataSize;            
    # c$ w2 |; x; m8 s5 D- l( H
  11.   uint32_t DataAlignment;         
    : ^; k3 ~% K6 l7 ~" e' K) f6 y
  12.   uint32_t BufferTransferLength;   
    + E# i' w' K& |) f$ U5 Y
  13.   uint32_t SourceBurst;                                            
    # W2 p1 B9 R3 [- S! G
  14.   uint32_t DestBurst;               
    % t: [1 r& Y9 c  y& ~* L6 B  V
  15.   int32_t SourceBlockAddressOffset;                                                                            $ M- ^0 i* \7 d: n9 o" K5 x. V
  16.   int32_t DestBlockAddressOffset;      
    % W3 L) _# t* [  i: u$ {0 j* D
  17. }MDMA_InitTypeDef;
复制代码

( K& {! {- _2 J1 j* ^- l" }
8 a$ w4 X. X4 O, L, q
9 n9 _! I5 x  Z! ]下面将这几个参数逐一为大家做个说明:5 a# b, Y9 H3 v3 D4 H

; m" W& f  P7 Y  h  uint32_t Request  o/ H) z# p5 `2 e. t1 I5 u
触发MDMA的请求源,支持请求源如下:
4 V( D& ^! K1 x/ T/ Y/ z
1 [( t+ ^6 I- e/ p. w( x
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)  
    & ~' l5 \6 h, Z! M$ P+ h) G
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  5 `% F6 _* q# o+ M! }; G# V( E
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) ( o) H) G) [  N1 C; A& F
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)  
      t- f# u+ |. w
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)  
    $ z$ S. W8 u+ }6 l
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U)
    ' B5 k; r- I$ a" u% z7 x9 K6 e
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)  
    - u% Q2 S' a$ e  k9 j5 i* q9 m4 X
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U)  
    8 o; m) b7 |% S; S& ^
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  
    : D1 ]7 c6 V" ?) j- \7 q$ b5 c: e/ R
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)  
    ; F2 O- o0 E& O" x# ~' m3 V
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  
    - c7 ?* d' Q' v5 x) F
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)
    ' x+ F" r3 Q1 e- q
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    & Q% n  F1 a6 v5 n7 m
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU) ( D2 t; X5 w. l" A4 B& \
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  
    1 K4 Y5 u4 t7 |3 Y) F
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)  
    ) s: |4 k  h) u' K2 n
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  
    4 V% X' Y" s  U: o
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U)
    4 x% J2 _+ b, o# A; `! i6 X, g7 o
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)  4 K7 y; [- ?: _7 W
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)  
    ( i$ n. X( h7 _
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  7 V  \/ K, c/ p: r& `
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  
    ; u- @- W4 S0 i, ?9 D
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  ) }5 ]6 @9 P# }: U4 k  L8 ?
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)  : S1 V9 t) d! m' }1 p
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)  % e0 ~% j* @9 i1 Z4 H+ N) a
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)  
    , \2 G& }7 I* L" [1 U: w
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)  
    , [0 B! |. g& n/ `  N. l) c
  28. ( P9 p, G* V0 ^/ B* z& t8 U2 i
  29. #if defined(DSI)
    ' c. @- l9 }/ `! l. e1 a' k
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU)  
    : G5 @. n1 F4 U9 Q3 r) ^7 A2 N$ a
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU)  8 i* a' g1 {! e  T1 @
  32. #endif /* DSI */
    ( D1 @* t' p/ e/ h0 t5 v" |

  33. 3 H/ D+ }6 p& B
  34. #define MDMA_REQUEST_SDMMC1_END_DATA      ((uint32_t)0x0000001DU) ' n+ ~- k+ R4 l
  35. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U) 2 c9 q: g; N9 u, Z! I* X5 X5 O
复制代码

& z: A% \- B( Y- R7 |/ [* W
( D: G9 g; [9 {6 G; ?  uint32_t TransferTriggerMode- ~5 E9 s! c6 g
MDMA的传输模式,具体支持的参数如下:+ w6 y! n, T: m$ Q' H) W

' |2 m% L: H7 D" o$ }, \
  1. #define MDMA_BUFFER_TRANSFER          ((uint32_t)0x00000000U)      /* 缓冲传输 */! h2 S, r' l8 I2 Q! ~
  2. #define MDMA_BLOCK_TRANSFER           ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */
    % ]  B# f0 ?' \0 D% h9 M% O8 O" v) j% L
  3. #define MDMA_REPEAT_BLOCK_TRANSFER    ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
    $ \; S4 G# p5 R* p9 h
  4. #define MDMA_FULL_TRANSFER            ((uint32_t)MDMA_CTCR_TRGM)   /* 链表传输 */
复制代码
6 O3 k* H$ z) S: z

; ~: |7 c+ u8 n* ~8 h6 Q+ N: j
* H! C! H4 U7 R# E  uint32_t Priority
5 q, Z; Y5 z& u% e# MMDMA通道的优先级设置,具体支持的参数如下:+ M( z  c* \3 B' U" @
" n9 \* X2 H; K7 ^
  1. #define MDMA_PRIORITY_LOW             ((uint32_t)0x00000000U)     * z# j: T3 m( U
  2. #define MDMA_PRIORITY_MEDIUM          ((uint32_t)MDMA_CCR_PL_0)  % R: \0 K! d/ k3 V
  3. #define MDMA_PRIORITY_HIGH            ((uint32_t)MDMA_CCR_PL_1)  
    2 @8 a* J+ L' G
  4. #define MDMA_PRIORITY_VERY_HIGH       ((uint32_t)MDMA_CCR_PL)   
复制代码

6 K6 S: @: P: z  V) v( @6 e2 d, i9 @3 p* @, F- o; ]
9 |7 h8 j# P" `9 W+ U
  uint32_t Endianness
6 i" A+ n0 Y7 x8 RMDMA数据传输格式,具体支持的参数如下:
' c3 b2 h4 l6 Y- P( p6 e7 {; v
2 r3 S, z$ S4 Z; l7 |  x
  1. #define MDMA_LITTLE_ENDIANNESS_PRESERVE          ((uint32_t)0x00000000U)  
    / c4 \0 ?1 U% P. T8 a( V" t# y
  2. #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_BEX)  ; Z% I' ^" [2 G8 Y# Q
  3. #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX)
    6 I3 v: y7 l" q6 K& _# e
  4. #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_WEX)  
复制代码
9 k$ `: n$ I7 n3 A+ m  L
! P# `3 f2 ]: k# Z/ o& k" M# [, ^
MDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。- V, B" U4 _  _% i3 v& g( q1 G

7 @) C" N5 F: ~& c/ oMDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。/ ]; t4 j: O: }8 t+ o1 D

" E$ F8 |; O" ?7 C( ~' eMDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。: v% U" L" m) [/ d9 Y0 K3 K, F
6 W% a6 h' s7 N% a2 L
MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。2 R( k. f  r  M* J5 }

9 q7 ?. v' }% G( }  ^4 o  uint32_t SourceInc) \0 L9 s7 _5 n5 Q  U3 o, d0 d
MDMA源数据自增或者自减模式,具体支持的参数如下:
9 D; G, D- S+ U/ `/ Z5 h* G

  1. 2 A  P% C6 A6 Y7 w( F" O
  2. #define MDMA_SRC_INC_DISABLE      ((uint32_t)0x00000000U)                                    
    8 @5 i" w/ Y$ U  i. F- {  p
  3. #define MDMA_SRC_INC_BYTE         ((uint32_t)MDMA_CTCR_SINC_1)                                
    8 Y! `0 w: P* I, b6 ]! u
  4. #define MDMA_SRC_INC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)
    / u' n, g+ h1 |& Z; C( B/ G6 `
  5. #define MDMA_SRC_INC_WORD         ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1) ! j( I3 N# k$ m/ e3 ^1 M
  6. #define MDMA_SRC_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)  
    / Q% y+ v: }) W, r9 L8 P7 x% x( }
  7. #define MDMA_SRC_DEC_BYTE         ((uint32_t)MDMA_CTCR_SINC)                                  # k/ g7 H  H6 n# [6 Z+ a) D
  8. #define MDMA_SRC_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0)   & w; j9 m: Y" k- Y6 P" t  S  |- e7 Y
  9. #define MDMA_SRC_DEC_WORD         ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1)   8 o6 R0 n& M/ _/ U1 a) J+ O! P
  10. #define MDMA_SRC_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)   
复制代码

) {% A& s7 B+ J+ X( V5 ]  ^: J. M" a" ~# m2 D

, e9 i( X3 o/ C- y  DestinationInc& P  Z8 j! L3 F/ i$ A2 }- Q. A
MDMA目的数据自增或者自减模式,具体支持的参数如下:
' Q" L1 F) R+ y5 w$ U9 o" B. {6 C- ~
7 K- B  S4 t- c6 _9 _& Y% p
  1. #define MDMA_DEST_INC_DISABLE      ((uint32_t)0x00000000U)                                    5 }/ P! L1 |2 O: ~& W1 y4 e, ^' d  S
  2. #define MDMA_DEST_INC_BYTE         ((uint32_t)MDMA_CTCR_DINC_1)                               5 t6 K" p9 k8 u" i$ I
  3. #define MDMA_DEST_INC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
    ' z6 L1 a5 ~% F& I* V
  4. #define MDMA_DEST_INC_WORD         ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1) 6 C- {8 Q, m2 y, N% j
  5. #define MDMA_DEST_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS)   5 J$ ]* K% F' _4 a3 c" ?& B" A
  6. #define MDMA_DEST_DEC_BYTE         ((uint32_t)MDMA_CTCR_DINC)                                5 P" U+ q% U. m6 f& H
  7. #define MDMA_DEST_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)   
    : Y6 F0 W: n9 s5 w' T
  8. #define MDMA_DEST_DEC_WORD         ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)   
    & `; W% @2 L2 u
  9. #define MDMA_DEST_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)  
复制代码

3 {( e$ }3 [0 }; o# l
/ K& p. T/ E7 Z* Y, q9 S: X2 X0 D; a  j, R2 `+ q! D- z5 s
  SourceDataSize
3 K7 X1 t/ n) v& D) D; [7 R3 Z; jMDMA源数据带宽,具体支持的参数如下:
3 Z" x) h# F  N% k# m6 e7 X  B5 h+ S5 l
  1. #define MDMA_SRC_DATASIZE_BYTE        ((uint32_t)0x00000000U)        " F; U  O, U. c& j; W
  2. #define MDMA_SRC_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_SSIZE_0)     
      P6 A* ?5 b2 R
  3. #define MDMA_SRC_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_SSIZE_1)  # J, ~2 B1 I: \9 ~0 v, o
  4. #define MDMA_SRC_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_SSIZE)   
    4 `9 w5 i4 E3 p; V
复制代码
( i7 E. v9 B6 k- ~) {

1 W' S0 z; U( C! G  DestDataSize0 s) Y. y: q1 `8 A; e* c
MDMA目的数据带宽,具体支持的参数如下:& L2 J0 i7 x) g+ Y3 {

& q, p4 z  R. _8 z
  1. #define MDMA_DEST_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    7 Z- {% ]! ]0 E
  2. #define MDMA_DEST_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_DSIZE_0)   ) T! R: W: e# o5 \% \' @- f& l
  3. #define MDMA_DEST_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_DSIZE_1)  8 G- `& c9 P8 U6 Z5 l
  4. #define MDMA_DEST_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_DSIZE)     
复制代码
, E- P. v: I; K* D2 g

" _  j, `& y7 L# m4 |4 W
: e3 m: X3 c9 I2 H1 u  x  DataAlignment
4 }  o2 j# R# d0 H, W# V6 xMDMA的填充/对齐设置,具体支持的参数如下:0 u1 I1 i$ b2 u0 O4 L. f
  1. #define MDMA_DATAALIGN_PACKENABLE        (uint32_t)MDMA_CTCR_PKE)     
    ' }( w& ?; {2 T- }% i
  2. #define MDMA_DATAALIGN_RIGHT            ((uint32_t)0x00000000U)     3 `) W8 ]% @' C: K! b% ^' C
  3. #define MDMA_DATAALIGN_RIGHT_SIGNED     ((uint32_t)MDMA_CTCR_PAM_0)  
    0 `, v9 V$ j2 O; Y$ b2 f
  4. #define MDMA_DATAALIGN_LEFT             ((uint32_t)MDMA_CTCR_PAM_1)  
复制代码
! ~: v7 I5 {$ E  ?2 Q" S+ r

2 R; K" \0 a, `8 b' h2 L$ N( [0 A7 D
MDMA_DATAALIGN_PACKENABLE:9 Z8 _8 l/ X6 {; |4 n# B$ E

. H# e5 {- a* b6 n4 |% f将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。1 {" _+ ^9 @5 A/ R" [1 s5 d# e/ [0 i
: s: X+ P+ B! e, u! Y
MDMA_DATAALIGN_RIGHT
4 ]7 ?- T/ W: V$ b; m$ v# y- j3 h. G7 L# {, M. E8 R! W
右对齐,用 0 进行填充(默认值)9 g8 p% {. f: A; H. i
% l$ \  d( \) r8 m$ l, ^
MDMA_DATAALIGN_RIGHT_SIGNED5 Y6 b* @1 e4 y3 K

9 r5 |: w( i5 r0 C1 c/ m右对齐,符号扩展& P- A* ]0 @8 M$ T0 A
' K, R" \) W. Z" \7 N: R: B1 d
MDMA_DATAALIGN_LEFT
. ~1 u; u6 h% S9 Y, L# R4 Q/ b
- S7 A/ r  G* g' N$ X左对齐(用 0 进行填充)3 L: P" C( S0 g  B; i% i+ {! l

# \* H, ]) m# s/ L" n8 x- B  BufferTransferLength
& \  A8 x. L8 U5 m8 k7 I6 f' Q+ ^- j单次传输长度设置,范围1-128,单位字节。6 N3 o! _3 m' f% h, g3 M
3 E% s. ~+ u( J
  SourceBurst. Q7 W5 O6 `4 O+ v
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:$ h# J3 p. D6 j+ Q3 q* S0 ?

. Z0 }- x9 N6 g( A( @
  1. #define MDMA_SOURCE_BURST_SINGLE        ((uint32_t)0x00000000U)                                      
    1 \6 `/ t. J8 A7 x) h( 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) , W$ U( T" x0 I5 M3 |
  3. #define MDMA_SOURCE_BURST_16BEATS       ((uint32_t)MDMA_CTCR_SBURST_2)                               - _8 x: l' }- n: n
  4. #define MDMA_SOURCE_BURST_32BEATS       ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2)
    9 v  ?  @8 K* m- c; l' }
  5. #define MDMA_SOURCE_BURST_64BEATS       ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2)
    5 V. F: W7 p. x. i& S3 y
  6. #define MDMA_SOURCE_BURST_128BEATS      ((uint32_t)MDMA_CTCR_SBURST)
    / j- F/ y3 l6 T' H# Q: I
复制代码

2 C: l. G7 a" r+ b! V
+ o8 Q$ Z2 b% U3 u1 S6 D; ]  DestBurst& \, F$ `! t  ^
目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下
6 x6 Y8 D! n  V; I) g8 n
  1. #define MDMA_DEST_BURST_SINGLE        ((uint32_t)0x00000000U)                                       
    & \# ?: g9 K, D8 \- s+ _0 C+ k
  2. #define MDMA_DEST_BURST_2BEATS        ((uint32_t)MDMA_CTCR_DBURST_0)                                 
    : h! x1 g9 a/ s9 l
  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)
    7 B! v# m/ X: N+ D: q$ K3 b
  4. #define MDMA_DEST_BURST_16BEATS       ((uint32_t)MDMA_CTCR_DBURST_2)                                 
    . {* [" m1 D0 q
  5. #define MDMA_DEST_BURST_32BEATS       ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)  
    9 u8 o* H2 V  b4 F
  6. #define MDMA_DEST_BURST_64BEATS       ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
    3 h+ T' P) M4 G) N+ R" ^/ u
  7. #define MDMA_DEST_BURST_128BEATS      ((uint32_t)MDMA_CTCR_DBURST)  1 K1 @8 ^; N# h/ @0 H/ U
复制代码

3 t7 \- }! E3 K9 _- |( `  SourceBlockAddressOffset! \/ X/ u3 |1 a0 n
用于设置源地址端数据偏移。' y% @; d( Z. V  W; ~! @
0 U- v6 \3 G" b. N: n
  DestBlockAddressOffset
6 B5 ^. F( l' a0 _7 s2 @: U用于设置目的地址端数据偏移。
5 h1 G) ?1 n# ~1 j' O2 S% T1 l- Y0 Y- w; {, ]! R3 Y* n' z
61.3.3 MDMA结构体句柄MDMA_HandleTypeDef
$ N# Z- Y( q& }( W6 a) PHAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:: P' b; T1 Y" |) e

2 V7 m9 l) v* ]1 [  R) P
  1. typedef struct __MDMA_HandleTypeDef3 c: Y" u2 L1 o, F! E( U
  2. {
    % e/ {; ]3 U4 U4 [
  3.   MDMA_Channel_TypeDef *Instance;                                                                                                                                                                                              . I2 |8 M7 `* ?. O- ?& J$ T
  4.   MDMA_InitTypeDef      Init;                                                              
    % N. E  s8 a, W$ D
  5.   HAL_LockTypeDef       Lock;                                                                  * _& Q" s5 S% d+ x. n
  6.   __IO HAL_MDMA_StateTypeDef  State;                                                           
    8 c# \9 Z( a- A2 N$ \1 f& ~) ^
  7.   void                  *Parent;                                                               
    2 Y( y  ^9 O0 ~& R! ]
  8.   void                  (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    ) \3 {; G3 l9 z$ Z1 p" X5 @2 b7 h) u
  9.   void                  (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     # _; f, }" a; @" A2 }- [3 d- j: b
  10.   void                  (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);      
    : q5 z) Y. C3 F7 u! z% J
  11.   void                  (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);4 u0 x! g) s: S( F1 H  C
  12.   void                  (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    . @/ a+ }$ ~5 H
  13.   void                  (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    / n( l' Y7 a" E. \4 A' R
  14.   MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;                                             2 d" T$ P3 y6 L  H3 L
  15.   MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;                                             
    ( V7 Z; T% R: ~
  16.   uint32_t LinkedListNodeCounter;                                                                                                                                                                                      5 z! k; {! D/ Q% I; S
  17.   __IO uint32_t          ErrorCode;                                                            % C3 Y4 Q% Y% s7 X$ A
  18. } MDMA_HandleTypeDef;
复制代码

4 \# ]" F, m: V$ L) K下面将这几个参数逐一做个说明。2 C% H% \" [  ^  h; ~$ c

! J& l) `+ q# A+ e9 d- b  z  MDMA_Channel_TypeDef  *Instance
0 A0 ^$ V( M; _, ~0 J" F) s这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。/ V% @- ~1 k1 U0 V9 u

% U. K# U2 [! ~  MDMA_InitTypeDef      Init
! Q" S5 I% v8 t( R% S这个参数用于MDMA的通道参数初始化,详见本章3.2小节。) k  H2 y: V! Z8 {
) i8 z# b; s$ Z" y* L
  void   *Parent
4 m# u$ Z, ?- }( J! Z+ n用于记录MDMA关联的外设。, i2 p: D2 Q: J, c* P
/ m- \$ P8 }! S$ h4 w
    void   (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);          + O( |( r- o6 A% e5 e& ?, W: }
    void   (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);    ! X& z9 Y0 X. x: B4 Z( E$ o
    void   (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     
2 `" p( O( u9 D4 H( o, t9 B    void   (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
: ^2 r3 l1 s$ l* m, L7 k' D    void   (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);          7 \# p, U+ Y9 J5 A
    void   (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);   3 Y+ h: c4 C& k5 c% t
MDMA的各种回调函数。      D3 t8 o$ l0 ~# ~8 ?( }
* L  x8 O8 X9 T3 m! l/ ^& {+ a
  MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;: n' O( G; N) b# h. l" @# v
  MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;
3 z1 J. p) ^6 z  R6 B: G' r  uint32_t LinkedListNodeCounter;. p; m1 t# [6 y. Q
用于MDMA的列表模式。% k6 s( N& N% O, V' V0 z
, [% [6 C7 v6 Y
  HAL_LockTypeDef          Lock           
* }6 K5 w1 L- `% W  __IO  HAL_DAC_STATETypeDef  State           $ H/ D1 J% N/ \% r7 N5 \) Y5 l
  __IO  uint32_t           ErrorCode      % r4 r( v4 B* p+ A$ x/ N# M. S2 b
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。
3 f* w4 V# Z- M! x& w1 i+ D
% V/ c! f! o. g3 U: B61.3.4 MDMA初始化流程总结
0 V3 W* [' j: r" z% q使用方法由HAL库提供:
8 j3 v( \. ]- c! ?) W/ f
: ^/ T7 V7 ?# }! M  第1步:基本的初始化。
# z5 W/ C, Z& O/ x6 ?3 z' H8 U, Y
# T( C. |4 k) [9 Q* d1 |) a  函数HAL_MDMA_Init配置MDMA的基本参数。
/ N# ^; E: d* Q. }$ [+ P9 R
7 `. n" b5 l$ u) H
- y) R- L  L% P  第2步:列表模式。
5 Z8 p5 i0 Z' P
0 k) M3 J* @) z如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
6 r% ]) C0 L, [5 H# |  ^4 `
8 d; h! P" n6 v* \6 `" w  ?2 g7 {. B
  第3步:查询模式。1 c9 i( t2 f0 d. n  \4 k' v. A6 H
; Z7 l  ~! b) Q
  函数HAL_MDMA_Start 启动传输。
* g# n/ V$ ^, t0 V2 Y' ?, V  函数HAL_MDMA_PollForTransfer 查询传输完成。7 F- O# s" l+ L4 t% B
  函数HAL_MDMA_Abort 终止传输。/ O. b+ y$ U; ~- X

0 k2 G# Z/ q  M
) a; W! e2 \& ^5 K4 g6 K' u  第4步:中断方式。. b- A/ l) i" w' L
5 s& e# V+ ]  ~: ?" u
函数HAL_NVIC_SetPriority设置MDMA中断优先级。. d7 d: E) j; Z5 T) n& C2 i8 M) a
函数HAL_NVIC_EnableIRQ使能中断。
9 h4 h" @5 i4 Z: z; B. Z 函数HAL_MDMA_Start_IT启动中断传输。( @0 T5 s6 s+ k, p7 [8 A
MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。$ I3 K+ ~' E  Z* B% x; V$ Y9 j. h8 R
函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)
( K5 q0 M3 _( x4 f# |
$ y# g' ^* X7 }2 |! }6 X2 _- o8 t1 Y7 ]# @% `  o2 n  P
  第5步:中断回调函数。/ p; N4 d4 j4 c7 D

5 V# p" @) ~4 ?* \函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。' u3 A1 q' l+ p. Q" J$ i
' W& B) O. s8 \$ {( {
  XferCpltCallback            : 传输完成回调。% b- a6 k2 ^/ P: @
  XferBufferCpltCallback      : buffer传输完成回调。9 V1 c0 K' \' u
  XferBlockCpltCallback       : block 传输完成回调。/ N! H4 k: q' r- w6 |& h1 {- I
  XferRepeatBlockCpltCallback : repeated block传输完成回调。
; i. H/ z& U3 o; p+ f, O# M  XferErrorCallback           : 传输错误回调。
) o2 Z: z2 f# ~9 L  XferAbortCallback          : 传输终止回调。% t! y1 |: c) `

. i( X) }7 l/ N4 m+ K; s3 [9 M- f( l0 U5 G( A4 G
61.4 源文件stm32h7xx_hal_mdma.c+ ]; s  Q4 D  D! z; I, I! h
这里把我们把如下几个常用到的函数做个说明:
3 C+ S" {/ \+ j5 m7 T* `2 C# I% V
& R/ @  }: ~) I  p3 ^  HAL_MDMA_Init
# N5 U3 V+ V& _5 x. m# N( |  l2 f  HAL_MDMA_Start_IT9 T2 X! S3 I) W% y. \
61.4.1 函数HAL_MDMA_Init
" |2 x9 M1 g; T5 F- B3 ?函数原型:
+ S+ X1 O5 h% L8 x4 Q/ a( k3 ]+ S
  1. HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
    $ V; m* O  u* @" P/ N' \3 g
  2. {1 R# r. m! H8 S+ l
  3.   uint32_t tickstart = HAL_GetTick();
    0 d( l4 v/ Y3 H# ^% T9 ]. Y5 }; Q+ g

  4. , l6 a' K( U7 G4 H* c; ?. d
  5.   /* 检测句柄是否有效 */
    % f& A+ ?% c2 u1 i7 A2 c  r
  6.   if(hmdma == NULL)
    6 X0 h) n. M1 i8 j) n; n/ J5 A
  7.   {2 N8 L% V  V( X& o3 i
  8.     return HAL_ERROR;! j! Y0 Y+ j) z* a2 t7 Q. }
  9.   }6 H0 S; R: m) j* v
  10. ( P$ E4 t: S0 j7 H$ [5 H3 W
  11.   /* 检测参数 */) G) l) E! E% E$ [; L) R
  12.   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
    2 K: t* n. N, {
  13.   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
    8 {( K* ^  Q) H" Q
  14.   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));4 @( u/ w/ _2 Q* i. B3 H7 D
  15.   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));& O. D# y  c: i3 U8 q
  16.   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
    , R" a8 r+ t2 I
  17.   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
    $ k: x+ C7 x# w7 V! X
  18.   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
    3 ~2 b% C* x3 |2 k$ J
  19.   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
    ! ?& [- }: u0 \
  20.   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
    & @. R+ ]& r* ~% c
  21.   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));$ }3 Z* e1 _) F' a
  22.   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));) y! G9 i- m' S
  23.   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));( V0 t6 `1 u& V0 s; O' q
  24.   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
    - i! O/ X! p$ J& e# X* o5 a. K
  25.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
    # `, h6 v/ a3 |$ e: j9 B" ~) ?
  26.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
    # {% q/ k4 p$ O! E

  27. ( {/ G( K  E" G: d. P

  28. 5 h. n4 A% f0 I8 U$ d+ d
  29.   /* 解锁 */" R- g2 Q2 T# F+ _6 G/ m7 p+ A
  30.   __HAL_UNLOCK(hmdma);
    7 C) ^0 t; G. }& F2 X
  31. ; J, L! w* x: z9 Z& X- P! G- X' N3 g
  32.   /* Change MDMA peripheral state */! ~/ {- E* a7 Z  o4 k
  33.   hmdma->State = HAL_MDMA_STATE_BUSY;
    $ o0 Y5 E: x5 A) l, M! Z- ]

  34. # i) L8 V0 U3 g) x" {
  35.   /* 禁止MDMA */6 H5 [5 q2 v& Z: h& y; r
  36.   __HAL_MDMA_DISABLE(hmdma);
    ! S0 v+ i) n: p0 n/ L
  37. - |5 b, {* K: q! U5 r
  38.   /* 等待禁止成功 */
    ! W3 N8 I: h* J; {$ T
  39.   while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET): E" f- [2 p% C
  40.   {
    2 c6 G* `  T  \) U- Z4 z. s$ T
  41.     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)+ L1 m0 w8 G, u2 v/ u
  42.     {
    # E& x- k. r# z- j6 v4 ]! A5 Z2 a
  43.       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;, c7 v: U' h3 S- ~4 T

  44. 8 c: E! s2 f; p! g
  45.       hmdma->State = HAL_MDMA_STATE_ERROR;
    ( x2 E8 ]+ V( I  o

  46. $ K/ y" l, H8 Y: m: @+ y
  47.       return HAL_ERROR;4 ?+ c9 L; h- l  R- @% ?
  48.     }  v! K* q) h8 ~; Q3 I% F  n6 P# |; b2 ~
  49.   }
    7 ?0 t+ ]- a, R; G
  50. / F) R. e, s. k7 R- ?
  51.   /* 初始化 MDMA  */
    / z8 Z$ B  S+ b( v5 |1 |
  52.   MDMA_Init(hmdma);# p3 Z7 G% K8 V4 p
  53. 9 z4 v! m1 C$ T6 _8 g  O2 k' J
  54.   /* 复位列表模式相关设置 */
    4 ^+ [0 K( M- o$ u3 \" E
  55.   hmdma->FirstLinkedListNodeAddress  = 0;
    1 P; `1 y+ _  W, M
  56.   hmdma->LastLinkedListNodeAddress   = 0;
    , W5 `& e2 N3 Q4 [
  57.   hmdma->LinkedListNodeCounter  = 0;  / B9 x3 _% s( l4 |* H
  58. ; Z! ?) G& g( p, A  b5 G! F. D( {
  59.   /* 设置无错误 */
    * f. P' k& x. P/ d& U7 R6 W
  60.   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
    0 S: h$ @; n( K+ ~7 e% ]

  61. ) z* h  r8 S, r$ s
  62.   /* 设置就绪 */
      V& u$ ?9 s9 M
  63.   hmdma->State = HAL_MDMA_STATE_READY;
    & t- q$ K3 {, a/ r, [1 }  ^

  64. 4 e& a+ f5 \/ I
  65.   return HAL_OK;* w9 l1 ]) }' ?
  66. }
复制代码
! h& _# U) V3 ?* }/ W* a
$ q& Z2 _) V0 I4 O4 g0 c
9 z* E7 K: x8 w# H4 q+ e
函数描述:
% ^; H, q3 p# \2 u% w2 r5 B: h5 f  X: Y
此函数用于初始化MDMA。
" e$ a& h, f5 h0 p' a6 J' b
& a* f5 w5 h1 A; d) y函数参数:$ `$ n- o4 j3 ]$ k

/ c8 K5 d/ V% P7 k0 B+ l; J. W  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
& a+ X' ]! c/ T2 J( E& p3 O  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。, S, B6 R8 q# K4 E$ H
使用举例:
" a) R# ?3 ^6 h( a1 d1 P& d
' u; t& b* M- T
  1. MDMA_HandleTypeDef  MDMA_Handle;) D" c# y% W  ]8 i

  2. ' c7 }# N* J1 J7 V0 X
  3. __HAL_RCC_MDMA_CLK_ENABLE();  
    : T- K  {8 r5 P$ t3 H

  4. - ^2 H. ?+ u1 j  K& X- X+ I
  5. MDMA_Handle.Instance = MDMA_Channel0;  , t0 z" y1 `% F; J3 V( [1 ]

  6. : {. o3 D7 E8 e4 s* g2 o1 x, {
  7. MDMA_Handle.Init.Request              = MDMA_REQUEST_SW;         /* 软件触发 */
    ! _3 ~7 `" I* S) C* I/ W. t2 w9 S) K
  8. MDMA_Handle.Init.TransferTriggerMode  = MDMA_BLOCK_TRANSFER;     /* 块传输 */
    3 @2 v, |6 C7 Y( H% I( p
  9. MDMA_Handle.Init.Priority             = MDMA_PRIORITY_HIGH;      /* 优先级高*/2 E1 E% X  x2 O
  10. MDMA_Handle.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */
    0 h% t+ _/ K% }0 ^2 g: ^
  11. MDMA_Handle.Init.SourceInc            = MDMA_SRC_INC_DOUBLEWORD;         /* 源地址自增,双字,即8字节 */3 n: K0 ?9 v* o
  12. MDMA_Handle.Init.DestinationInc       = MDMA_DEST_INC_DOUBLEWORD;        /* 目的地址自增,双字,即8字节 */# N4 D* f/ H; O
  13. MDMA_Handle.Init.SourceDataSize       = MDMA_SRC_DATASIZE_DOUBLEWORD;    /* 源地址数据宽度双字,即8字节 */
    ; c8 @, L6 F, w! r+ h9 v
  14. MDMA_Handle.Init.DestDataSize         = MDMA_DEST_DATASIZE_DOUBLEWORD;   /* 目的地址数据宽度双字,即8字节 */& e" G: n% x+ W6 Q6 D+ s  f) V( a
  15. MDMA_Handle.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;       /* 小端,右对齐 */                    
      s+ H: M2 l; L
  16. MDMA_Handle.Init.SourceBurst          = MDMA_SOURCE_BURST_16BEATS;      /* 源数据突发传输 */
    4 ?: X* x4 M% |; s* l/ c0 N
  17. MDMA_Handle.Init.DestBurst            = MDMA_DEST_BURST_16BEATS;        /* 目的数据突发传输 */6 G8 |3 J# U! L7 B% S
  18. / u; G/ V# ?0 T8 K2 |+ [2 U7 y" q
  19. MDMA_Handle.Init.BufferTransferLength = 128;    /* 每次传输128个字节 */
    ) g9 a6 [: E7 i7 V5 @5 a" s
  20. $ S) w4 J3 \9 g# l' a
  21. MDMA_Handle.Init.SourceBlockAddressOffset  = 0; /* 用于block传输,地址偏移0 */- N( U- E% u5 }  K$ u2 W
  22. MDMA_Handle.Init.DestBlockAddressOffset    = 0; /* 用于block传输,地址偏移0 */% p$ K* C; u% E* w8 j% e" l+ g) s

  23. ( r" z/ {" a1 b+ U
  24. /* 初始化MDMA */
    $ M! X6 T( O8 C5 p$ ]- I" k
  25. if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)
    # Q5 M% |  C. P3 E  {
  26. {
    ' q+ c6 U5 O* S% i8 p5 y
  27.      Error_Handler(__FILE__, __LINE__);  a- R) V6 N, Q& y9 j
  28. }
    ( z6 `  x' k4 O/ t! Y' U
  29. " |( b/ v) U/ K- q7 x+ `
复制代码
8 C; N6 L1 p! \
61.4.2 函数HAL_MDMA_Start_IT) ]7 x7 k; K+ B- A
函数原型:
7 F* C3 h+ p: [; t3 ~* b$ P0 o9 W1 A
% H  J# B$ \; Z- ]( d: D4 e
  1. HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)1 H3 e' S* y' ]5 i, |  H
  2. {  ^: Q3 c. c0 c  V4 D& d
  3.   /* 检测参数 */: L  Q" H5 F- q- [' f4 K
  4.   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
    $ u9 a5 \6 d3 T8 Z& e  K& M. O
  5.   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); 4 |  T- J* [# q, q; _* }
  6. , M5 w% w4 }+ Y$ F# V: h7 w
  7.   /* 检测句柄是否有效 */1 v& U' ?3 j7 R' H# V- V8 y' E
  8.   if(hmdma == NULL)/ A  T- M2 N3 y" W. S: D
  9.   {
    . N# Y! L6 M8 O
  10.     return HAL_ERROR;5 c6 N( U5 z4 a1 q  \/ y
  11.   }& [( C: P; y) i
  12. 4 x: [6 o8 \3 H  i8 O" w: Q) }
  13.   /* 上锁 */6 L) {. ]8 d" I' c
  14.   __HAL_LOCK(hmdma);
    * F% s$ r9 N3 L

  15. ; L' J1 s, P4 _0 z
  16.   if(HAL_MDMA_STATE_READY == hmdma->State)) V2 x  q* a3 H0 s( g) v
  17.   {
    / P7 Y1 w% ^; Y
  18.     hmdma->State = HAL_MDMA_STATE_BUSY;, t5 k6 P4 P3 o6 q, P) m% s, I

  19. % e! \  }: u3 N/ g
  20.     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;     ) ~/ C5 q$ n9 Z

  21. - Q: X" `5 L& E9 C* T! z
  22.     __HAL_MDMA_DISABLE(hmdma);5 c3 `5 K- Z% l

  23. 5 U, C' w  [4 k! |. w3 X! Y9 p  @
  24.     /* 配置MDMA */
    ' C+ _: W" Y5 D# q
  25.     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
    * ]  F) ?/ e0 V4 J( s

  26. $ m* k4 W1 m9 h4 N2 b1 t; P  J4 F
  27.     /* 使能传输错误和传输完成中断 */
    2 y9 p6 X* `7 R4 O4 J
  28.     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
    + Z" d4 l- y" \7 |; k# I; w
  29. 1 f2 ^7 i5 `! V! u. K$ m7 f
  30.     if(hmdma->XferBlockCpltCallback != NULL)7 V1 C% C" w  [0 L, f2 ^  D7 m6 t
  31.     {5 d8 R! G0 _6 z8 d7 [& i" _
  32.       /* 使能块传输完成中断 */: ~' L5 ^. T5 c+ \+ `( d. C  J
  33.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);    ; e2 ]: G  D8 \- J
  34.     }/ G% a4 C# [: ^/ Q
  35. # f- O1 v2 Q; q, w$ n
  36.     if(hmdma->XferRepeatBlockCpltCallback != NULL)- h- A  Y- l0 W2 r& b; m
  37.     {
    + r- g- K" H1 `* |* o; U
  38.       /* 使能多块传输完成中断 */      
    " J+ D9 [! L3 }2 J
  39.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);    0 `# Z8 w7 E9 ]6 \: Y
  40.     }  
    1 z3 M# e) c: b/ X% C
  41. 7 Y& ^- p" a' l+ X; @
  42.     if(hmdma->XferBufferCpltCallback != NULL)
    ; w* ~5 x1 J0 T' B
  43.     {
    2 X3 A  K9 k0 N, s! q3 T
  44.       /* 使能传输完成中断 */6 W7 Q5 ^5 ?1 D$ M! t
  45.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);1 T, {& }' C/ A3 K9 Y
  46.     }2 e9 l0 O: z( W: R& b& F
  47. ! T/ a" ]8 B8 `: T. }, w
  48.     /* 使能外设 */
    7 B' R& g: `9 |" K5 a  @
  49.     __HAL_MDMA_ENABLE(hmdma);$ M% z/ s3 z* E# f

  50. 1 c. W, i5 _& T- }3 }% E
  51.     if(hmdma->Init.Request == MDMA_REQUEST_SW)
    : f* d$ k  a' y& G1 F
  52.     {) |3 R' b- D6 U: I. J
  53.       /* 使能软件请求 */' n1 h+ \3 R# j. ^
  54.       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
    / B0 b# m! Y9 n* ^' v: g" p
  55.     }  4 O; f. `8 l2 m- Y
  56.   }
    $ b4 j$ y) r! Y2 @* D) r
  57.   else0 E, q8 w) Z, A
  58.   {
    + y8 c. r$ c. b  k
  59.     /* 解锁 */
    ( Q+ @1 C3 m& ~0 C, ^4 ]+ N6 N
  60.     __HAL_UNLOCK(hmdma);
    : d9 z% m* {- S+ t) \" I
  61. ) n1 |" Z, O1 V% a+ c
  62.     /* 返回忙 */4 p7 C7 ~0 r0 ?8 M, K, `' a, |
  63.     return HAL_BUSY;4 s; `* l$ d# J( c) E
  64.   }# a  U! y! {2 G* d1 C7 J9 z" O9 }
  65. % T: L& g0 L; E( v" F0 ]' ^
  66.   return HAL_OK;; h0 _: z! Q  c$ k  M: h1 w
  67. }
复制代码

& y7 k% A+ ~5 J6 U' ?' L. W8 k) T$ J$ u. y) F9 P5 G! D

1 |& L5 i1 c4 O: L2 g函数描述:9 Q- r( O1 O. H  @% U1 G
5 W3 N. V7 j! K* g7 A; a# k, N$ _2 K
此函数主要用于配置MDMA的中断方式传输。% j- g, o2 J7 W0 \5 p9 T

( i, ^0 g" O  R* N9 G函数参数:7 l, ]+ e) A# U

; m$ Z" X5 E+ B. `  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
" ?% k& b2 w, {8 G; j. o  第2个参数是源缓冲地址。
2 M5 {$ O* D1 f  第3个参数是目的地址。
* ^: ~- H; L# J+ N" i: M$ \  第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。8 T3 i+ Q+ o6 {3 ^0 }) `& t
  第5个参数是传输的块数,范围不可以超过4095块。* }1 q. P. _3 a- l/ N7 O2 o4 i
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
/ {, `& X& M) R* A使用举例:
. ?$ G: B' W2 N. ^/ v2 d  s) e/ K7 w9 h/ X4 ^6 Z, i
  1. /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 */
    0 }& P: w- R5 C, F4 n" p+ A
  2. HAL_MDMA_Start_IT(&MDMA_Handle, 8 p; ^: ~* U# B1 l
  3.                   (uint32_t)0x24000000,
    0 Z3 g. [. _3 c# m& ^  U
  4.                   (uint32_t)(0x24000000 + 64*1024),
    ) ]! _% t( w8 D) a7 J' G+ I
  5.                   64*1024, 4 f7 `  A" t4 j2 d
  6.                   1);5 u, ^/ j: v9 f: T' @0 J! E
复制代码
; Q1 n# z" [3 ]

  \1 R- \" J2 [; T61.5 总结
0 P5 h9 y( a1 x, Z2 A) n本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。- a3 B* W/ D: s+ u
1 \! _/ \; E% i3 U0 s0 N

* Z! w9 h& X4 r. f
收藏 1 评论0 发布时间:2021-11-1 08:00

举报

0个回答

所属标签

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