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
* |# _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
- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U)
. _1 z) P( B5 f M4 l$ v - #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U) . m! w7 l1 b* |$ ~6 ]; Y1 ^5 d
- #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U) " \( j& e- Y/ t- h
- #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U)
* O$ m9 b9 j4 {: q' g- Z - #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)
* p: M, c5 y& s - #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U)
( Y2 W3 G. @( b3 \ L$ G. z# z W" y - #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
" M7 E0 o$ D7 D - #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U) 2 o5 m3 ^# |" |! \7 Q9 |
- #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U) 5 D" M% D6 P7 [
- #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
1 a' D( E c$ ]1 j4 _1 P - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU)
5 U3 C+ P/ F z& {0 J& H7 w - #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU) ! J( E0 \9 J l
- #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
+ u& h& n, [ B/ N, [ - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU)
0 v: i# G) c" j5 d; s - #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU) # z" I3 O# m5 r8 S$ G* x" L
- #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU)
! `4 _2 {' I/ H+ ~ m- X: e* V- o - #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U)
% l3 Z" @+ Y" a! V, C, Z) X+ Q% q - #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U)
1 P- n/ f0 i8 r4 b# T! }$ M, d - #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U) ( ^, \! S9 t/ o+ P$ e$ U
- #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U) . S n1 [! d# G6 w' @1 D) P
- #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U)
" ~9 G" d9 X1 Q. `' I) f - #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U) 1 } d6 z. i# l7 U1 r G& |& v5 H
- #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U)
6 H. P% W6 S* s - #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U)
) x% `5 u/ h0 o - #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U)
* z+ h, P9 I2 e; B, Y - #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U)
0 Y: K' S& }- L% A - #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU)- \* L$ j" C* v: X. q3 E, w [
- ; M- `1 _: k6 I6 b/ Z- f
- #if defined(DSI)4 a& m2 N* u' G/ |
- #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU) , J' Q( U4 \& ^; t+ E
- #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU) $ g' [* }* M6 I4 e4 Q
- #endif /* DSI */
( T9 M8 d: V; j! ~2 [7 s. W/ h - ' t9 Y; z5 g# J2 N. H
- #define MDMA_REQUEST_SDMMC1_ED_DATA ((uint32_t)0x0000001DU)
/ }3 G- a: I5 R `1 o4 y5 X( y7 d - ) V! _ [& z7 ~) B d; C6 |
- #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
- typedef struct
7 K7 G. n5 \2 N3 T1 [3 D) |) j% }+ w - {+ S. `$ W% p5 c2 o7 i) w
- __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */; W; ^, ~5 A" N! x! M- U
- __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */
1 ^ e8 ?3 F3 y5 d - __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 *// a$ s) o" Y0 P
- __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ 0 p8 `9 k6 M; J2 R- o f2 k
- __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */
7 S% c. c1 I9 m) y! n - __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */* G3 u& z/ m' {; Q2 i) w6 h3 K
- __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */
. b5 Q1 h& i6 }& Y K/ S - __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */4 N3 k" g" A& l
- __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */
/ [4 Q' |2 o0 S - __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */* w- Y. F1 C9 ~0 z9 {8 Y8 m
- __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */
0 X B% {' J9 e3 N$ T- @9 x - uint32_t RESERVED0; /*!< Reserved, 0x68 */
! V( R* j W& t: W$ d3 I) } - __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */5 I: l# _; O$ V9 X4 J1 \/ ]
- __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */0 w- ~' @2 m% z: l8 E
- }MDMA_Channel_TypeDef;1 z" y6 B/ o( d/ w* u+ m
2 I' i) E2 N% G- typedef struct' d4 r6 I% ?$ e* G3 E% h
- {
. W# h& {- n# K$ @ - __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */+ k0 V0 z. d6 i8 o/ s
- }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
- #define __O volatile /*!< Defines 'write only' permissions */0 i1 R9 s/ w( K) S2 X
- #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! ^- _
- #define PERIPH_BASE ((uint32_t)0x40000000)
# C' s" o: o+ K( y2 b) N - #define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000)2 D1 I; y$ D V5 l9 P* h2 B; g6 J
- #define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000)
& \- R9 K- g( o
, R. f* s y* R/ o( ~- #define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040)8 s( z& M' a `& b& L8 g3 U8 F8 j
- #define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080)
5 H9 }: q. c3 X" K - #define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0)
) u$ U9 ~' G) \% l - #define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100). Y% ?- d% ?: n+ n
- #define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140)8 r' L8 p* b# X2 |$ n. h5 k
- #define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180)
4 C8 o" K M3 o% U+ C; T3 { - #define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0)+ C9 ^' M) [# {3 b7 K- ^ `
- #define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200). P0 C' [/ t6 W1 _" E$ q0 @9 X
- #define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240)
& u T# O3 r7 z1 r$ m/ Y% i - #define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280)* c8 N! ?7 ^2 m" Q& Z: q' E
- #define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0)
, f9 j$ m/ J/ F8 U& K, i' ?6 [ - #define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300)' l( w5 D6 D% Y# A
- #define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340)& B. n+ N1 T2 d# y, Q2 g# G
- #define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380)- Z# a" l5 y7 x3 `" [7 c; T/ u
- #define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0)
& ^- b/ Y1 h. B - #define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400)( ]- I7 T* q4 f# a. N
- + q! I' m3 X+ }& c, e
- #define MDMA ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000
2 ]) H: }+ e6 }& A4 D$ D - #define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)- p/ X; {2 Q S: m2 K" c: z
- #define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)6 d1 N" G9 f1 ]1 d5 V% _/ ?
- #define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)/ A4 C/ P2 c4 \3 G t; [
- #define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
1 B/ V- Y9 b) \' E# |0 @ } - #define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)
3 T/ G" y( J s u1 c8 A - #define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
' f3 P+ ^: \/ f - #define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)/ q: {' \/ T) l0 E- P
- #define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
" K) x6 r- }2 [8 `2 b( ~( R - #define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)
$ g' D) w- ]- k# ?$ |4 y - #define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE). Y) W- C& g: l: L3 |6 O
- #define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)! r0 U5 [, E" b3 a4 |, K
- #define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE): E; ^% k( m0 V$ z3 `6 C
- #define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)0 j' z4 x1 ^/ x' l
- #define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
$ X( l: }$ N9 u2 y# M# o* v - #define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)* p( `; T; V1 J6 E1 L0 w
- #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- typedef struct9 H f J+ ~: R0 j4 s
- {& M9 G4 I1 W' l( f& s% v0 n4 E& I
- uint32_t Request;
% U0 w% i8 p1 W - uint32_t TransferTriggerMode; : C& F+ D7 D$ I, l9 Y! v
- uint32_t Priority;
6 _" i4 q, }( ?) \! D0 u - uint32_t Endianness;
$ i2 W! h% Q; N+ U% I* \4 e" A - uint32_t SourceInc; 4 T" h$ Q5 Y7 W
- uint32_t DestinationInc;
/ \7 O4 ~/ D, b. I5 A0 s W - uint32_t SourceDataSize;
$ K/ \; f# Y+ H/ m5 C2 c% z - uint32_t DestDataSize; $ b9 {2 U& d& y) n, U3 J
- uint32_t DataAlignment; : \+ Q0 ?2 k8 G& o. W! f2 H; x% e
- uint32_t BufferTransferLength;
* K% g3 W3 F) Y ^$ P - uint32_t SourceBurst;
1 p g1 V: A& l: m: ] - uint32_t DestBurst; - d' _* @* O4 }& Y. K
- int32_t SourceBlockAddressOffset;
7 O5 }. r7 ]: U& } - int32_t DestBlockAddressOffset;
& ^$ [. n- M) u, {( n) R* ]9 P - }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# @- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U) $ P ]! ~9 F' N+ o2 t+ l1 K" S
- #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U)
$ k; w1 q' U2 E& _9 _; x - #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U)
% |9 i, V* O+ o9 `) S - #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U)
0 y0 H" D1 X( F: V2 q - #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)
5 y2 p2 i1 d* _& a) H2 n# [# o, g - #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U)
$ l2 j+ F' M7 d+ ]7 M - #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
+ u+ s/ o* [5 v2 H; X3 i. | - #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U)
, ?7 ]6 W: v8 a7 N$ R - #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U) " C& p3 i- F8 A& R; Y
- #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
. k! M; R# l G6 T# E& `6 | - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU) 9 O, J2 j2 k& z2 J" r0 g2 L
- #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU)$ n- m1 D! t/ X; |) [$ N7 S! {
- #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
/ H+ e$ ?2 Z4 t* n0 U* a6 m9 _# V1 d - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU) 8 f7 N) x% ?4 k0 H
- #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU) # O/ V, O& C9 y) X3 n. A
- #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU) % z: L0 r+ O, K, k$ H
- #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U) ( |/ M6 n" [3 b+ K) l& Z
- #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U)
" N1 k1 ]4 ?3 S - #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U) ; x! G5 c* @# m% I
- #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U) 2 ?5 X& k# t9 b5 L' v
- #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U)
4 ]. v3 B1 S+ q3 S - #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U)
4 o' X8 ]" R- ^" c9 U- v/ K - #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U)
m: k( M4 k/ c( c - #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) 4 L, Z6 d K3 T" F6 k1 y
- #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U) 0 S& K$ Z& }: n' R3 Z
- #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U)
: N x7 M% b4 t" l+ ?3 v - #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU) $ G- @" H" b3 f
: N; u1 c% _" ~' E- #if defined(DSI)2 Q* H5 x6 F7 S* j" p; n# G
- #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU)
4 L) r7 r0 T/ n* S# F - #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU)
& I% {' h9 z: O5 t& x9 ^8 d, e - #endif /* DSI */4 i- R& X6 F9 Y8 [5 x8 D! y! N
! c% R. m9 R9 N( @- #define MDMA_REQUEST_SDMMC1_END_DATA ((uint32_t)0x0000001DU)
, A9 `% @: O) w2 c' q; ~- { - #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
- #define MDMA_BUFFER_TRANSFER ((uint32_t)0x00000000U) /* 缓冲传输 */2 `3 e+ l9 P* ?( ?8 A1 \$ z) A
- #define MDMA_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */- p4 c! J+ e9 K* \
- #define MDMA_REPEAT_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
0 j9 z" E6 R) U& n - #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- #define MDMA_PRIORITY_LOW ((uint32_t)0x00000000U) 7 ]( a) O4 M' F% e/ z
- #define MDMA_PRIORITY_MEDIUM ((uint32_t)MDMA_CCR_PL_0) ! N* J) J; ~7 l( ^" e. P3 q
- #define MDMA_PRIORITY_HIGH ((uint32_t)MDMA_CCR_PL_1)
6 f0 f8 p- v# ?- g - #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
- #define MDMA_LITTLE_ENDIANNESS_PRESERVE ((uint32_t)0x00000000U)
0 Y5 J, M3 o! ]! a( K2 ^% N - #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_BEX) 6 k& m+ |, `! O; B2 X
- #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX)
5 n4 h) T% y$ Y# @ - #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
' J2 E s# b( s! f- #define MDMA_SRC_INC_DISABLE ((uint32_t)0x00000000U)
3 Y4 O" v8 j; v) M# X/ d - #define MDMA_SRC_INC_BYTE ((uint32_t)MDMA_CTCR_SINC_1) 5 t1 I& C b& A+ w
- #define MDMA_SRC_INC_HALFWORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)% L# J6 a* d1 w8 L
- #define MDMA_SRC_INC_WORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1) 3 I$ |* o' h% }, l% Y
- #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 - #define MDMA_SRC_DEC_BYTE ((uint32_t)MDMA_CTCR_SINC)
, Y4 t$ Z; P3 R3 M5 ?1 v - #define MDMA_SRC_DEC_HALFWORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0) # h& S2 L! |/ @" t7 X
- #define MDMA_SRC_DEC_WORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1) M; ?7 F; I3 K( B6 {! @# X
- #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& ~
- #define MDMA_DEST_INC_DISABLE ((uint32_t)0x00000000U) 1 P5 f1 Q9 L. ]' N2 R3 A
- #define MDMA_DEST_INC_BYTE ((uint32_t)MDMA_CTCR_DINC_1)
7 [, o! T0 ]* v/ d1 R; w - #define MDMA_DEST_INC_HALFWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
; O' t x* M6 v" s. x - #define MDMA_DEST_INC_WORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1)
# J9 E8 ^; S2 l5 \! S - #define MDMA_DEST_INC_DOUBLEWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS)
" w' D' ~8 G# Q j" W8 b3 \ - #define MDMA_DEST_DEC_BYTE ((uint32_t)MDMA_CTCR_DINC) ; g+ ~( W! y! W% ~% h4 n( ?
- #define MDMA_DEST_DEC_HALFWORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)
2 u! ]9 ?" [, O, R - #define MDMA_DEST_DEC_WORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1) + Q, I# p# c' v: r7 O+ ?
- #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- #define MDMA_SRC_DATASIZE_BYTE ((uint32_t)0x00000000U)
0 o$ s& J! X r3 A4 y5 ] - #define MDMA_SRC_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_SSIZE_0) : u3 u0 a" L9 S6 z+ H
- #define MDMA_SRC_DATASIZE_WORD ((uint32_t)MDMA_CTCR_SSIZE_1)
( J5 |$ f& z2 @! {( V - #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
- #define MDMA_DEST_DATASIZE_BYTE ((uint32_t)0x00000000U)
0 t, _5 s0 @5 s9 N: N2 Q! f - #define MDMA_DEST_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_DSIZE_0) : t& j6 {# p/ u' D+ e5 i# Z
- #define MDMA_DEST_DATASIZE_WORD ((uint32_t)MDMA_CTCR_DSIZE_1)
2 j7 j; E0 u; X( ~2 I! I - #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 }- #define MDMA_DATAALIGN_PACKENABLE (uint32_t)MDMA_CTCR_PKE) ' f+ b" X& \. E8 y1 ~# @/ |
- #define MDMA_DATAALIGN_RIGHT ((uint32_t)0x00000000U) " ~) e. r$ p, C; I) x
- #define MDMA_DATAALIGN_RIGHT_SIGNED ((uint32_t)MDMA_CTCR_PAM_0)
8 I! r9 X2 f8 \$ c6 P- H* \ - #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
- #define MDMA_SOURCE_BURST_SINGLE ((uint32_t)0x00000000U)
6 t; b1 r( |9 R7 U; R% ~ ^4 A - #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
- #define MDMA_SOURCE_BURST_16BEATS ((uint32_t)MDMA_CTCR_SBURST_2)
- n5 ~6 Y2 H7 i6 V - #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 - #define MDMA_SOURCE_BURST_64BEATS ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2)
8 p" ?6 Q, W: ~! r9 A - #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( ~
- #define MDMA_DEST_BURST_SINGLE ((uint32_t)0x00000000U) 4 @$ `" W/ L0 I* [) k/ r( m
- #define MDMA_DEST_BURST_2BEATS ((uint32_t)MDMA_CTCR_DBURST_0)
% h: O/ T T8 o, ~# T' O - #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
- #define MDMA_DEST_BURST_16BEATS ((uint32_t)MDMA_CTCR_DBURST_2)
' ~& Q4 S1 V( h - #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
- #define MDMA_DEST_BURST_64BEATS ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
- K0 \. w6 p' ]# ?3 v# G% T - #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- typedef struct __MDMA_HandleTypeDef
t* O. R0 \9 r2 @$ s$ Q - {
+ C C" J' w2 l# ~( a - MDMA_Channel_TypeDef *Instance; & S+ r" G$ X& ?; B$ V# V; Q
- MDMA_InitTypeDef Init; / z X/ u) x) R: W
- HAL_LockTypeDef Lock;
+ C. \6 b) m. B. W( l( E! C8 P - __IO HAL_MDMA_StateTypeDef State; 7 l. ?) i5 ~* z V$ o8 B
- void *Parent;
. ~- s2 V) J/ O" N7 Q `1 h" [. | - void (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
. Q* |9 P) d X; ]9 M, C - void (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
! f1 @4 y( d8 {" g9 ~ - void (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
6 D; m, P) j& k" ~* ~4 Q# K' y {& O( ? - void (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
6 n% j6 U" w' M - void (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);
4 a$ C- X. V# U# l8 i( j& [7 I - void (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);
5 i. ~: A8 b3 w/ D2 O - MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress; 5 W) i) {) }8 H/ T
- MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress; * M; R9 O3 G+ D, S4 E, |8 ^$ Q8 |
- uint32_t LinkedListNodeCounter; 6 x( A" Z8 `3 d& [
- __IO uint32_t ErrorCode; : H# Z; W8 {& [( k
- } 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
- HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma), `7 s% g7 ?9 m; D1 {9 { T4 o
- {
% S P% \/ P( s - uint32_t tickstart = HAL_GetTick();8 d5 E! w; C) N8 H, O+ h
- / Q3 l" O! S; G( e+ t
- /* 检测句柄是否有效 */
$ C. ]* A& O8 `" W0 L& Y - if(hmdma == NULL)$ l* ? ~6 [9 Y. E N/ Y0 t) k
- {
4 j* O4 M# e* E/ q2 | \1 ~' g: m t - return HAL_ERROR;
* y* J7 U) a$ g6 @, d- F8 R! l! k- w - }
1 a& C) w* ?$ G* K - " s0 W' W: Q# P3 a$ X2 F
- /* 检测参数 */2 Y6 C; b9 t9 ?% P
- assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
) X! [" Z# g; m4 \1 S - assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));7 _+ f' k" o+ Y6 R0 U. A
- assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));" g& H6 r. `3 g+ X% p7 i
- assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));) ^1 D: e( S3 O" ~' \
- assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
8 M( a# k" K( ^- p. m - assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));; T) l3 ]/ h0 ?4 ?
- assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
! u/ l' i* U2 E. H* ^! T - assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
. \1 Y0 Y" H/ Z( \2 P, o- K - assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
/ e5 }' ], q- W' ], _ - assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
# U' M: a/ k" n: h+ D% Y - assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
3 Y$ R9 {4 E# W/ V9 c' |" O - assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));" g6 j' M" ?+ Y9 x6 v9 q$ T5 ~
- assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));5 A0 e- U" O: |& h
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
" X0 n% _; f6 a" ? - assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
9 _- a" L* X. t2 j& R2 c
; W4 p1 a0 M& P% K4 X: L
) W: \ j3 l9 i0 M! ?3 D/ W( v: @- /* 解锁 */
' x- S& g4 c- d7 {, P - __HAL_UNLOCK(hmdma);# U/ u- L, D8 Z1 g
9 w+ [) |4 n% C/ M: `- /* Change MDMA peripheral state */" a2 M1 l: o& q) }5 N
- hmdma->State = HAL_MDMA_STATE_BUSY;* w, B, S6 L: B5 |% M; I
4 o/ L# o( [: z6 X3 n( W5 f! c$ Q- /* 禁止MDMA */0 i, P! ]+ k: m) O" H
- __HAL_MDMA_DISABLE(hmdma);
! V& o2 N. S4 |! i2 P! @& v& M9 r8 h - 0 i0 [* q8 n. |$ n# w( U
- /* 等待禁止成功 */* f! @, m5 l8 I4 F
- while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET)
5 E( r |! L0 c* I2 h. H - {7 b: s. }8 L0 k
- if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)1 m4 r5 |9 o. J# A/ Y
- {
8 w9 t. c/ [- N3 p- S; x. D - hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
+ E# w( {' g8 Y# \7 Q! J& I4 d8 j! } - * T9 F" @/ V' n0 y+ r( L" ?
- hmdma->State = HAL_MDMA_STATE_ERROR;& @. @5 }* {/ V- }
- # v0 c7 t& ^ `* [& c
- return HAL_ERROR;5 c- I' v* e1 @% i* w
- }
' k8 }8 D& |1 A. A% K+ D+ W7 L6 |- v - }, k" g. ~# {2 x0 i9 D/ l- u" Q$ l
2 _% H3 W4 T9 x8 u( m7 e- /* 初始化 MDMA */
0 o( C0 T9 R% p( O% V7 V) w1 i. {8 G - MDMA_Init(hmdma); \! A$ R8 |) a) b
- ' q1 o( t: l9 E3 O1 H5 P
- /* 复位列表模式相关设置 */$ c1 G; \, q0 A
- hmdma->FirstLinkedListNodeAddress = 0;
; N) h2 M& ~4 O: x - hmdma->LastLinkedListNodeAddress = 0; + K3 v, E) p, Y7 J4 d
- hmdma->LinkedListNodeCounter = 0;
# W1 N. N4 J+ H( O
) B) @& W0 r* O- /* 设置无错误 */! G2 J4 s) M0 j. _& i' n
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1 U/ | y- n* T
b. T2 m3 B! P* E- /* 设置就绪 */4 `9 |8 Y+ ^. N4 ^
- hmdma->State = HAL_MDMA_STATE_READY;9 R5 A% v w9 X0 D/ B# m9 v$ u
' N9 h+ Y( H. G/ l, S- return HAL_OK;
( z! ^) O4 s* [* Z! @7 g1 y - }
复制代码
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
- MDMA_HandleTypeDef MDMA_Handle;
$ i' o0 F% \1 R. B3 b( O - 8 L) j8 v9 e0 F$ ^4 r+ u
- __HAL_RCC_MDMA_CLK_ENABLE(); 1 n' L( ] A4 b3 H$ r
- # e1 z* N7 L1 z
- MDMA_Handle.Instance = MDMA_Channel0;
/ q0 ^1 x6 q& X
3 k# | ?/ F9 V4 _9 ]+ h- MDMA_Handle.Init.Request = MDMA_REQUEST_SW; /* 软件触发 */
" q# Z( _. r; Y- n7 e - MDMA_Handle.Init.TransferTriggerMode = MDMA_BLOCK_TRANSFER; /* 块传输 */: o( [+ K' e5 J8 C( c, g3 w
- MDMA_Handle.Init.Priority = MDMA_PRIORITY_HIGH; /* 优先级高*/
8 w7 N$ @6 N! X9 u' M: y - MDMA_Handle.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */; c1 {+ F8 S5 ]% O. l
- MDMA_Handle.Init.SourceInc = MDMA_SRC_INC_DOUBLEWORD; /* 源地址自增,双字,即8字节 */
% ~$ _' R- { v: z8 V& j - MDMA_Handle.Init.DestinationInc = MDMA_DEST_INC_DOUBLEWORD; /* 目的地址自增,双字,即8字节 */
+ f4 y& W6 Q: F' O, J8 e! H - MDMA_Handle.Init.SourceDataSize = MDMA_SRC_DATASIZE_DOUBLEWORD; /* 源地址数据宽度双字,即8字节 */& U( }; I* c8 e Q
- MDMA_Handle.Init.DestDataSize = MDMA_DEST_DATASIZE_DOUBLEWORD; /* 目的地址数据宽度双字,即8字节 */1 O: R; v$ a9 K5 v I
- MDMA_Handle.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; /* 小端,右对齐 */ - E( I% }3 W$ y! k
- MDMA_Handle.Init.SourceBurst = MDMA_SOURCE_BURST_16BEATS; /* 源数据突发传输 */- _/ M2 M9 w+ p. U6 r% u
- MDMA_Handle.Init.DestBurst = MDMA_DEST_BURST_16BEATS; /* 目的数据突发传输 */: i" g& ~9 @3 i; e9 S t! s0 R6 I
; ^+ @* {) d5 N8 B- MDMA_Handle.Init.BufferTransferLength = 128; /* 每次传输128个字节 */6 L9 f- ^- K! E! j: V, S. C4 [
- w- n# \, Q+ E8 i1 a- MDMA_Handle.Init.SourceBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */
% G n; C1 x) j, L7 }; V6 f - MDMA_Handle.Init.DestBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */
, ]$ o" h+ o- O/ x" ?% z, Z: q7 f - $ J# p! G* d3 k
- /* 初始化MDMA */" d9 u0 v1 j8 u& I) J" o
- if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)2 B; q. G1 ~ _0 o- r$ _; Z
- {
7 h# V4 }. @# p6 G+ J- u0 k- M3 b - Error_Handler(__FILE__, __LINE__);
9 p5 _ S- N+ _% w& u - }
7 t5 h! |5 Z/ L. z% ]
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 ?: _- 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
- {
- t' ?2 B6 S, F& F1 ^0 Z: w8 s9 v- l - /* 检测参数 */
1 E% [! C6 {6 G! G/ c U6 v - assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
; Z2 t3 G/ B t' o - assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); 6 l) q m$ @2 w7 w6 Y, T
- 0 a7 ^' _! F7 G/ b" ]: P9 Z
- /* 检测句柄是否有效 */! F2 {/ ^% W5 i9 [/ e4 A
- if(hmdma == NULL)0 U& k. |3 ]( b8 ?: D2 t
- {1 H. I1 b0 ~3 G
- return HAL_ERROR;
% Z3 d" R& x5 A0 } - }
# Z$ q7 s& w# p! b0 }' ?9 i - ( L& D/ ^* z' M7 { x" S2 V
- /* 上锁 */6 y' K% Q2 M$ L6 B/ M# _
- __HAL_LOCK(hmdma);& D9 K& E$ q; g
( d( j M3 l# ?) K9 M1 A- if(HAL_MDMA_STATE_READY == hmdma->State)
5 O& ]1 F6 E$ j+ Z" T% V - {5 K+ J q" x( l9 R: ^5 R( y) W
- hmdma->State = HAL_MDMA_STATE_BUSY;+ a! p& N a% E: N* f
6 k4 a* c0 S1 r6 O; t& d% R; R- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; $ I2 V6 N$ f. K3 r# j, D' j+ S
- & h: k3 ~0 m \$ J6 S/ |" G1 H
- __HAL_MDMA_DISABLE(hmdma);
. J( R1 e2 u+ G# H; x, ^9 w& @1 B
2 e- _' M0 {7 v9 z, Z6 _3 H- /* 配置MDMA */
, t% \# o- D0 Y8 n - MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);, q# f( G0 E: l- a& V/ b
2 Y3 J1 ~2 w# f4 D( L9 Z7 e- /* 使能传输错误和传输完成中断 */6 C8 L3 t+ y8 y% H
- __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
+ b- P$ c- j. I! n - 7 C4 C! K+ `8 x' f
- if(hmdma->XferBlockCpltCallback != NULL)
1 h9 C8 Z8 n v2 q& d+ U# _ - {
! l1 e+ |" _9 n0 g - /* 使能块传输完成中断 */' }" P' Z. H. q" \$ E' Y. E
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
8 l* U( B5 c9 \% e* u& Q# d; c8 y - }9 e# X' o$ |3 `+ C9 L
- 0 p. q( V# [5 ~- q2 x
- if(hmdma->XferRepeatBlockCpltCallback != NULL). A8 f! C: r0 E& d$ a; @9 A6 Q
- {
. p& W6 T4 o( ?5 w - /* 使能多块传输完成中断 */ / ^( @) x6 j6 b7 e H8 D
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT); / @0 n3 V ~7 ]9 F
- }
: P# g, s7 ~5 b( e- }( J$ j1 s
3 W- b2 ]1 e* \, c- if(hmdma->XferBufferCpltCallback != NULL)
1 a+ h- e$ x* ]+ ? - {: M/ b" C; X# l& j5 K. ~2 @9 c
- /* 使能传输完成中断 */
; m0 R# G) I# j, Y0 p - __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);9 u; [) H( k- L
- }
; `1 W& ^. m( @5 x" J - ( `+ B7 f5 {2 w. Q2 n
- /* 使能外设 *// x O# f+ K0 |! t. a
- __HAL_MDMA_ENABLE(hmdma);& x5 z* i3 j7 p5 x7 H+ T
: J( y8 ~4 X+ _ D7 W# s/ |- if(hmdma->Init.Request == MDMA_REQUEST_SW)# p9 r+ i1 @# W/ k! ^
- {
8 W# N) w1 @4 S/ m: I; ^# N - /* 使能软件请求 */
4 w9 B, u; A; h0 b - hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
/ H1 {& F9 U7 E s5 z A2 W. B. c - } 2 G# |, f0 G* k5 P7 l. V4 Q7 B
- }
, a: D* W6 ]" r1 [6 I* C - else1 |) f1 l+ [9 j+ ?5 P
- {
- {9 K7 Z. o O1 M; x - /* 解锁 */
- `8 X$ d W* g7 |" ~: W - __HAL_UNLOCK(hmdma);
! U7 f& q! u, d" @
) D% X: m5 k2 ]+ i4 c. j- d3 k9 f/ |- /* 返回忙 */; H1 @8 F) b j1 ~1 R5 g
- return HAL_BUSY;
w7 K9 d$ o! F- A+ l$ v/ S - }: g6 p8 u9 s! V2 G" n
2 p/ |) M- S% o- z! r; g: w- [- return HAL_OK;9 P( K6 f; y& x' S& D
- }
复制代码 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- /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 *// S& d. i7 K3 w9 m/ }
- HAL_MDMA_Start_IT(&MDMA_Handle,
+ K2 H, I: d% M6 m% V - (uint32_t)0x24000000,
/ {. u0 k* M) g; r/ h$ o - (uint32_t)(0x24000000 + 64*1024), . [3 W5 m! W0 X7 P. o
- 64*1024,
$ `) n; q+ a M* S/ m- _ - 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 |