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

【经验分享】STM32 DMA详解

[复制链接]
STMCU小助手 发布时间:2022-4-18 10:22
本文是根据STM32F207的用户手册翻译整理而来- j  A4 y) _& L8 q7 `
2 g) C9 z" t# [# @4 E7 E
20200804225540904.png
  x/ u: O! o- Z1 {+ E( \- l8 N$ V$ {
+ O& u6 |' [" @1、综述
  j7 y7 n  j' a. N! H2 zDMA(Direct memory access)直接内存访问,被用于内存和内存之间或内存和外设之间的高速数据传输。数据传输可以在没有CPU的干预下快速移动,这样可以保持CPU资源处理其他事情
4 J$ |3 g" X. ~$ R2 \
% N1 Y" C& r% p8 E! E: ^DMA 控制器基于复杂的总线矩阵架构,将功能强大的双 AHB 主总线架构与独立的 FIFO 结
) E5 `7 _/ |# S0 A) T$ d9 D6 a7 c/ V7 ?
" I8 v# b! F" z- I% b8 C/ [合在一起,优化了系统带宽,下图①处,可以看出双 AHB 主总线架构与独立的 FIFO的结构; j& c$ n2 V4 m
$ N/ ~6 b$ c2 e: m1 Q
20200804222700423.png ' ~+ U0 J4 o3 B/ A7 d
; Z0 ^7 M7 j% M! m& U
注意看英文备注:  Z7 I, _% D2 C, E

. g2 _* L, p9 m% jDMA1控制器AHB外设端口没有像DMA2一样连接到总线矩阵,所以只有DMA2数据流可以执行存储器到存储器的传输3 X7 V! h+ J  W# o7 w

' y' j+ z( N/ c5 }" R8 H  @' V我们对上图的②处,(DMA1和DMA2结构一样,我们就选择DMA1)详细看; p9 |1 b/ Y) n$ J; u& h

0 S/ E8 l# X' _  Q: w2 ] 20200804222726518.png
$ o* ~5 I7 D1 W# V
: f6 l# _/ ^, D7 O3 y; D①每个数据流总共可以有多达 8 个通道(或称请求)4 I: V, b& w' I6 g1 s; d) ~

% q+ K" T. d  b* d, H②DMA1共有8个数据数据流(两个DMA共有16个数据流)
9 t$ f% ?( Z: x+ i
/ K, i) H- N0 J( y' l9 s* ]0 S③每个DMA都有数据流仲裁器,用于处理 DMA 请求间的优先级
8 z, ?, L  `3 ~/ H0 ~+ S9 ?  G' s3 V" S+ C
④DMA的数据流又有独立的FIFO
% H/ r" X; B) Y* U% p, k, B/ h0 |) G/ J
⑤DMA采用双 AHB 主总线架构& L* D& t6 }$ S8 u0 n) ^
# U$ a# T* \, }1 N  V6 z
备注:  |: ]; C5 f4 f. T8 r. R
; X; d& v2 V' `/ w. x9 o: y  t) V
①处是选择器,配置完成只能选择一个通道,而③处是仲裁器,也就是说,配置完成,可能8个数据流全部存在,由仲裁器判断优先级8 ]/ R# V% d5 y% e" j+ M! Q
- y( J" [7 S% _& e) Y* Q6 U7 h
2、DMA事务2 Y2 X+ ^" p' `8 ?) u4 I
DMA从传输事务包含一系列的给定数目的数据传输序列。传输的数目可以通过软件编程,8位,16位或32位。
% Y1 m% ^7 y0 J. ~% F! p; C
! U( K- }5 @" [) g. I每一次DMA传输包含3个操作
+ D& f* g1 I+ v  O& W通过 DMA_SxPAR 或 DMA_SxM0AR 寄存器寻址,从外设数据寄存器或存储器单元中加载数据。: P! T# k* P0 a  d4 e
通过 DMA_SxPAR 或 DMA_SxM0AR 寄存器寻址,将加载的数据存储到外设数据寄存器或存储器单元
! `- }* \# {* d  l3 M( `2 a$ jDMA_SxNDTR 计数器在数据存储结束后递减,该计数器中包含仍需执行的事务数
. l* K6 }! m9 `4 \& d: v在产生事件后,外设会向 DMA 控制器发送请求信号。 DMA 控制器根据通道优先级处理该请求。只要 DMA 控制器访问外设, DMA 控制器就会向外设发送确认信号。外设获得 DMA 控制器的确认信号后,便会立即释放其请求。一旦外设使请求失效, DMA 控制器就会释放确认信号。如果有更多请求,外设可以启动下一个事务
& a+ Z1 W4 Q) |$ Y! k' E$ U" `7 M! D( w1 h$ M! U; f
3、通道选择
5 H" y4 q/ E* ?" Z每个数据流可以有8个通道  J- w7 a' f) E1 w8 s, f
7 H6 G4 ?  m4 M4 x; s# s2 B
20200804222752389.png . M: B1 r& @+ i5 A
  x9 b- t$ q3 F/ W5 C/ V, ~  p5 A
通过上图①可以看出,通道选择仲裁器可以通过DMA_SxCR寄存器的CHSEL[2:0]配置7 g# S2 F$ y, c2 A6 ?- W

! k+ K, ?2 D8 \3 J; BDMA的请求可以来自TIM,ADC,SPI等外设
) R1 G: g4 T8 r! d4 F0 g0 w( H" s9 A+ P/ q" q! \3 ]
DMA1的请求通道
4 o  W+ a1 O% D- w
, ~3 y: }" I2 G5 J0 _, \ 20200804222816147.png + d' A; `8 Z4 x  I! X$ w2 M3 x& r

: a$ D& S+ C3 S% k/ D+ D1 E3 J6 s! dDMA2的请求通道
1 M1 ~/ ~( h5 V" v( R; ~& @1 m; l% }9 j
, C) V. [: _$ |% G+ D* Q( u 20200804222838496.png
6 v) s4 k7 T9 y2 p$ H3 E/ u, @  u
4、仲裁器# S- \# W, z3 _" Y8 ~+ i3 r
仲裁器为两个 AHB 主端口(存储器和外设端口)提供基于请求优先级的 8 个 DMA 数据流请求管理,并启动外设/存储器访问序列。
! p7 {0 t) r# R: ]6 Y! U) X3 ~' }0 @7 U
优先级管理分为两个阶段
1 [$ w: t1 V2 X/ c2 j软件:每个数据流优先级都可以在 DMA_SxCR 寄存器中配置。分为四个级别:非常高优先级、高优先级、中优先级、低优先级
" ~4 k" W: y- i+ l硬件:如果两个请求具有相同的软件优先级,则编号低的数据流优先于编号高的数据流。例如,数据流 2 的优先级高于数据流 4
& `8 R" _3 y# B6 t+ _3 M
9 ]2 U2 ?: i$ x# ^0 x5、DMA数据流6 ^% O( k- t( e% V: R6 N2 `$ V; @
8个DMA控制器数据流都能够提供源和目标之间的单向传输链路
7 n4 {2 ?9 t( \+ k/ ^% S9 g
, r, g# J! I2 O7 X, Z每个数据流配置后都可以执行% l+ H! l4 ]! t1 T
常规类型事务:存储器到外设、外设到存储器或存储器到存储器的传输: J( O: E/ d) v/ B. v
双缓冲区类型事务:使用存储器的两个存储器指针的双缓冲区传输(当 DMA 正在进行自/至缓冲区的读/写操作时,应用程序可以进行至/自其它缓冲区的写/读操作)
: o; J! ~8 @( M% f! [
1 c% O* A6 s3 t' y) y要传输的数据量(多达 65535)可以编程,并与连接到外设 AHB 端口的外设(请求 DMA 传输)的源宽度相关。每个事务完成后,包含要传输的数据项总量的寄存器都会递减。+ q( @7 c$ {& c0 q4 m: L

3 a" t2 \" I- z! H" W6、源、目标和传输模式
6 i/ Y, g, ]& ?9 Q源地址和目标地址可以在整个4G地址空间,在0x00000000和0xFFFFFFFF之间
' N. c* C, j# }1 L
* v6 m, L# Q1 b9 d/ m% O在DNA_SxCR寄存求的DIR[1:0]配置DMA的传输方式
) l( y3 e  n% M1 d1 J7 P6 n) P7 A* M4 {. T. ^
20200804223130296.png ' v) O  R( X/ M; ]& ^: a

6 k+ r/ t2 a4 U& L! {源地址和目标地址的关系, [" R9 |* \; l$ \8 Z6 E
( f  I; e/ H5 M: T( X
20200804223256817.png
5 t* E* d0 f  l- _) q# ^$ d% @  n0 k9 U8 _* `, f
当数据宽度是半字或字时,外设地址或存储器地址必须是半字或字对齐
2 c/ I, \; r: r3 Z# {
  ?' |* c1 H4 R6.1、外设到存储器模式, R5 X0 _+ v% a- y3 k
当配置成外设到存储器的DMA传输模式时,两种模式
( A* P6 {5 q# v" {, g/ ~( X5 G" Y
FIFO模式:外设有DMA请求(TIM溢出,PWM下降沿等)时,DMA会搬运源数据(外设数据)到FIFO,当FIFO满时,将数传输给目标地址(内存)& J( I* c  G% y* L7 @
直连模式:配置直连模式,DMA_SxFCR 寄存器中的 DMDIS 值为“0”。不使用 FIFO 的阈值级别控制:每完成一次从外设到 FIFO 的数据传输后,相应的数据立即就会移出并存储到目标中。6 q4 t$ W4 L! Q. L

- j# ], L# F& n8 {$ m- [ 20200804223458815.png
* m( }0 _  K7 W2 G  T" [
9 a, J( X9 w2 }; r$ \  I! T, e传输开始条件,使能数据流(DMA_SxCR 寄存器中的位 EN 置 1),然后外设发出请求,再然后该请求赢得了数据流仲裁,才会开始传输。
3 n6 P0 f8 S6 T& e$ q$ t" m( u5 L8 z# t/ ^% F
传输停止条件,下列满足一条即可1 y5 i/ r1 j% C- d+ w1 Y
DMA_SxNDTR 寄存器达到零
' W( N& k9 \0 B$ b外设请求传输终止& t/ s) S. x5 ?# [  ^! [
DMA_SxCR 寄存器中的 EN 位由软件清零" X7 x% @8 ~  ~% [
9 k" }# M- e: s2 O, g
6.2 存储器到外设模式
3 N/ J! A+ u9 y$ Z9 {3 s% s% [FIFO模式. v0 a8 v+ p9 ?- |: T
这种模式,只要使能数据流(DMA_SxCR 寄存器中的位 EN 置 1),存储器数据就会传输到FIFO中,发生外设请求,FIFO数据会移出并存储到目标地址。当FIFO小于阈值,存储器的数据会重载FIFO。
9 W; _( p% K2 K3 t0 i( v, V' X
9 m1 c, H  L+ D8 }' U4 s2 q直连模式5 V' J/ u( A5 Z& Q
使能数据流时,DMA传输存储器的第一个数据到内部FIFO,发生外设请求时,DMA把预装在值发送的目标地址,然后进行下一个数据的传输。预装载的数据大小为 DMA_SxCR 寄存器中 PSIZE 位字段的值# b" O+ R" X5 G" j  i0 h. `" N

6 _* Y1 Y- ~, `8 N传输停止条件,下列满足一条即可/ u7 G5 X4 i& ~, i; c+ ]" a
DMA_SxNDTR 寄存器达到零
# f# G% b/ _" B3 ?外设请求传输终止
9 a$ a5 C% {7 ADMA_SxCR 寄存器中的 EN 位由软件清零! e: J/ z+ ?# f0 h; u4 U  |0 E( L

  M; H& ^4 W: E6 w存储器到外设模式和外设到存储器模式一样,同样需要对应数据流赢得仲裁,才会启动传输5 I  S) O5 B0 f9 i: C/ u) N: E
' U5 o* ~0 O) s7 H: K; I
20200804223640404.png
5 G# h4 K3 C$ F, Y7 M- c( U& T! J4 A
  {* U1 ^6 _) ~3 d) k6.3 存储器到存储器模式
6 \4 A1 f2 k, V$ S这种模式较为简单,没有外设请求
3 f+ G! s2 c" K% L, f* J# |
4 Z4 o; z$ x9 a( t0 B启动传输- a; s8 M$ _6 d1 M2 O
9 x& |; A4 p4 U* |5 o
DMA_SxCR 寄存器中的使能位 (EN) 置 1 来使能数据流时,数据就会从源地址传输到FIFO,到达FIFO阈值时,FIFO数据移出到目标地址( n3 ]' X+ E, p( C7 ?) y
7 \0 S8 p+ X7 Z+ D( b
停止传输,下列满足一条即可5 A! Z0 }/ z* \% b$ u9 e# t
DMA_SxNDTR 寄存器达到零
' o. D% d+ E  E1 M) Q; EDMA_SxCR 寄存器中的 EN 位由软件清零: ^( X+ q/ ]# U1 |' Y- X
5 P- c- s/ i+ H5 ?# j8 g' \
当然,同样该数据流需要赢得仲裁4 F/ l5 u- y0 O; c: @4 R
" Q$ y7 Z6 p) `) g8 R
2020080422371572.png / f0 L( E' {# v7 F

8 `. a8 a4 W9 M* u6 X" X. ]0 [7、指针递增
* m1 {$ J& K. o; d/ i0 i外设和存储器指针在每次传输后自动向后递增或保持常量,根据DMA_SxCR寄存器的PINC和MINC位。8 i* |3 H" ]. p/ v+ h

: n6 ~6 Y& K/ X/ J" P9 {禁止递增模式时非常有用的,当外设源和目标数据是通过单个寄存器访问的
0 W8 D& t5 n# d8 d2 m# N, d$ R* |1 C8 x6 [* w
如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1(对于字节)、 2(对于半字)或 4(对于字)3 i# f# N. b: L7 R3 e1 X
. _2 v  {2 f7 F6 {7 a. {
为了优化封装操作,可以不管 AHB 外设端口上传输的数据的大小,将外设地址的增量偏移大小固定下来。 DMA_SxCR 寄存器中的 PINCOS 位用于将增量偏移大小与外设 AHB 端口或32 位地址(此时地址递增 4)上的数据大小对齐。 PINCOS 位仅对 AHB 外设端口有影响。
5 ?( N/ @" l& h5 g
" V8 @7 F: F8 z" Q6 [$ ^如果将 PINCOS 位置 1,则不论 PSIZE 值是多少,下一次传输的地址总是前一次传输的地址递增 4(自动与 32 位地址对齐) 。但是, AHB 存储器端口不受此操作影响。, u- j" o1 h: I9 ]5 o% B

3 @  e3 {' Z6 _* |$ u如果 AHB 外设端口或 AHB 存储器端口分别请求突发事务,为了满足 AMBA 协议(在固定地址模式下不允许突发事务),则需要将 PINC 或 MINC 位置 1。
  m, r  o! V8 A/ n
+ v; \+ @- |: @/ z) R; G3 x8、循环模式% R6 F- x3 p4 g
循环模式可用于处理循环缓冲区和连续数据流(例如 ADC 扫描模式)。可以使用 DMA_SxCR寄存器中的 CIRC 位使能此特性。
+ ~# N3 V/ e0 x% Q
, L7 w! r! q8 ^* B# A当激活循环模式时,要传输的数据项的数目在数据流配置阶段自动用设置的初始值进行加载,并继续响应 DMA 请求。
9 B& e# j, _* d( O0 N# F0 J. X6 _9 A  ]) N( G( u
也就是说,比如我们要从内存中采集 64 个字节发送到串口,如果设置为重复采集,那么它会在 64 个字节采集完成之后继续从内存的第一个地址采集,如此循环。这里我们设置为一次连续采集完成之后不循环。所以设置值为 DMA_Mode_Normal。在我们下面的实验中,如果设置此参数为循环采集,那么你会看到串口不停的打印数据,不会中断,: e. b4 a3 c$ e+ g; N
6 b# \: u) U7 [/ |' I& H* C3 o' K
9、双缓冲模式' |- P8 e) ~7 H) m$ }" E- n
此模式可用于所有 DMA1 和 DMA2 数据流。, z1 h' y( S7 x+ ^$ o3 G

' c; N) O% J8 ~9 j4 p通过将 DMA_SxCR 寄存器中的 DBM 位置 1,即可使能双缓冲区模式。
- v+ M% x% I9 r) |2 }& x: h4 t$ J4 Z& ^/ n& U9 E" z" S
除了有两个存储器指针之外,双缓冲区数据流的工作方式与常规(单缓冲区)数据流的一样。使能双缓冲区模式时,将自动使能循环模式( DMA_SxCR 中的 CIRC 位的状态是“无关”),并在每次事务结束时交换存储器指针。  {& R/ g& J) }( y2 d4 d
* g0 @# Z& E0 V4 b$ a4 I  u
在此模式下,每次事务结束时, DMA 控制器都从一个存储器目标交换为另一个存储器目标。这样,软件在处理一个存储器区域的同时, DMA 传输还可以填充/使用第二个存储器区域
/ a5 I! f+ \7 e6 ^( W7 F
* Z# X3 t: K: G基于DMA双缓冲模式的的特点,应用中必须开辟两个存储区以及存放两个存储区首地址的存储寄存器,DMA_SxM0AR和DMA_SxM1AR。
4 M, Q) ~3 C3 K% s: F  }+ C+ ?) s" ?# S
1:DMA_SxM0AR:指向存储区0(DMA_Memory_0),单缓冲模式下默认使用该寄存器做存储区指针。
2 E, ~3 s: u- J4 W7 _
# M' J% H. y9 G6 [8 j) N2:DMA_SxM1AR:指向存储区1(DMA_Memory_1),仅在DMA双缓冲模式下才能使用。) p) a3 t3 J% h3 s
/ p4 Z7 P, n2 j* k4 k
3:DMA正在访问的当前存储区由DMA_SxCR表示% I  ]  q: N2 m: s6 X

& Y! q' D% y1 Z" W1 Z3 qCT:当前目标
) q  h- E4 M5 t7 ?8 d8 i
% e: _9 A; X' y8 L. g7 a9 BCT = 0:DMA正在访问存储区0,CPU可以访问存储区1
; Q+ f# x. H; C2 @+ A& o- X1 a6 P( Y3 Z/ L  F
CT = 1:DMA正在访问存储区1,CPU可以访问存储区05 \+ p" N$ e) A8 j8 M: [! Y  C

* ?; \( W4 ~* L4 p! v- _, } 20200804223753415.png $ y6 ~& ^3 F1 H8 @$ f4 T, V0 R
. j& l) B+ y+ U
优点:
/ V; E5 |' \. j% x8 J% d4 C4 Q  W5 B5 g
使用DMA双缓冲传输,既可以减少CPU的负荷,又能最大程度地实现DMA数据传输和CPU数据处理互不打扰又互不耽搁,DMA双缓冲模式的循环特性,使用它对存储区的空间容量要求也会大大降低。尤其在大批量数据传送时,你只需开辟两个合适大小的存储区,能满足DMA在切换存储区时的当前新存储区空出来就好,并不一定要开辟多大多深的存储空间,单纯一味地加大双缓冲区的深度并不明显改善数据传输状况
* i# x0 J6 @: b) |8 E6 U9 a6 ~' N
0 b- s& u$ H5 O- i$ w1 T0 {# z10、可编程数据宽度、封装/解封、字节顺序
+ U2 k7 u8 d; s6 \要传输的数据项数目必须在使能数据流之前编程到 DMA_SxNDTR(要传输数据项数目位,NDT)中,当流控制器是外设且 DMA_SxCR 中的 PFCTRL 位置为 1 时除外。
' Y& B5 D0 e& }; ~' s: i! N% m- R; U' a& t, ~& h
当使用内部 FIFO 时,源和目标数据的数据宽度可以通过 DMA_SxCR 寄存器的 PSIZE 和MSIZE 位(可以是 8、 16 或32 位)编程3 K! Z2 n% t3 Y' I1 {
# u% X/ k4 v% W9 k
11、单次传输和突发传输' I& Y' j# M! X6 i
DMA控制器可以产生一个单次传输或者4、8或16节拍的突发传输/ z( M8 _$ j# h! V! d/ `9 w

' p; ~( W, ?5 Z5 t5 z; N% s突发大小通过软件针对两个 AHB 端口独立配置,配置时使用 DMA_SxCR 寄存器中的MBURST[1:0] 和 PBURST[1:0] 位
% Q$ Y. T: y( t7 ~
& d+ b$ \5 H( S( r/ z8 A" [7 E突发大小指示突发中的节拍数,而不是传输的字节数。+ T. A3 `. g6 O! I$ i$ s4 f
; {: u* t1 z0 f; I4 ]
为确保数据一致性,形成突发的每一组传输都不可分割:在突发传输序列期间, AHB 传输会锁定,并且 AHB 总线矩阵的仲裁器不解除对 DMA 主总线的授权。# ^: j( U% ^: {7 z/ i+ a9 j

9 U0 F7 Q1 Y9 [$ G7 n$ X# [" U根据单次或突发配置的情况,每个 DMA 请求在 AHB 外设端口上相应地启动不同数量的传输
3 m$ ^" U5 }4 y: I' ]& G3 i5 g2 |* K) o: W% z3 J. j
当 AHB 外设端口被配置为单次传输时,根据 DMA_SxCR 寄存器 PSIZE[1:0] 位的值,每个 DMA 请求产生一次字节、半字或字的数据传输
; [% c  e/ [) O) z+ g7 G2 J- E5 p2 j当 AHB 外设端口被配置为突发传输时,根据 DMA_SxCR 寄存器 PBURST[1:0] 和PSIZE[1:0] 位的值,每个 DMA 请求相应地生成 4 个、 8 个或 16 个节拍的字节、半字或字的传输+ Y* [, L6 G% d

; w: w. z! k' u$ T对于需要配置 MBURST 和 MSIZE 位的 AHB 存储器端口,必须考虑与上述相同的内容。在直接模式下,数据流只能生成单次传输,而 MBURST[1:0] 和 PBURST[1:0] 位由硬件强制配置。/ N, y8 W) z; W
* u" J  {' h7 J, Z
必须选择地址指针(DMA_SxPAR 或 DMA_SxM0AR 寄存器),以确保一个突发块内的所有传输在等于传输大小的地址边界对齐
3 y/ H6 M1 g* G: G- `9 d- V& U
2 B2 X2 `# e, @0 U! {7 G  O% y选择突发配置必须要遵守 AHB 协议,即突发传输不得越过 1 KB 地址边界,因为可以分配给单个从设备的最小地址空间是 1 KB。这意味着突发块传输不应越过 1 KB 地址边界,否则就会产生一个 AHB 错误,并且 DMA 寄存器不会报告这个错误。
9 T) o( U& N9 U5 }) G& Q( Y
) f7 S. {4 A1 R: [1 I12、FIFO
2 F6 h/ N# _7 n1 z  S+ YFIFO结构; a8 j6 ^1 |) j2 ~- j

; ?7 O! e& l3 [; ]: ~FIFO是用来临时存储从源地址传来的数据,在这些数据被发送到目的地市之前。4 T3 e% o( [5 @% u
3 m6 V: a5 `8 ?/ Z
每个数据流都有独立的4字FIFO,他们可以被软件配置为1/4、1/2、3/4或满' c7 R9 {9 T+ b5 V" R! G
4 `! s) K$ Q3 K) L  u
使用FIFO阈值,必须禁止直接模式
! q2 A1 ~- P$ [7 P/ @! j4 v  d6 V( D+ N0 |5 @* f
下图是FIFO结构和数据源、阈值关系的示意图
" f) E; s6 G1 M
* ?! j2 ~: `' ]+ o# R& h- L 20200804223825101.png
$ @! i  R; q; A2 K7 m7 r0 L4 i% [: J# z4 a* @  T4 I
FIFO阈值和突发设置
1 y/ H! \- q; y( c* C* Q
& `  f5 r% [* u警告被要求,选择 FIFO 阈值(DMA_SxFCR 寄存器的位 FTH[1:0])和存储器突发大(DMA_SxCR 寄存器的 MBURST[1:0] 位):FIFO 阈值指向的内容必须与整数个存储器突发传输完全匹配。如果不是这样,当使能数据流时将生成一个 FIFO 错误( DMA_HISR 或 DMA_LISR寄存器的标志 FEIFx),然后将自动禁止数据流" U$ k7 J8 V3 l% _' ~0 l# y: `
' ]; s7 p8 E' q
20200804223848517.png
0 b8 [! Z1 i  ~7 q1 M6 r5 {4 h3 m, _1 }9 g% w
FIFO更新
4 m( l( k( m3 Z  o4 I* y6 v8 M
$ V! Z" a+ F$ \- R+ O) R, a9 GFIFO可以被更新,当数据流被禁止通过写入DMA_SxCR寄存器的EN位和当数据被配置成外设到存储器或存储区到存储区模式:如果禁止数据流时仍有某些数据存留在FIFO 中, DMA 控制器会将剩余的数据继续传输到目标(即使已经有效禁止了数据流)。刷新完成时,会将 DMA_LISR 或 DMA_HISR 寄存器中的传输完成状态位 (TCIFx) 置 1。
1 z: C- V4 r/ Z; h, I( H8 _; z9 E
' [' [$ @8 r' W在这种情况下,剩余数据计数器 DMA_SxNDTR 保持的值指示在目标存储器现有多少可用数据项。2 r& Y, v$ ]$ n& s! }

5 x$ e: f. }- L6 L直接模式5 d$ t9 M- s2 u3 J4 L( d7 G
5 `9 m" U+ m# M1 m7 d, ~
默认情况下, FIFO 以直接模式操作(将 DMA_SxFCR 中的 DMDIS 位置 1),不使用 FIFO阈值级别。如果在每次 DMA 请求之后,系统需要至/自存储器的立即和单独传输,这种模式非常有用。9 m  p, T$ w0 \
& i' i& N3 C1 i6 l9 }3 [* z
当在直接模式(禁止 FIFO)下将 DMA 配置为以存储器到外设模式传输数据时, DMA 会将一个数据从存储器预加载到内部 FIFO,从而确保一旦外设触发 DMA 请求时则立即传输数据9 G! z$ W5 h0 J9 e( q5 b
  W( E4 q- o0 @; p$ C5 A3 e
13、DMA传输完成
/ v! A. C$ z& A  x2 p) I# |$ E以下各种事件均可以结束传输过程,并将 DMA_LISR 或 DMA_HISR 状态寄存器中的 TCIFx位置 1
7 Z4 _) r% J) ~# S+ m5 z6 F. C
在 DMA 流控制器模式下:①在存储器到外设模式下, DMA_SxNDTR 计数器已达到零,②传输结束前禁止了数据流(通过将 DMA_SxCR 寄存器中的 EN 位清零),并在传输是外设到存储器或存储器到存储器的模式时,所有的剩余数据均已从 FIFO 刷新到存储器+ l5 t8 }$ C1 x6 s$ g* q
在外设流控制器模式下:①已从外设生成最后的外部突发请求或单独请求,并当 DMA 在外设到存储器模式下工作时,剩余数据已从 FIFO 传输到存储器②数据流由软件禁止,并当 DMA 在外设到存储器模式下工作时,剩余数据已从 FIFO传输到存储器
! o9 d9 Y! U4 n- ^6 R$ T1 |+ U8 Z+ b
14、DMA传输暂停
$ e& u  _3 `8 x: G& [可以随时暂停 DMA 传输以供稍后重新开始;也可以在 DMA 传输结束前明确禁止暂停功能,分两种情况
& S' I0 U9 o5 N
6 {: i" O/ n' R数据流禁止传输,以后不从停止点重新开始暂停。这种情况下,只需将 DMA_SxCR 寄存器中的 EN 位清零来禁止数据流,除此之外不需要任何其他操作。禁止数据流可能要花费一些时间(需要首先完成正在进行的传输)。需要将传输完成中断标志(DMA_LISR 或DMA_HISR 寄存器中的 TCIF)置 1 来指示传输结束。现在 DMA_SxCR 中的 EN 位的值是“0”,借此确认数据流已经终止传输。 DMA_SxNDTR 寄存器包含数据流停止时剩余数据项的数目,这样软件便可以确定数据流中断前已传输了多少数据项。/ I, n' `3 p3 f: I4 _- \# c" |

7 E( B3 T# h1 T5 b数据流在 DMA_SxNDTR 寄存器中要传输的剩余数据项数目达到 0 之前暂停传输。目的是以后通过重新使能数据流重新开始传输。为了在传输停止点重新开始传输,软件必须在通过写入 DMA_SxCR 寄存器中的 EN 位(然后检查确认该位为‘0’)禁止数据流之后,首先读写入DMA_SxNDTR 寄存器来了解已经收集的数据项的数目。然后①必须更新外设和/或存储器地址以调整地址指针②必须使用要传输的剩余数据项的数目(禁止数据流时读取的值)更新 SxNDTR 寄存器③然后可以重新使能数据流,从停止点重新开始传输' m& j& ?  Z) W1 M
$ p4 `- |( D* Q$ c; u) X
15、流控制器: c& q7 C7 ^6 x( V# {5 R
控制要传输的数据数目的实体称为流控制器。此流控制器使用 DMA_SxCR 寄存器中的PFCTRL 位针对每个数据流独立配置
6 F+ M# x: y# d3 C) Q6 U
  U8 k. T) P2 @# G- B流控制器可以是:
4 ?/ u  G) S# m* ]9 d  b3 g
0 u$ `6 j) e2 ?& f& j7 i2 zDMA 控制器:在这种情况下,要传输的数据项的数目在使能 DMA 数据流之前由软件编程到 DMA_SxNDTR 寄存器
& S4 D& u5 Z3 v* N
! t4 B  {. c0 w) }外设源或目标:当要传输的数据项的数目未知时属于这种情况。当所传输的是最后的数据时,外设通过硬件向 DMA 控制器发出指示。仅限能够发出传输结束信号的外设支持此功能,也就是SDIO
, u2 ]0 y) @( q, x3 i+ `: q7 _: \; |6 ~. _
16、流配置过程
9 R. F4 H- N' J5 O配置 DMA 数据流 x(其中 x 是数据流编号)时应遵守下面的顺序
$ ~. n- O  A$ i' l& O: i$ P9 o( g/ u  q3 x
1.如果使能了数据流,通过重置 DMA_SxCR 寄存器中的 EN 位将其禁止,然后读取此位以确认没有正在进行的数据流操作。将此位写为 0 不会立即生效,因为实际上只有所有当前传输都已完成时才会将其写为 0。 当所读取 EN 位的值为 0 时,才表示可以配置数据流。因此在开始任何数据流配置之前,需要等待 EN 位置 0。应将先前的数据块 DMA传输中在状态寄存器(DMA_LISR 和 DMA_HISR)中置 1 的所有数据流专用的位置 0,然后才可重新使能数据流2 \  N# p' p  W3 D+ ?
2.在 DMA_SxPAR 寄存器中设置外设端口寄存器地址。外设事件发生后,数据会从此地址移动到外设端口或从外设端口移动到此地址
7 a6 ]& i- w! w! G2 l3.在 DMA_SxMA0R 寄存器(在双缓冲区模式的情况下还有 DMA_SxMA1R 寄存器)中设置存储器地址。外设事件发生后,将从此存储器读取数据或将数据写入此存储器
2 F' ]# I! o% r" l/ \, p4 p2 j4.在 DMA_SxNDTR 寄存器中配置要传输的数据项的总数。每出现一次外设事件或每出现一个节拍的突发传输,该值都会递减* j( S! s9 x% ?
5.使用 DMA_SxCR 寄存器中的 CHSEL[2:0] 选择 DMA 通道(请求)
" p- R& Z. X4 c5 |) S% ]+ B3 q8 \* O6.如果外设用作流控制器而且支持此功能,请将 DMA_SxCR 寄存器中的 PFCTRL 位置 1* ?9 `; d  d. l+ V8 k5 D$ W4 a
7.使用 DMA_SxCR 寄存器中的 PL[1:0] 位配置数据流优先级
4 \5 e2 D( y' j8.配置 FIFO 的使用情况(使能或禁止,发送和接收阈值)2 W+ \. v- n- ?% Q7 n
9.配置数据传输方向、外设和存储器增量 / 固定模式、单独或突发事务、外设和存储器数据宽度、循环模式、双缓冲区模式和传输完成一半和/或全部完成,和/或 DMA_SxCR寄存器中错误的中断
7 H) A, j4 ]$ V: M! j4 [10.通过将 DMA_SxCR 寄存器中的 EN 位置 1 激活数据流
+ r( x/ R" v, D: j: _4 a* E9 A& H4 n
0 o6 p; I/ h4 ?4 c; }一旦使能了流,即可响应连接到数据流的外设发出的任何 DMA 请求。
6 N& s7 \8 c! D7 L# U1 @/ i4 }$ |8 L5 z2 r) A- g: r
一旦在 AHB 目标端口上传输了一半数据,传输一半标志 (HTIF) 便会置 1,如果传输一半中断使能位 (HTIE) 置 1,还会生成中断。传输结束时,传输完成标志 (TCIF) 便会置 1,如果传输完成中断使能位 (TCIE) 置 1,还会生成中断。  g  W: q9 y( d' {

; ^6 C4 r8 \$ O4 x5 T0 p9 _17、中断' k4 l. t- ]5 g9 `# N; B! Q
对于每个 DMA 数据流,可在发生以下事件时产生中断
0 d  L5 ~5 y" O* P7 J0 d1 ~9 D
2 C) P" w' H/ Z; d" G3 J传输一半时) b" G2 f4 d1 o3 J
传输完成时
, _! i3 e6 C9 a6 Y. V传输错误时2 N, S3 T( s' J; B& w6 G5 M
FIFO错误(溢出,下溢或FIFO等级错误)
0 B2 z+ p( x# S" Q! e直接模式错误& Z" B3 _! ?1 `4 T9 [
* E7 x1 X% a  O( a" @; l, [
中断列表! g9 Y& {  Z3 M& s7 u0 w7 |' t! ~
8 s& b* U& C/ v: i6 V
20200804223916639.png
) l% v& B& g  p/ I+ ^9 v/ h% a: M) z% j, \, Y- R" Z% B
18、代码配置
3 R( L- m* n  H配置代码
9 {9 a' o) m, f, X/ F4 O4 T2 Q, T* K" w7 ^
  1. /* Configure DMA Stream */& O$ w& P8 v; J7 w' H9 K' p
  2. DMA_InitStructure.DMA_Channel = DMA_Channel_0;* b( {+ r+ y+ i
  3. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;4 k3 K7 L1 S( n% K% g
  4. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DST_Buffer;
    9 e- C- O, q/ N6 i1 |' t
  5. DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;' Z& o% I: [, q6 _
  6. DMA_InitStructure.DMA_BufferSize = (uint32_t)32;- e7 n* ~* U$ c* E' r# n
  7. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
    $ N$ j8 Q! A: @: e$ `. [! A- o
  8. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;$ ?6 f" D/ k/ `! R' o
  9. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;& @9 ?7 L6 J7 ~; ]% J' M$ P
  10. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    & X# \9 p3 D  I4 O  s. q
  11. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;8 B" p+ j6 I" X9 T
  12. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    * E/ }0 q$ P; X+ T0 g3 {* q
  13. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;.         
    . d8 l2 H5 k: j: Z' ]$ d
  14. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;0 ^# H: |& [" ]! O  j! C
  15. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;6 A3 |1 ^: _% b$ H
  16. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;1 Z* k- U, R; {5 G
  17. DMA_Init(DMA2_Stream0, &DMA_InitStructure);
复制代码

$ ?/ [  N1 s2 N3 D4 f$ F# lDMA_Channel :2 A9 E* x% Q/ \5 ?  a2 e% G8 ^8 h

% K" g$ W# m6 S设置 DMA 数据流对应的通道,供每个数据流选择的通道请求多达 8 个,取值有
- k' N3 Q4 Z+ q# h
# e& g3 E% G8 w& i; ~% R% V; |. u7 X
  1. #define DMA_Channel_0                     ((uint32_t)0x00000000)
    3 }- Z; ~: _+ ?, ?9 a) y
  2. #define DMA_Channel_1                     ((uint32_t)0x02000000)
    / h3 z. S* k  _6 {1 D7 @
  3. #define DMA_Channel_2                     ((uint32_t)0x04000000)
    5 i$ E+ M- O3 m  ~2 P/ g- O
  4. #define DMA_Channel_3                     ((uint32_t)0x06000000)
    6 R+ _  M! a1 A9 N9 }& Q
  5. #define DMA_Channel_4                     ((uint32_t)0x08000000)# k2 V  E$ e" u; S0 w
  6. #define DMA_Channel_5                     ((uint32_t)0x0A000000)
    - ~6 p9 m6 Q1 s9 v
  7. #define DMA_Channel_6                     ((uint32_t)0x0C000000)& p4 ?8 D+ d1 G# u  @# b* A
  8. #define DMA_Channel_7                     ((uint32_t)0x0E000000)
复制代码

7 [- K; U9 K1 wDMA_PeripheralBaseAddr :
: g0 m9 g& ]* c' R3 I- V! Y; k! ]( W1 O5 E" d' i$ p
DMA 传输的外设基地址,假设进行uart1串口DMA 传输,我们可以按照寄存器的地址偏移直接设置地址:0x40011004,也可以直接使用ST提供库的表示方法:&USART1->DR
- K8 {- g; c! ]2 u  `8 x  K' B/ w, L. Z, o
DMA_Memory0BaseAddr :$ [1 P& M0 {8 O+ L" X
, m$ L* H2 \4 }2 b6 E( S
DMA 传输的内存基地址) q9 a( v- {3 b& b& b
: Z6 R8 W) o5 V! D3 ?% o- w* N
DMA_DIR:
  G6 Z/ R0 j% G$ Y
! p4 r' F8 i0 X' |, o1 R7 [设置数据传输方向,有存储器到存储器,存储器到外设,外设到存储器三种选择,取值有:
  1. #define DMA_DIR_PeripheralToMemory     ((uint32_t)0x00000000) 0 G9 l2 j6 O( n3 M/ N
  2. #define DMA_DIR_MemoryToPeripheral     ((uint32_t)0x00000040)
    ) `+ [: c0 ?* _6 u" d6 {
  3. #define DMA_DIR_MemoryToMemory         ((uint32_t)0x00000080)
复制代码
# ?) j& t  q, M6 ^- s( @. ?
DMA_BufferSize:
0 }! L! a) l6 l0 m8 u- J. o
0 |6 f, c. p# J3 I$ A设置一次传输数据量的大小
$ z' Z# n: S- `& W1 V, J( Q0 i, o7 a
DMA_PeripheralInc:
; p$ y+ G8 q  K+ J+ }, e: ?7 V) E0 y* X' c
设置传输数据的时候外设地址是不变还是递增,如果设置为递增,那么下一次传输的时候地址加 1,取值有:, V0 y1 U  |  c& W6 U$ I: w

  1. ; W5 m! `5 ~  m# A" N
  2. #define DMA_PeripheralInc_Enable      ((uint32_t)0x00000200) + N. |' o9 a2 p% I# ~! [
  3. #define DMA_PeripheralInc_Disable     ((uint32_t)0x00000000)
复制代码
/ n9 F/ R1 S8 f2 y  ]+ d, W) m3 v
DMA_MemoryInc:
8 ?* c) `' e7 K% B! J8 J& @0 n
5 @, q1 E/ Q0 E; U2 p, r8 n4 J7 H设置传输数据时 候内存地址 是否递增。 这个参数和DMA_PeripheralInc 意思接近,只不过针对的是内存(存储器),取值有:
2 B" K4 n. M6 s4 ^% `; Z) ]. |0 G3 F; y5 b! A" ~. T/ N  K
  1. #define DMA_MemoryInc_Enable      ((uint32_t)0x00000400)
    6 ^% m3 Y2 [& c' @* H
  2. #define DMA_MemoryInc_Disable     ((uint32_t)0x00000000)
复制代码

9 F9 `8 u9 C/ y7 y* j# ?& K4 ~DMA_PeripheralDataSize:
' b' |* t6 R7 R5 h
+ I* {' x+ y9 ?设置外设的数据长度是为字节传输(8bits),半字 传 输 (16bits) 还 是 字 传 输 (32bits),取值有:! n% v6 d3 d7 i+ l( X
! ]% T$ Q" G$ ^4 ~% s
  1. #define DMA_PeripheralDataSize_Byte         ((uint32_t)0x00000000) 3 m9 x% O+ ?# @; q5 S1 _) y
  2. #define DMA_PeripheralDataSize_HalfWord     ((uint32_t)0x00000800) 5 k7 W1 r% c4 O" |
  3. #define DMA_PeripheralDataSize_Word         ((uint32_t)0x00001000)
复制代码

: |& a, l  I3 mDMA_MemoryDataSize:
; j, f+ C* r7 k, f3 z5 ^# k, j9 D0 C3 }0 S! d  L
用来设置内存的数据长度
6 Y& Y& t% T/ F4 M! S
; e) \1 H# w+ [, [0 ]7 qDMA_Mode:) r0 b, G& r: t& W; R

2 A8 K5 H  K/ ?; a设置 DMA 模式是否循环采集,取值有:& E1 N' V( f' y% ]
/ h0 M4 m' o- J/ z; s# }7 M3 K  @" Q, j
  1. #define DMA_Mode_Normal           ((uint32_t)0x00000000) 2 s( S0 B9 g+ }
  2. #define DMA_Mode_Circular         ((uint32_t)0x00000100)
复制代码
8 \" K5 y6 p. o5 _& @; Z" H
DMA_Priority:  H. u; k( p; l  G/ V5 J2 d  y) I3 W
% t5 Y6 O" i, a& Y9 V
设置 DMA 通道的优先级,有低,中,高,超高三种模式。就是仲裁器仲裁的时候用的,当多个数据流同时开启,DMA仲裁器优先处理优先级高的数据流,取值有:0 r+ J# ?4 G2 }; G5 c1 }
( Q* u: l3 w; D# V# s
  1. #define DMA_Priority_Low              ((uint32_t)0x00000000) , g6 Q' ~* ^1 A
  2. #define DMA_Priority_Medium           ((uint32_t)0x00010000)
    6 b3 G% ?+ h( S, S
  3. #define DMA_Priority_High             ((uint32_t)0x00020000)
    1 N7 V: ]: q9 G5 G  ]
  4. #define DMA_Priority_VeryHigh         ((uint32_t)0x00030000)
复制代码
# _& E8 Y4 S& K9 y6 H6 b$ Y, f
DMA_FIFOMode:' S# W' B6 }6 p( v" A/ _$ I) l

' w1 n4 Z1 a. Y/ C* ^设置是否开启 FIFO 模式,取值有:
1 T: ^; Z# J& q, J) Q( g9 r. g5 a3 T0 f7 {# r
  1. #define DMA_FIFOMode_Disable        ((uint32_t)0x00000000)
    ) R# Z/ ]% R3 r2 H8 M) {* h- ~
  2. #define DMA_FIFOMode_Enable         ((uint32_t)0x00000004)
复制代码

/ M% B' n. `- Q, ~DMA_FIFOThreshold:0 i! q) I3 {6 _- w) l9 k* R# S
+ w- ]  k+ t- N) O2 [) _" W
选择 FIFO 阈值,只有上个参数选择使能FIFO,这个参数才有用。取值有:& J0 x4 O; e9 @" F& z8 X/ U( m5 y

6 C$ b6 A! G7 i2 L7 J
  1. #define DMA_FIFOThreshold_1QuarterFull         ((uint32_t)0x00000000)
    ) o. D1 t; E5 ?6 ?4 p$ Z
  2. #define DMA_FIFOThreshold_HalfFull             ((uint32_t)0x00000001) 4 e" u2 F9 l) a- r2 _
  3. #define DMA_FIFOThreshold_3QuartersFull        ((uint32_t)0x00000002)
    9 j5 f! z/ G& m0 e" M% I
  4. #define DMA_FIFOThreshold_Full                 ((uint32_t)0x00000003)
复制代码

- d( x, m" p. }2 Y' wDMA_MemoryBurst:5 u! a. g" `9 ^6 v0 V
' v+ x4 o- a0 l; Q% k0 i, j
配置存储器突发传输配置。可以选择为 4 个节拍的增量突发传输 ,8 个节拍的增量突发传输 , 16 个街拍的增量突发传输以及单次传输。取值有:
3 e. L& t7 S1 _5 W" U/ @( V1 }2 o5 `, Z) O; ?) _
  1. #define DMA_MemoryBurst_Single           ((uint32_t)0x00000000) 3 w5 R% k6 L* x. D9 ^
  2. #define DMA_MemoryBurst_INC4             ((uint32_t)0x00800000)
    0 r, o# e" S$ s5 E- k% E0 O8 V
  3. #define DMA_MemoryBurst_INC8             ((uint32_t)0x01000000)
    6 n4 M8 x7 D: w" a3 i8 \2 V1 ]
  4. #define DMA_MemoryBurst_INC16            ((uint32_t)0x01800000)
复制代码
9 x6 S( e+ @; r
DMA_PeripheralBurst:
7 e" D( a: c. N" W0 l+ f$ o! ~6 [/ J* @- l+ ^
配置外设突发传输配置。跟前面一个参数DMA_MemoryBurst 作用类似,只不过一个针对的是存储器。取值有:
$ V3 ?4 a: C$ a+ F. S9 L& u- a7 Q( a6 ?# y
  1. #define DMA_PeripheralBurst_Single         ((uint32_t)0x00000000)
    ( H8 U7 {" ~0 e
  2. #define DMA_PeripheralBurst_INC4           ((uint32_t)0x00200000) ) @2 n8 G# f5 o" R. L
  3. #define DMA_PeripheralBurst_INC8           ((uint32_t)0x00400000)
    4 L8 O( v9 v8 e+ I9 [
  4. #define DMA_PeripheralBurst_INC16          ((uint32_t)0x00600000)
复制代码

. l" \! h$ o7 s; nDMA_MemoryDataSize:
$ k# P- j5 K& R
3 a; V+ |6 Y6 F2 s* U5 {用来设置内存的数据长度
+ Q. O4 Z( s& B6 K$ k% A
3 A- L. b9 u6 cDMA_Mode:
8 p/ M; Q* r( `' j7 M% d; c" ~$ V2 z7 w( z0 k* ~
设置 DMA 模式是否循环采集,取值有:
  1. #define DMA_Mode_Normal           ((uint32_t)0x00000000) % S6 w# k& G3 O2 f
  2. #define DMA_Mode_Circular         ((uint32_t)0x00000100)
复制代码

0 q/ K* g# ^3 [  Z! IDMA_Priority:
6 m0 i1 q7 V" g' x
6 Q0 T9 M/ ^8 G/ E7 p
设置 DMA 通道的优先级,有低,中,高,超高三种模式。就是仲裁器仲裁的时候用的,当多个数据流同时开启,DMA仲裁器优先处理优先级高的数据流,取值有:9 @' Y& ^2 L6 c$ G" p
7 T7 e) F1 N  K# M7 N
  1. #define DMA_Priority_Low              ((uint32_t)0x00000000)
    1 o! I. R1 \. `2 @3 v! }5 u
  2. #define DMA_Priority_Medium           ((uint32_t)0x00010000)
    * B5 v4 y& ~) d3 t( P$ o$ z8 v
  3. #define DMA_Priority_High             ((uint32_t)0x00020000)
    ' v6 R8 [5 _* E" |" K- s: ?
  4. #define DMA_Priority_VeryHigh         ((uint32_t)0x00030000)
复制代码

1 e/ r! T8 i3 ?) yDMA_FIFOMode:
0 e: B5 N. v  p' v; W( Q( r! k/ K* y! S) k$ c4 E5 }+ @$ q
设置是否开启 FIFO 模式,取值有:5 A0 F1 k$ |3 u

6 f( {" y* v1 A7 s' ^) Y8 w% Z6 P
  1. #define DMA_FIFOMode_Disable        ((uint32_t)0x00000000)
    5 @, ^( p' U+ c* X& h' e: V% A
  2. #define DMA_FIFOMode_Enable         ((uint32_t)0x00000004)
复制代码

1 U, t, k" E) R. |) xDMA_FIFOThreshold:

. x, J8 g6 O2 Y- [, o& z9 P
  s5 M, E" c& u3 }# L5 \选择 FIFO 阈值,只有上个参数选择使能FIFO,这个参数才有用。取值有:; I. ?) k3 F* ?; j, x7 |- ~

# S  L0 D: j# {
  1. #define DMA_FIFOThreshold_1QuarterFull         ((uint32_t)0x00000000)
    " V2 l+ [  M/ n! O
  2. #define DMA_FIFOThreshold_HalfFull             ((uint32_t)0x00000001)
    0 r* O2 P. j! C0 ]) b
  3. #define DMA_FIFOThreshold_3QuartersFull        ((uint32_t)0x00000002)
    ' E2 r1 ^1 N% _: }0 n
  4. #define DMA_FIFOThreshold_Full                 ((uint32_t)0x00000003)
复制代码

8 O4 ^( P4 @& LDMA_MemoryBurst:; t' r; J, p  N# y7 \* Q
( l- `* w3 Z) `" a5 k; V
配置存储器突发传输配置。可以选择为 4 个节拍的增量突发传输 ,8 个节拍的增量突发传输 , 16 个街拍的增量突发传输以及单次传输。取值有:
# L- `: D; }* U/ p/ C# e: s- O7 ~$ o( I# N: P& M/ X. D
  1. #define DMA_MemoryBurst_Single           ((uint32_t)0x00000000)
    9 Q, G9 E+ V, S8 C0 Z7 F
  2. #define DMA_MemoryBurst_INC4             ((uint32_t)0x00800000)
    & M2 d8 Y9 m. h  {+ h
  3. #define DMA_MemoryBurst_INC8             ((uint32_t)0x01000000)
    : y" z. M5 Y  A3 j6 g" q
  4. #define DMA_MemoryBurst_INC16            ((uint32_t)0x01800000)
复制代码

/ s# A% R, U0 z7 q) MDMA_PeripheralBurst:  P% E' L/ t1 R3 d

- `: h$ ~7 j2 g7 u配置外设突发传输配置。跟前面一个参数DMA_MemoryBurst 作用类似,只不过一个针对的是存储器。取值有:
) @  P/ Q; ~4 o/ y; C& b8 C
+ c2 P& ^* {! C+ f! d) t- P
  1. #define DMA_PeripheralBurst_Single         ((uint32_t)0x00000000)
    " D" n- \# [: \- h, ]- N) o
  2. #define DMA_PeripheralBurst_INC4           ((uint32_t)0x00200000)
    4 f$ R( ~: M/ w. e9 {3 V/ F- I- z, U9 {" E
  3. #define DMA_PeripheralBurst_INC8           ((uint32_t)0x00400000) $ ]8 p7 L0 ]2 N. y3 G; h
  4. #define DMA_PeripheralBurst_INC16          ((uint32_t)0x00600000)
复制代码

, z  f6 r8 i. f8 S8 ]
( `) w. G# K# i2 t
  u6 v5 H, O) N7 T- W7 W2 ~* Q& K  L1 a7 X+ O
收藏 评论0 发布时间:2022-4-18 10:22

举报

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