61.1 初学者重要提示
* B3 g0 f2 X- H0 ]6 p5 d$ G3 h MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。! K; D' [, n2 n9 C0 V
对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。
, C# @: g! U8 H$ [61.2 MDMA基础知识
5 l% W3 h! J! x$ R- X* r6 {对于STM32H7的MDMA了解到以下几点即可:
5 l9 K+ p& W# _$ Z) u# n& g3 l( T; U( o' ~
由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。
4 r* e9 W+ B0 S; W1 \6 y MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。4 Q% A( k% ~7 y3 C: T8 x/ U" f" T
有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。; v& n T: _7 ~3 Q/ b+ S: j( V
16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2
) b0 C/ G- _5 { MDMA具有一个256级的DMA空间,被分为两个128级空间使用。
/ |, r8 a) \! y: U% B- z7 |( V7 q MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低
+ o$ {. o/ V" f. V4 A) t. r 数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
- s9 j& i. J4 e8 P6 X4 c0 S 源地址和目标地址的大小和地址增量可以独立选择。4 |! b! V$ A2 B& f8 k5 s+ J
数据的打包和拆解是采用的小端格式。* y3 _3 q9 t7 _4 {4 W7 U9 [
支持突发模式,最大可传输128字节。
, u3 l) k/ j1 A1 ~ 当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。5 ~' C& x/ \6 W9 @4 p! X5 U
61.2.1 MDMA硬件框图 w$ e+ w; H! r& M* _& M: R
认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:7 H2 Z L% [: X8 @6 X! f
' O8 v# _$ u- ^% m, U$ o2 _2 Q2 ]
u& ?* q% S4 W通过这个框图,我们可以得到如下信息:
6 z; ^6 o( i2 e% X; `- R5 q5 d' s( `
9 q3 \1 k7 M* {6 |' ` mdma_it
- \" e5 t6 S0 N" v% pmdma的中断触发信号。
; J. _+ t1 U* F/ f* |
. x: e; f1 J% o( z" |2 `. u- S mdma_str0到mdma_str31触发源5 _+ N5 b2 o. f& t( k" N% g- V
mdma的输入请求。
/ R" M5 ?* }( w2 _4 [; \2 |' K0 j4 W- W0 h& G
mdma_hclk, A k: ~7 q% E2 n" T1 F
MDMA的HCLK时钟。
( j6 J: J& ]* p; Q+ [5 [2 H3 O
9 C7 a) y& w. \61.2.2 MDMA块传输,缓冲传输和列表传输区别3 M0 B! Z5 z8 q: U/ U0 m
初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。
1 g3 Z, O( T' Q8 e; |
" d+ J# P$ t) l 缓冲传输(MDMA_BUFFER_TRANSFER)& p3 N k0 x4 t3 z
这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。) D. s6 B1 Y9 E
% R/ \! _) R. }& q1 V) R5 n7 W/ h$ p4 }6 p: z
块传输(MDMA_BLOCK_TRANSFER)9 m6 S) J, U+ S* ]6 h
此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。 R; T( }: ^1 w, @1 N, P
' m, I( X; p$ O: d6 }6 x( x5 p+ j H" L( E; w6 ^( {
多块传输(MDMA_REPEAT_BLOCK_TRANSFER)% ]3 L& \9 J3 Q& [
顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
$ _* ^, D) j9 w, U s) s0 ^
4 e4 {; W/ M9 K' O
& J& H& X9 [; @ 列表传输(MDMA_FULL_TRANSFER)0 Z5 a: t6 N, H. F( v
这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),$ \. |5 b! w; m. I% ?7 V5 z$ f- B
# n1 r4 b* _8 P* b8 a
61.2.3 MDMA列表模式及其循环方式
- m2 t7 H; f& x列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。4 T$ n" X [) `- h4 O! E# Z7 X
# W: ~+ d+ S4 X. N: J
使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。$ x2 t8 b6 E+ A
使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。
+ y) Y6 P, z' b7 G* V: U 节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。6 o+ [& x$ u( d: o; |- Y
如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。
# @4 p8 r' m/ z7 e) W: p m 通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。( g5 G* J: B( P. y9 U. g& Q. g
61.2.4 MDMA的触发源
2 N& `, J/ j$ w/ a( ?" G# s" T( HMDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:
% o N1 o% G* Y, e" C$ X5 o3 z0 l" z: _) l8 {& t5 q
- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U)
4 w0 v% n. }) K: L" y - #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U) / g( o h% C! L" Q2 c
- #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U) 9 ]/ [* C7 i1 i" g, o" c
- #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U) ! t+ B. F' w8 B6 f
- #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)5 U# I# n3 w2 A/ z
- #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U) ) Z8 b8 f* J! A$ E; k- l
- #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U); e" L' o4 A" Z3 w8 A
- #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U) + d) F4 S* ]5 S% p9 ^( n0 |
- #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U)
- E { j; G& ` - #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
1 X. K2 l/ d1 K) w# s# h3 E - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU)
# [6 X6 k* \/ e; S% `9 N - #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU)
- O' x* S) I9 M& _ - #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
, n9 F+ w& V0 ] - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU)2 O N# y. n2 A$ n( J. j7 E1 h% W- u" H
- #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU) * X, D3 l4 L" z' Q/ d
- #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU)8 m2 m* U9 a) R- j8 r; Q( G
- #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U) / \9 F# a; q5 F I3 ^
- #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U) + X, n' f# {, v' }. N" T
- #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U)
+ W; P7 a) Y6 J" z* D; O# _) h - #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U) 3 r. I& A! }7 q
- #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U) # z! M2 x" F& c/ l
- #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U) ; o! S5 D. i6 Z2 L
- #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) 8 v# t# c, C+ h9 f! e
- #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) : S3 M( ]7 k3 j' h: O
- #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U)
z! _. U0 H4 m: Y, { - #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U) ) y1 g7 n8 x1 o; D3 O- d
- #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU)
2 l$ f/ W4 l7 K; H
9 {- `0 ?3 i' {: s3 @- #if defined(DSI)
' y7 i# N/ N8 I* t+ U9 [5 q - #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU) & @! Q: k0 k! F( P+ n4 s$ A9 C4 g
- #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU)
) K$ X2 L6 k4 ]/ d; H - #endif /* DSI */, x* y8 Y7 R$ k' j9 B
- a4 j/ h$ P( Q1 m9 }- #define MDMA_REQUEST_SDMMC1_ED_DATA ((uint32_t)0x0000001DU) ! k/ M- i0 J2 W2 x1 @. k* N
- ; f$ R C2 \9 X5 J
- #define MDMA_REQUEST_SW ((uint32_t)0x40000000U)
复制代码
$ M8 v1 ?1 }; y c. i0 _3 U& V% \# G) g3 A
5 W2 K3 x3 O) \8 V* n61.2.5 MDMA的软件触发方式
! m. b0 c! l. u5 ^4 \MDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:6 ~7 N; w+ u: p4 y# |
! S3 E O( O ~, ~) f' a
如果传输结束或者传输还没有启动,调用此函数会返回error。0 i1 @# X: Y$ U: @
如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。
# h7 R$ ^4 [4 j. ^. T" P& G8 R& A! b
. @2 Z2 ]9 {5 X
应用示例1:
% `& n8 m: H# ?+ ~' B& t7 @
& R7 @9 e! ^4 m! O MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。
( S4 d. ]; ]' E. j3 z% O 注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。" p- m- B/ K! \+ v! j; n
调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。2 [, V0 v2 A" B! M4 Q2 @) _
传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。8 G# d4 P/ F, A2 L# \' ~
" B, }5 G o& c) C5 q1 `4 t% ^: s8 J& _1 b
应用示例2:' _! m% A$ d$ d9 Q
6 ^5 s' v% X0 Y2 ~& ], J; i7 a MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。
: V* x& l! C! }; o" l 注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。: G3 e6 p/ n3 w. C4 i4 N, {) N
调用函数HAL_MDMA_Start_IT会触发一次块传输。
+ s3 k' ^& i0 M2 c 传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。
7 ~+ ^6 d Q0 x( @$ I& _" t7 |$ [61.3 MDMA的HAL库用法
8 H, N: p/ U$ Q* I1 yMDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
, w- Y, W) Z* s! p7 J; Y" M) n& J* [% U7 `, l4 ^/ T }2 s
61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef
. N4 {! M% V4 k0 G0 J' T. jMDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:# R1 U0 }4 F/ N* k/ s( t3 @
3 Y1 F1 g. n% i- m/ _
- typedef struct9 u" f# P/ z! ~: R
- {
- K2 B) g8 ]2 [$ r - __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */# Q1 V! u# J9 j: @: d7 S! d3 P
- __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */: C' ?( t$ z. @* [3 j% ?
- __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */
* Q3 e' J" q% R. q - __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ ' }. x$ |* M% ], b% s
- __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */( s2 c% k1 l$ j6 w# ? A/ [$ }
- __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */0 g3 v6 T n6 j
- __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */
# f4 L1 C8 O# ]% o9 z - __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */1 [5 M, e& Z) G1 v1 Q' C# Y0 F
- __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */
5 Q! c3 L6 k- P5 s8 a3 K9 _9 | - __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */5 y& w( ?5 k8 s6 \& T5 d. E3 ^
- __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */6 u8 t7 X+ q( e$ }8 }5 x( T
- uint32_t RESERVED0; /*!< Reserved, 0x68 */ r! f2 x0 C7 p4 r; e
- __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */
$ z9 w+ b8 _/ P% C( q - __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */
$ P) N' t4 r0 Y. R! C - }MDMA_Channel_TypeDef;4 K! {& H* L" H# S1 d7 [2 J
+ R$ y7 m* f& m0 W- typedef struct
+ Q2 _: V; `2 l. o - {4 L% @$ v7 H( ~0 {& B2 z# m* O" q
- __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */8 N4 N' Y8 U& ~5 d# S# V8 M f9 G3 h
- }MDMA_TypeDef;* a# r9 I" o4 P. L$ M
复制代码 * [* g) _ S4 o2 J
1 v% s% o2 N6 N' j" I% ?__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
- n7 N. E( S9 U! F0 Q9 {- #define __O volatile /*!< Defines 'write only' permissions */
* M# Y( O0 _& T0 {$ _, _9 M - #define __IO volatile /*!< Defines 'read / write' permissions */
复制代码 8 R. W1 j8 h! t: J
下面我们再看MDMA的定义,在stm32h743xx.h文件。
- j3 X4 H- v+ W6 [' P- I$ Q3 D8 c' P" a( n* O1 T
- #define PERIPH_BASE ((uint32_t)0x40000000)
% e8 Q! Q1 y& m1 v- o5 E$ D - #define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000)
( c9 u' ^% i+ z - #define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000)
8 R! Q( h2 e" V0 l0 n4 S4 e - 6 e: e: o0 A/ H4 W2 x9 ]. P
- #define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040)+ [! w7 y2 m3 z! G! k
- #define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080)5 D* Z5 y* H. j3 M; R
- #define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0)
' t$ d6 b [- f# `4 ?1 Q - #define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100)
. \' j# j H7 {) }3 ^6 Z" S - #define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140)0 g* O$ d# v7 Y' w, ^! n
- #define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180)( c' @$ v! m% h; J! ?! m' W, A
- #define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0)
( Z6 e" _ x4 p7 \ - #define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200) V7 R! x6 b: R' \
- #define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240)
/ a3 N% s% R" d; Y7 U - #define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280)8 t9 |6 Y2 o# q
- #define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0)
9 {- k" J% l# b0 }% F/ K - #define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300); o5 C/ R! T; ]( ~* F/ y6 P
- #define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340)
% s1 B/ i" k4 y5 o* S, `5 t - #define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380)
4 v; E# i2 T4 k# F/ v2 R. H0 _ - #define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0)- f* L- @! ~% A6 e4 ]
- #define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400)6 n r! o, p& ]
7 H5 c/ s9 i7 A# {4 v& N$ e$ \- #define MDMA ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000- J; v3 }, D! @# `8 Q, x
- #define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)
+ n: i$ `; J- i/ Y/ [ - #define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)0 I% c7 K) X, y/ C8 q( i
- #define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)
4 ]$ }- y+ ^- l9 @9 H+ W - #define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
i* @ V# O+ m$ o2 }0 ^! e - #define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)
1 K8 d2 e2 y2 a, S7 P8 U - #define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
+ f- A" P5 {$ x! n$ F$ C& ] - #define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
$ S* l, ^# d2 j/ u1 K/ {3 q - #define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
! d- o0 S8 B' D8 ^; o/ O& ~; w1 i - #define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)" Y# ?2 h" `( t5 Y1 l% m8 Y' J
- #define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE)/ _+ g, x' Y3 T, Z* I8 y5 V, Q
- #define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)& L9 N2 _5 l8 J! o" u' f4 r' {
- #define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
: E6 V. e5 Q& P9 w - #define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)8 z' q" V" ]3 ] s
- #define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
$ O/ U1 J8 q5 d9 E9 j - #define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)" L9 S! V H) n4 J7 X T
- #define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码
1 _+ H W4 f# c6 I3 H2 y( z/ [/ n- D; e# [/ z, \2 \
8 s2 E/ ]: M- C6 ^8 e4 ?
我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。
0 M: ^8 m: T$ }4 P8 \: p3 @' J: _" l2 g% r
61.3.2 MDMA的参数结构体MDMA_InitTypeDef
* f1 }0 n( H' v1 q0 U此结构体用于MDMA的参数配置,具体定义如下:
4 {7 i: D* I7 N* ]$ q$ |
$ q& g, T- ~. S# _- n, J- typedef struct
# B4 H" ?" z( A2 D! O6 Y4 [ - {. ?' {* F, W. `$ U6 E
- uint32_t Request;
& T9 ?% Z0 M- d% c! p, N - uint32_t TransferTriggerMode; $ y' h h F( y
- uint32_t Priority;
# i) `. M. q3 g l# G( u - uint32_t Endianness;
3 x+ \2 W2 F" D3 M - uint32_t SourceInc; - D, ^5 p+ }9 i4 n" `! O, x
- uint32_t DestinationInc;
- Q' K* C0 M' i& x - uint32_t SourceDataSize; % f# v8 ? |: y
- uint32_t DestDataSize;
9 N8 V- c- s7 U1 q* l( r - uint32_t DataAlignment; % ?$ g0 X, k& C5 }% V: A9 q
- uint32_t BufferTransferLength; & c6 G) c) N/ p; @2 i) a
- uint32_t SourceBurst; ) Y7 ?! l! n% {) ]" p% h1 Z
- uint32_t DestBurst;
2 g. e' W+ Y2 T3 Y$ a9 w# j* ? - int32_t SourceBlockAddressOffset; # r! G: A1 _; T) T
- int32_t DestBlockAddressOffset;
4 A, {% ~$ ]$ i- h - }MDMA_InitTypeDef;
复制代码 , |. y5 B4 Z# g3 _/ A+ B3 A( o
@$ i2 u9 `, @6 n
/ I8 x( C' ?/ _ ^1 O下面将这几个参数逐一为大家做个说明:
. o+ s- P& }6 S2 b# [* p. M- i2 V5 \3 `8 a$ b7 r2 ]
uint32_t Request5 ^1 z7 V5 j$ Y3 R; Y% `/ a
触发MDMA的请求源,支持请求源如下:
3 A% J' g3 m L; M0 E) J
9 X) _( L: \3 i' P- ]; v5 _/ W- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U) , P1 Z8 _6 O& z+ `. s& r# s* W
- #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U) ; { a' V3 ~# G
- #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U) ' ]( G5 |0 } ?1 Y& s# ~! j- G7 h
- #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U)
# n9 B- `8 M+ R/ X& z, q' C5 B - #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U) 7 D! Y/ R3 N; ]. ]5 W& E2 l% Z9 q
- #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U) 4 t# ~: T1 u) c4 i
- #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
5 P2 j8 ^. ?/ u( R/ E - #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U) ! H: s% d. e( x& ^
- #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U)
! W+ O1 M* h: L3 Q) i: g0 B - #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
: Y+ p, j2 M' |1 B. p# Y8 A- b - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU) , \; a& K$ e7 e( T! [6 r! V
- #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU)
/ D: U7 \* p0 y2 |" A$ K" Z - #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
4 p! t: j1 Q7 G& i - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU)
& L& v* b) {: k. X - #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU) - z* ^/ ]7 d8 x0 k) q+ x
- #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU) " {; ? D6 z- }" F" }5 a) U( {
- #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U)
4 F- u6 _% A/ w. |4 v - #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U)
% z4 {0 ^" r4 t8 S- o% n - #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U) ; _# U0 W% o! I0 a# U* Z
- #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U) 0 X) c4 r4 v9 }& O* ^. g$ v j$ E
- #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U)
$ n2 Y# C3 R2 Y+ D1 |2 @ - #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U) $ n: e5 t% f) Z% U! H- X( W; I5 x
- #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U)
h4 K0 ~ m/ z - #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U)
0 m* T, p! Q+ E+ W; ] - #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U) + W9 R. O) X7 O
- #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U) & L4 N+ N2 a" m! N$ X/ c; g& w& s" E
- #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU) & r" d; O! {- t, Q+ h
- # n+ `' t% D* c! B
- #if defined(DSI)
% R2 X* `0 m9 @7 d - #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU)
; E( c; M- O* S - #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU)
- {8 D6 [( Y6 A' r& x8 r' ]. ] - #endif /* DSI */# p3 Z9 u- x: S( b+ O' R0 t
" m/ |" |7 l9 y1 o) i- #define MDMA_REQUEST_SDMMC1_END_DATA ((uint32_t)0x0000001DU)
T- Y. L+ f9 T' J6 y- h1 L - #define MDMA_REQUEST_SW ((uint32_t)0x40000000U) 8 ^+ `% [! N, U( R- b
复制代码 & b" q1 t- Y( s; X, y
1 n W( w4 e" ^ g
uint32_t TransferTriggerMode$ t2 E: w" I% F% z2 g3 y
MDMA的传输模式,具体支持的参数如下:
7 e, V& k& Q# m3 U9 c( w' `9 R6 G3 M, O# k9 S) U
- #define MDMA_BUFFER_TRANSFER ((uint32_t)0x00000000U) /* 缓冲传输 */2 E( [: {$ Y5 \+ f, `
- #define MDMA_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */6 B) N6 P- @) C" T, e* F" l% f
- #define MDMA_REPEAT_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
; p; z8 ^. H$ ` K- z+ @4 M [ - #define MDMA_FULL_TRANSFER ((uint32_t)MDMA_CTCR_TRGM) /* 链表传输 */
复制代码 $ R- d) W3 ~5 T$ u8 t
5 h" J+ O7 C4 {+ P j4 ^# r3 |
$ Z3 w. L& l6 O uint32_t Priority
$ e/ y3 j: A& Z6 [7 JMDMA通道的优先级设置,具体支持的参数如下:1 i8 ^( i/ |' O2 U
9 ~8 g- J1 f+ v2 c6 ^5 F! J! N1 N- #define MDMA_PRIORITY_LOW ((uint32_t)0x00000000U) ' {/ z2 w$ {& [8 ]
- #define MDMA_PRIORITY_MEDIUM ((uint32_t)MDMA_CCR_PL_0)
5 C' t' j5 W; f, ^" U$ m0 d - #define MDMA_PRIORITY_HIGH ((uint32_t)MDMA_CCR_PL_1)
( g3 \: j5 ^1 g( @5 | P8 I - #define MDMA_PRIORITY_VERY_HIGH ((uint32_t)MDMA_CCR_PL)
复制代码
" b! K% n/ Z, x, G9 w( M
s3 F: z$ g% g; c, _, Q1 }% S& I
" [9 H! N+ F. k E0 }( c8 h6 d uint32_t Endianness' s1 N8 x u# u G! r: [% w$ a
MDMA数据传输格式,具体支持的参数如下:
- T o, b4 l {% u! z0 Q
0 B1 Y$ H: z$ W0 }" F* ]- #define MDMA_LITTLE_ENDIANNESS_PRESERVE ((uint32_t)0x00000000U)
2 n% {" v. m( M6 }& @ B- K3 s0 S - #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_BEX)
* @2 {- ] o2 s0 e& G& ? - #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX) # x# g$ R7 F. a' B
- #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_WEX)
复制代码 ( P$ l; I% }1 A2 A* `" o/ i' {
- U1 ~7 K% m, nMDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。
! Q) n1 F4 b. |3 J, _) R
, H' X) y! g; V& k' JMDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。
8 ^$ O: k+ o+ ], U! @+ D- e: g% R, I6 [5 w1 `
MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。; I* o5 q8 A9 Y
- t0 t4 G; V/ E5 O1 P5 J4 nMDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。
% ^/ }& W, o! a. ^+ Y2 B' k7 F
1 P" D- k: O6 k) K. @ uint32_t SourceInc5 O+ H: g; N8 h% s
MDMA源数据自增或者自减模式,具体支持的参数如下:
( }# |) k1 w0 N: @0 }+ G- ?- $ J: q, c8 r+ C6 N" S# q2 M+ c
- #define MDMA_SRC_INC_DISABLE ((uint32_t)0x00000000U) 5 i6 w1 c4 b# @) Q9 H0 n J O
- #define MDMA_SRC_INC_BYTE ((uint32_t)MDMA_CTCR_SINC_1) , F. w+ A' d( o# Z' V$ m
- #define MDMA_SRC_INC_HALFWORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)
/ o+ l* ~- W4 ~ T# _ - #define MDMA_SRC_INC_WORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1)
+ h7 O; P/ e+ c6 q2 S5 m: _. D - #define MDMA_SRC_INC_DOUBLEWORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)
A! R/ o8 y0 b) y - #define MDMA_SRC_DEC_BYTE ((uint32_t)MDMA_CTCR_SINC) * B: V$ G2 r8 j
- #define MDMA_SRC_DEC_HALFWORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0)
- c8 c% k( ?2 V - #define MDMA_SRC_DEC_WORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1) 5 k7 }" r3 |, T. M- o- m% N: p
- #define MDMA_SRC_DEC_DOUBLEWORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)
复制代码
, J: R( y5 M1 f" J6 e* J$ l5 \3 \+ r$ J/ C6 H& X
]! C% M' {- t0 J; E DestinationInc
2 t% s! C; w% m4 o0 ]8 v$ |MDMA目的数据自增或者自减模式,具体支持的参数如下:
0 m7 V4 \7 K; u2 L/ c
7 n) r' K6 A8 n) N# k7 l$ S7 ^- #define MDMA_DEST_INC_DISABLE ((uint32_t)0x00000000U)
) |9 F( m( C* z H- P" k, ~! _0 T - #define MDMA_DEST_INC_BYTE ((uint32_t)MDMA_CTCR_DINC_1) ! |7 _! \! O) y! P$ N: p8 N$ l
- #define MDMA_DEST_INC_HALFWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
( Y2 A) z f v- T( {, }8 \7 C x6 O - #define MDMA_DEST_INC_WORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1) : N b6 `7 l# y2 Y+ L( g
- #define MDMA_DEST_INC_DOUBLEWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS) & m0 M' Z m1 O) Y- q
- #define MDMA_DEST_DEC_BYTE ((uint32_t)MDMA_CTCR_DINC) 5 r9 u' L. ]7 o) }
- #define MDMA_DEST_DEC_HALFWORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0) - {5 K) D$ C" k) `6 _1 N% T
- #define MDMA_DEST_DEC_WORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)
7 F- c# t6 C( ]+ `+ ]+ ~ - #define MDMA_DEST_DEC_DOUBLEWORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)
复制代码 - v3 y7 A! _) `/ c
. ` t! a. x: i5 g
, e6 g: K% B8 u3 X SourceDataSize& D" j6 g/ B. g9 J2 J2 r+ _1 t7 l
MDMA源数据带宽,具体支持的参数如下:
: v h$ r a) g O) L) H5 Z, B. N5 Y3 Y2 {* Z& U
- #define MDMA_SRC_DATASIZE_BYTE ((uint32_t)0x00000000U)
6 b5 |& j& _) {! b6 U/ a4 s - #define MDMA_SRC_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_SSIZE_0) - P0 c' M9 ?8 S; S
- #define MDMA_SRC_DATASIZE_WORD ((uint32_t)MDMA_CTCR_SSIZE_1) / K7 j" S. ~' |4 \
- #define MDMA_SRC_DATASIZE_DOUBLEWORD ((uint32_t)MDMA_CTCR_SSIZE)
- S" X, h+ P+ N, G0 m/ {# v
复制代码
* [! }( \) B5 m1 c
1 x4 `) }9 q8 p# |0 M% v' Y DestDataSize
( {. }" T. w; s$ O% ^( g' r) XMDMA目的数据带宽,具体支持的参数如下: X+ K/ r1 {4 \3 b
9 [! |0 m5 o8 T u- #define MDMA_DEST_DATASIZE_BYTE ((uint32_t)0x00000000U)
* N, @$ j0 ]% \8 T& I& Y1 c8 F! \ - #define MDMA_DEST_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_DSIZE_0)
. [0 G' D9 Y/ i* D - #define MDMA_DEST_DATASIZE_WORD ((uint32_t)MDMA_CTCR_DSIZE_1) 2 P2 w, T, M1 j8 P* H2 J
- #define MDMA_DEST_DATASIZE_DOUBLEWORD ((uint32_t)MDMA_CTCR_DSIZE)
复制代码 % l4 \ }/ _2 k. H9 B+ o
: v E- |3 F$ W8 \# f( C4 \& ?( z! z G: F+ F: z6 P9 x
DataAlignment" S9 | D+ c; e5 q3 X
MDMA的填充/对齐设置,具体支持的参数如下:3 r4 O9 I6 m* k! ~# Z/ ^
- #define MDMA_DATAALIGN_PACKENABLE (uint32_t)MDMA_CTCR_PKE) V1 I7 u3 b4 o6 b9 }
- #define MDMA_DATAALIGN_RIGHT ((uint32_t)0x00000000U) 8 e/ r# k. _% u) U' q
- #define MDMA_DATAALIGN_RIGHT_SIGNED ((uint32_t)MDMA_CTCR_PAM_0) 1 G# a& f6 m ^9 c3 Z$ ^ f3 Y8 I
- #define MDMA_DATAALIGN_LEFT ((uint32_t)MDMA_CTCR_PAM_1)
复制代码
/ i7 i; [0 l! v. F+ n, v8 f. ]# l9 r- t0 X {! |
1 [2 B+ I; L0 \. WMDMA_DATAALIGN_PACKENABLE:/ G: u. R$ \ k+ P: [
( L8 W( `! F0 ^& x1 w
将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。: G4 Q2 }# D( b
' ?& ?0 _" E8 kMDMA_DATAALIGN_RIGHT& n' a1 \3 x) p, W, ~
4 D; p6 W9 B5 c( w0 l4 K+ h) N8 C右对齐,用 0 进行填充(默认值)- G; y& M7 t! }+ {4 z' v4 D- v
$ R0 g' Q$ X s: g' I9 NMDMA_DATAALIGN_RIGHT_SIGNED, E' R1 T. G( U; R7 q
) @' r* e C1 U0 i右对齐,符号扩展
9 V- `+ V' I* X$ L( U
4 m. I4 I- d; S3 j% L# M; d- D- w0 LMDMA_DATAALIGN_LEFT
6 w! V+ r; }' ^* f" ? r, M! V8 ^* E0 h G
左对齐(用 0 进行填充)
3 s R3 A7 S! N) ^
1 q- [+ m! Q1 I) l BufferTransferLength
I; h9 ?3 X! F& |, U单次传输长度设置,范围1-128,单位字节。+ X* \) M4 M- K( E
7 ^/ a5 Q" `4 j SourceBurst+ F9 S" x5 X5 S @/ }0 y: s8 U
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:
# |9 u7 Y4 ]* n% F! v; p5 i2 D$ k
- #define MDMA_SOURCE_BURST_SINGLE ((uint32_t)0x00000000U)
: ~, p& i' c9 x8 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) % y" v; c' u6 K6 t; x6 w+ V4 R/ n* e3 k
- #define MDMA_SOURCE_BURST_16BEATS ((uint32_t)MDMA_CTCR_SBURST_2)
% w9 N) F# O$ d; j9 I' D& |9 \) g - #define MDMA_SOURCE_BURST_32BEATS ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2) 2 I* g/ @4 l* ^$ C6 n( U
- #define MDMA_SOURCE_BURST_64BEATS ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2) ( |" r' }: d. n- ]
- #define MDMA_SOURCE_BURST_128BEATS ((uint32_t)MDMA_CTCR_SBURST) 5 ] R; b% h- I* H6 C8 v
复制代码
. v r0 v( T- @
h0 [+ f) W6 S4 r2 o2 ~ DestBurst
& q$ O3 r8 W! r9 u+ E. a" G目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下
/ [6 d3 p7 N( L- #define MDMA_DEST_BURST_SINGLE ((uint32_t)0x00000000U) - k4 ^, d" [$ f+ |6 S
- #define MDMA_DEST_BURST_2BEATS ((uint32_t)MDMA_CTCR_DBURST_0) $ J' l/ `( p1 }* O8 | t) E
- #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) ! o! q3 C2 G& |" E# c9 W4 b5 P
- #define MDMA_DEST_BURST_16BEATS ((uint32_t)MDMA_CTCR_DBURST_2)
~& Q( v& k3 M - #define MDMA_DEST_BURST_32BEATS ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)
P( X3 }+ I) V5 D$ a6 b1 g - #define MDMA_DEST_BURST_64BEATS ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
# b4 i/ P4 h; w7 [/ R1 B4 { - #define MDMA_DEST_BURST_128BEATS ((uint32_t)MDMA_CTCR_DBURST)
, N2 k3 q9 c3 @/ E+ e
复制代码 % Z- _6 W0 C- \0 D
SourceBlockAddressOffset
4 l% ]$ @: d/ x" Z4 A) z用于设置源地址端数据偏移。6 n8 O+ m J7 A: Y. Y
2 j7 h+ f$ ~" G2 K DestBlockAddressOffset$ K0 R( O, I5 s: W
用于设置目的地址端数据偏移。. x0 n* v0 T& T$ d9 L
4 B) R7 k& X( L2 G3 J3 c61.3.3 MDMA结构体句柄MDMA_HandleTypeDef
5 d, i' u2 x1 H* ^& K0 L; p, ]HAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:$ g6 o# W9 b, f! M2 k2 ~7 `- ?
. x! A+ C, C! n% D- typedef struct __MDMA_HandleTypeDef
) s3 ^) A1 X; I4 ~$ r* W: G$ A: b - {
6 ]# q1 n. G# ]4 k3 B - MDMA_Channel_TypeDef *Instance;
. m8 p: ?+ k- }0 D# N - MDMA_InitTypeDef Init; $ C" |3 j% _; w; h- E% L
- HAL_LockTypeDef Lock;
, P# D: w: d+ f! A5 G N0 R7 c$ O - __IO HAL_MDMA_StateTypeDef State; : ` \8 b: o) v9 y+ p$ x$ ~# O
- void *Parent; ' O. G' Y+ r' _) Q4 A! }
- void (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma); * @8 P( V/ @# t
- void (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
0 w9 f; ^4 M H( p. w - void (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
( y1 O! I9 K+ p4 _ P - void (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
$ d! L" R+ r/ k2 |, M - void (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma); 5 b* q0 g* q9 u1 V, ?
- void (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);
% k# W0 {5 t8 C0 R) r5 _ - MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;
4 ]& r- }' r) X5 }) v. N - MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress; / D3 b6 [# w9 y
- uint32_t LinkedListNodeCounter; & N+ g! g8 ^7 P4 h% C
- __IO uint32_t ErrorCode; 6 m, E0 d- w! ~2 d- d* o+ T) H& N4 {
- } MDMA_HandleTypeDef;
复制代码
/ E1 {( D$ d; N! n8 l1 x. m下面将这几个参数逐一做个说明。
2 ^% M3 @, _+ S: h, ` E' k0 O0 U! q$ y
/ Z4 w9 j" }9 M5 N) f5 O' J! @ MDMA_Channel_TypeDef *Instance! l, y6 s) v% k
这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。/ K' c6 P! d0 T% T, `9 C2 N
; S6 A# t2 y6 n+ ^& J1 s
MDMA_InitTypeDef Init
9 r* b7 ?0 S, V这个参数用于MDMA的通道参数初始化,详见本章3.2小节。! S, ~2 }) a) K2 j' ]
# `' b# I, Y$ n i) ] void *Parent
1 Y* f/ C d2 T/ p* r! B0 ?7 @8 d9 |2 Z用于记录MDMA关联的外设。$ O7 i! Y6 ~5 E. ?" ^( r
# b* B" ]! B8 [7 t' f void (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
, ~! n8 H! x3 p$ V void (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
' \. Q6 ~9 p4 v# a6 {3 H& { void (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma); 4 N! }2 v% y0 J' r! p: K/ c; h6 d
void (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);% I u1 ?' I( Y' y
void (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma); + ? x, l' w7 x
void (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma); 6 |, M* I7 Z1 }$ \0 J! x
MDMA的各种回调函数。
0 L' r I+ o: ~9 ^2 O$ B5 r0 W" W. R+ k9 T( g4 D
MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;
+ f6 r3 d$ r d$ \- \# T: u MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;5 n" S) N. n) c
uint32_t LinkedListNodeCounter;- F9 Q% S) _0 G
用于MDMA的列表模式。7 h, M. q9 k2 @6 ]" e1 N
% H1 F7 o- I0 P$ K, Y HAL_LockTypeDef Lock
4 \- S, ] j! W0 S0 f __IO HAL_DAC_STATETypeDef State
0 P; \! @2 f8 ~* g3 N1 Y8 a: D __IO uint32_t ErrorCode , G( h6 n' i0 J. F8 v2 o+ a
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。
6 c6 _0 b4 n# K3 i
8 s$ B; X2 y: p; a61.3.4 MDMA初始化流程总结0 F( g* \# O; J( }6 Z
使用方法由HAL库提供:
4 B0 _" y2 r6 F8 O( r& P& j* n5 O
0 M" @- p$ m' C! F, O 第1步:基本的初始化。
; U! W" M8 X4 G% i# Z" V9 A6 W# F) j' {6 N% |
函数HAL_MDMA_Init配置MDMA的基本参数。
$ t) o( @" P# n+ W' k& Q
' ^) m7 l8 t) p7 U u" I/ \
# E6 w6 l9 g& Z5 k# ^ 第2步:列表模式。
" m% L4 }8 }/ r0 C2 D1 n
& p6 R2 @3 ~) z/ @% D6 ^' |# O如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
* |8 W5 f; K8 \, j4 ?
1 m ?; b6 g2 t# [* Z; H& T' h+ b% c9 {
第3步:查询模式。
8 T |: F2 Z+ b8 u* h" e
1 z: I& l7 L, G. `, }9 O( k 函数HAL_MDMA_Start 启动传输。
2 W* ~) Z' _2 y5 u; J1 [- i 函数HAL_MDMA_PollForTransfer 查询传输完成。
4 X3 f8 `; b- @& l 函数HAL_MDMA_Abort 终止传输。$ `& e6 A" ]7 `1 g+ w; U
& D ^4 p! [; j, a; ]5 F+ F- _3 N. G& Z
第4步:中断方式。' D3 n# r1 P! C3 c" s* o7 J8 u& `% w
5 f' H4 t: x( K6 A- g
函数HAL_NVIC_SetPriority设置MDMA中断优先级。) U2 v. f& C4 r
函数HAL_NVIC_EnableIRQ使能中断。
( ]9 I z. \$ A+ @- s3 h 函数HAL_MDMA_Start_IT启动中断传输。3 a# @" `- S1 e% S
MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。
6 J& _ \; k& i* j; G. d5 ] 函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)* L& H# w+ p: O" U6 j. N
" a* q- r" }5 s, z3 P6 k# Q J& _' r- @* K1 ]
第5步:中断回调函数。
* S, q9 ]' X$ H7 T, S/ @# }5 E6 a! L9 d% l5 W0 b+ {1 p
函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。' X+ W7 s2 }9 z0 r( H
& {* ?( B( L C- w/ e$ x XferCpltCallback : 传输完成回调。% i* L1 V3 b5 B7 G9 ?
XferBufferCpltCallback : buffer传输完成回调。
' \" c: j1 D* ?0 t& q6 a# H6 |& W XferBlockCpltCallback : block 传输完成回调。
5 C% d8 {9 t) P; ^9 L( H XferRepeatBlockCpltCallback : repeated block传输完成回调。 e! `" {2 N7 N3 n
XferErrorCallback : 传输错误回调。6 G" _" y- Y, s- j
XferAbortCallback : 传输终止回调。4 t! x3 C' D1 }+ J# U4 U# k. [
! o5 S1 m0 d% u& T# s$ {2 _( t2 m9 [5 n2 b% G, V, y" Y" _
61.4 源文件stm32h7xx_hal_mdma.c' T* T: V+ S- K) ^! |& C. @
这里把我们把如下几个常用到的函数做个说明:
# [. F8 x1 D+ ^! N5 @6 |% j! C6 I8 e) X1 z0 B
HAL_MDMA_Init
1 ^* w3 E4 S6 a! I3 P HAL_MDMA_Start_IT
8 ` l( K" c1 \$ D61.4.1 函数HAL_MDMA_Init
1 S" @, ^& S% i+ t+ A# e4 ^. i2 X. k3 H函数原型:7 ?+ d9 \1 s5 r
1 l: U$ s" E7 t& W/ t4 p
- HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)7 G0 k% f& g7 \2 y
- {/ O- C! y, I/ O6 Y
- uint32_t tickstart = HAL_GetTick();
: q- t& {5 B4 X8 E% |) k - ; |6 M- J* H% [# s6 i0 x) Y
- /* 检测句柄是否有效 */2 y8 L$ z; b) h5 t) }1 `
- if(hmdma == NULL); M; P% h( _3 S m6 v) |
- {0 n6 @* \0 ~' I1 r6 U* S
- return HAL_ERROR;
& U) h: C4 v. `0 m& o* b" K - }
* a$ j0 F c* p: n0 Q. v( F8 s1 _ - ; g9 O% @ r4 K4 I7 \6 y
- /* 检测参数 */0 Z# ^9 _& C" V$ S% X
- assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
" o4 S: k8 `. E1 l4 A" j9 o - assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
0 t3 o& |1 \3 C; L3 R - assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));5 z; X6 Q2 }: P
- assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
n ]. `7 Y9 h: [% A8 Z - assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));" w5 T& |' d" [4 A' _$ `
- assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));2 M0 L, o) j$ T5 F8 P
- assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
4 E" c: O7 j% M& G - assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));# E# F* S! p" k. R" ^: L. J+ J
- assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));1 V3 |9 n: \* I" o8 x6 I' y
- assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
# L* X. I A. v- V# W - assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));( t; B; Q& L' ?- \
- assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));) w- Y* J6 F( Z
- assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));! s: v6 @4 q9 j2 |$ |8 P
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
W2 u5 u2 u9 x. r - assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset)); & O, ^0 D% s: y# p N
" T1 E; F" X' S- |# `# f- a) B( c* j8 ^2 W7 w6 I
- /* 解锁 */7 f5 A9 {) J6 n1 Q
- __HAL_UNLOCK(hmdma);
# F) b5 F5 e' T" G& U; E
7 h4 _( X: O8 S5 A8 y% I L- /* Change MDMA peripheral state */
4 H6 z" x; _/ M. g/ J2 J5 @2 j& V - hmdma->State = HAL_MDMA_STATE_BUSY;
# c, ]7 A; f9 }+ }6 [4 F1 b0 ]
4 v [" p5 I! O- /* 禁止MDMA */3 B) d" [; A2 Y7 [4 d. l
- __HAL_MDMA_DISABLE(hmdma);
" a7 [6 ]6 G7 z: R/ r. m4 f - $ O3 K/ g- M' q9 q5 m7 v
- /* 等待禁止成功 */: x* o: x0 Y+ y7 ~, { M1 n O7 t
- while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET)
9 u+ P6 Z, C4 F' o7 T - {
) [% v) V @' s; t& \ - if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)7 S' B7 L- Q* w
- {
! `# J! o* {" z7 n- y - hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;& r; R- P: ~- F9 j
- ( ?, D$ e6 C) t2 ]6 S& _' @
- hmdma->State = HAL_MDMA_STATE_ERROR;
; `8 _7 ^6 x' `& N2 R% @ - 8 F; G( ]) H9 h/ F* l
- return HAL_ERROR;, ^0 _2 w5 h/ g2 g$ S
- }' j$ j( o: i% ]& d* G
- }
# O! v& ?$ ]2 P4 g0 u6 i% N: e7 g: o - 3 ^" I/ {! P; v+ k. Y
- /* 初始化 MDMA */ w% n% J4 k% N& s% b8 r
- MDMA_Init(hmdma);/ I& X2 D; L' J; q: s$ H( t
" I3 q/ D: c% f; ^, ^4 E4 I- /* 复位列表模式相关设置 */* E: J6 \& ]6 d
- hmdma->FirstLinkedListNodeAddress = 0;
K; g! r4 o* G; W& U - hmdma->LastLinkedListNodeAddress = 0; 0 x% B& u" V" T2 K
- hmdma->LinkedListNodeCounter = 0;
' ^: R, t" f7 y9 J - ! z7 A9 h+ Z6 ~0 q/ n D- ]
- /* 设置无错误 */# i+ A9 v9 H5 d: f3 q! A( M
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
+ k. u: M, ^! b: }) M7 p) N
3 G3 P5 O9 a! Z6 C7 X( z3 m- /* 设置就绪 */
: M, H5 t4 I N0 Z - hmdma->State = HAL_MDMA_STATE_READY;
) a* A- @3 A& Y+ B) X - 3 {) c9 v# W. c" T8 K
- return HAL_OK;* W: [; y5 r. m% j$ C1 B2 O! ^; P/ h
- }
复制代码
3 z }/ A1 M; |1 e: S; a7 i r F; A, r; G' L/ A/ l
! G: X& ^, _/ K G! o3 Z/ P函数描述:+ \9 l* b. p$ r0 O
D3 U" G' P! R( s
此函数用于初始化MDMA。
" m/ y( s& z+ ]* ~; I$ d! S7 y- C! }" d) }
函数参数:
. y. `6 Q* d1 a+ T$ @( |7 r
1 }. R, W0 u& Z0 s/ j5 ^4 M 第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
@5 i, @$ W% ^! r0 |( e 返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。- y* e4 Y8 T( T1 S7 g
使用举例:
' I8 C" R' a- S( t' z% X2 U2 N. ^ r0 l; h: t- F
- MDMA_HandleTypeDef MDMA_Handle;
- C8 I* E, k- U2 j, N
; }$ d/ ]0 P0 S' D- __HAL_RCC_MDMA_CLK_ENABLE(); 8 X( t: f) y7 T: \4 q- E7 p G3 S9 e. ^
- 7 Y6 o: m/ e5 R& |6 T. E0 [
- MDMA_Handle.Instance = MDMA_Channel0; 0 V0 r; }. [- g8 E9 j" M# r6 H
- # ^$ Y9 m$ y; C' X! A2 n. M
- MDMA_Handle.Init.Request = MDMA_REQUEST_SW; /* 软件触发 */
U! h# e/ }/ g - MDMA_Handle.Init.TransferTriggerMode = MDMA_BLOCK_TRANSFER; /* 块传输 */' f$ m: G- a. O* b: G Z5 w
- MDMA_Handle.Init.Priority = MDMA_PRIORITY_HIGH; /* 优先级高*/+ M5 n5 Y; g/ k4 e. [# K
- MDMA_Handle.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */
6 l! t6 i b9 v) z% C - MDMA_Handle.Init.SourceInc = MDMA_SRC_INC_DOUBLEWORD; /* 源地址自增,双字,即8字节 */- Y* e* J. S: E* Y4 |7 l
- MDMA_Handle.Init.DestinationInc = MDMA_DEST_INC_DOUBLEWORD; /* 目的地址自增,双字,即8字节 *// b, B& I+ \$ S6 @* D
- MDMA_Handle.Init.SourceDataSize = MDMA_SRC_DATASIZE_DOUBLEWORD; /* 源地址数据宽度双字,即8字节 */
# r8 z$ N9 _( o; S @, X - MDMA_Handle.Init.DestDataSize = MDMA_DEST_DATASIZE_DOUBLEWORD; /* 目的地址数据宽度双字,即8字节 */
0 K* H) ~ i' C; J% r, ^* x2 w - MDMA_Handle.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; /* 小端,右对齐 */
' H6 X u! N Q& l S8 m& k1 @ - MDMA_Handle.Init.SourceBurst = MDMA_SOURCE_BURST_16BEATS; /* 源数据突发传输 */- ?) e. i1 B- I+ \4 M! U/ D
- MDMA_Handle.Init.DestBurst = MDMA_DEST_BURST_16BEATS; /* 目的数据突发传输 */) d3 G# _# \1 t. {' {, n7 L7 ?
- / G. \' T' W# i# T# R& k- K0 h
- MDMA_Handle.Init.BufferTransferLength = 128; /* 每次传输128个字节 */
$ T9 D( ~* s6 F" h9 a, j
) x6 X. q. S4 t- MDMA_Handle.Init.SourceBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */
, x3 x# I" a( }: Z - MDMA_Handle.Init.DestBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */* Q' m; g+ S9 s I+ e
- - `# L! \4 ]( u' M
- /* 初始化MDMA */
6 \3 T% N0 [! R! Z8 c - if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)
3 |6 M& i- f6 Y& ^$ M! c, Z; q - {
+ R! H# o+ {# ]9 H - Error_Handler(__FILE__, __LINE__);
6 ?0 F L& ], x- |/ V8 `" Y8 k+ q - }
% j9 w2 g1 C8 R0 D# q6 \ - 6 m8 [& [; b7 A O4 V# W
复制代码 9 Y( \2 U+ P' Q3 Z: C
61.4.2 函数HAL_MDMA_Start_IT
5 Z2 Z0 A1 L6 `6 ~& `$ z函数原型:+ W! m: H! W' T$ x: n! O0 j
, M* L7 m0 n; W8 T
- HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
, n$ e) _9 {; O% R - {4 i* v' }3 O q9 F/ n$ |
- /* 检测参数 */
: u, Z# W) Y* r6 B9 U - assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1 [ T% {4 ^# O: o - assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
0 N$ C( {0 l4 v& v G - . W3 l: ~, a% G- ^
- /* 检测句柄是否有效 */
0 J; N# A9 o3 Y/ d% A5 c* i - if(hmdma == NULL)
- P$ j' A1 _, e7 u1 r3 e - {$ u! |9 C- ~4 f& Q* h
- return HAL_ERROR;4 \: x4 `% i9 n* {
- }
( C6 f8 a, M6 g2 a* L
; Q" h h* }: g) R$ |- /* 上锁 */
! u1 B0 R* |3 i' E* ` - __HAL_LOCK(hmdma);$ K) n! C9 W3 }8 ^& K: g
8 l* P1 B$ q3 r% h- if(HAL_MDMA_STATE_READY == hmdma->State)/ ]2 }) A f3 S% {1 G; T
- {$ ^! l+ N+ C$ f" G
- hmdma->State = HAL_MDMA_STATE_BUSY;( R2 q+ ]4 L' {2 |/ L9 T7 T
- . D$ X, S) O. ?1 E G
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; # a& C* x2 b- I* e5 k3 ~ T. c
- 8 ^' k! A4 E9 N S3 A& R
- __HAL_MDMA_DISABLE(hmdma);
+ D j; m4 L. E) t3 i# ]' e. B - # \5 {" O' `# r/ i
- /* 配置MDMA */8 x! J, b' q' q3 ]$ l+ G: s+ S
- MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);& I1 F9 N) e9 S
- , M9 b: O2 n6 P
- /* 使能传输错误和传输完成中断 */
! G! Z% B8 c$ `4 e3 s - __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
* ~/ n. X8 R, x% g+ D - 9 m" O; B+ E8 w, Z, r. [- \8 `3 d
- if(hmdma->XferBlockCpltCallback != NULL)
! b, ~% L4 V! W# T* X! ^- l+ I( F7 O$ u - {) b( v! Q# N! j* j5 {) j
- /* 使能块传输完成中断 */+ K0 Y' G' m6 `6 L' e% d5 X1 d( C
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
6 K- f8 ^* V5 w6 F/ K - }. M/ o0 L" V' f) c
% j" K; f: E4 \4 s, J& ?- if(hmdma->XferRepeatBlockCpltCallback != NULL)
' o6 J; \: r- ` L/ q8 m1 H - {& i o3 L) ]. z$ D$ J7 S4 b# w
- /* 使能多块传输完成中断 */
. L ?( {7 Y7 H* e, x" I - __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
- S! X% |+ }/ }" |, E' P - } : l6 p( ?, }0 q8 `
# C: y. G4 k8 [7 j- if(hmdma->XferBufferCpltCallback != NULL)
3 R2 e. L) H$ l( ?8 Z - {
. a) L! N5 {2 ~1 r- ?$ v! z g - /* 使能传输完成中断 */4 [& w) [/ ^% G
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);' {7 h. M4 Z" w2 h+ i
- }- M1 v$ c1 q/ d: m3 N4 h
- ; c1 N j& J! [6 j
- /* 使能外设 */
) {( f- N: u% n; Z9 o - __HAL_MDMA_ENABLE(hmdma);
; u" g; C5 E* |1 b, L' ~+ B- [. e: e& O - 4 I4 C' j2 U+ @" w1 b2 I0 R+ j; S& w
- if(hmdma->Init.Request == MDMA_REQUEST_SW)
+ g, E! ~7 A* o: l+ f% s - {) W) `, n h# T' s. v; ]
- /* 使能软件请求 */( M7 y5 F* I" H
- hmdma->Instance->CCR |= MDMA_CCR_SWRQ;# s5 s5 |7 m4 }) u
- }
, l& ~6 z b: {% T+ R& \. ?, d - }
$ S* j1 ] I5 z - else' i0 m2 c- m3 f
- {
; j. a' b2 |! \7 A - /* 解锁 */. X1 b8 X0 ~( \' D
- __HAL_UNLOCK(hmdma);
9 s" n! ~' g1 U) _$ M - I" b# F t3 |5 S7 K V
- /* 返回忙 */
0 T: _- y0 q" M- s" I - return HAL_BUSY;
7 |" M1 A' I: l. j+ L& V - }( q: i$ x6 B! ~# V3 O
C. {( n& _* [+ R- return HAL_OK;
6 y3 L% L! l$ V( V9 M) s+ g - }
复制代码 5 U7 Q3 K! @' X
3 l" N, y1 a5 \; O+ w7 B; o3 C2 k3 K! L3 Y
函数描述:
6 F6 x. o/ h. L* {7 Z" Y: @+ P* S
2 A: F$ X6 ~! e4 Z+ {4 b此函数主要用于配置MDMA的中断方式传输。# b0 D0 \( o/ m8 J
* W+ y0 W% C, d" U8 T; N" H6 J, E+ T函数参数:
8 n) u& P1 x! V- S; N* B
# J L+ ~3 e( ]# l* o- y! A4 ?' _ 第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。% V3 B6 e, _/ e1 g
第2个参数是源缓冲地址。2 @+ r# m( U1 Q4 {( G
第3个参数是目的地址。
! s1 J. ]; \, Q7 E) Q 第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。
& I5 ^8 \! c# B$ ]" b8 r. b1 d( h 第5个参数是传输的块数,范围不可以超过4095块。
# L- R0 r$ [$ F% @/ L( N& z' h 返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。 d! C) Z0 E, v/ y' J% `
使用举例:
5 h" H0 J; X' Y: \2 ~6 k7 J8 y, C% P' a2 ]: C6 [
- /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 */! k2 K* z5 X" E5 `
- HAL_MDMA_Start_IT(&MDMA_Handle, ! R* ]" z! \! U# S2 e; S6 w! B5 r
- (uint32_t)0x24000000, ' z" G" l A9 m$ y; k8 Q$ i% C" h
- (uint32_t)(0x24000000 + 64*1024),
& m. O \0 M8 P3 l3 Z# O7 {1 s - 64*1024,
! u# a) k. K7 ]& C$ p) ~ - 1);
3 B: ~% U4 P$ X* g# S
复制代码
/ p" e* Y9 u4 b) a
- r: x D0 w- `3 Y61.5 总结% U) D2 b' D; j' ]5 ^" A
本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。
1 I) R' a X# b% r% [, H; r
* Y" \ J) l8 B$ j5 t: b! E( e! f# }) m& I7 k* k+ A8 L
|