直接存储器存取(DMA)用于在外围设备和内存以及内存到内存。数据可以通过DMA快速移动没有任何CPU操作。这使CPU资源对其他操作保持空闲。DMA控制器有5个通道,每个通道专门用于管理内存访问请求。来自一个或多个外围设备。它有一个仲裁器来处理DMA之间的优先级请求。
4 q; v% n, M" ~5 Z+ d
' E8 o. j- s8 m ] J; z( ^配置过程详解:
" E/ v: {" y; O5 t4 q6 X& c/ V1 C1 `8 r& b
/ }, s9 x% T; a+ h4 Y; a: V
1 s0 P. W" } }+ R0 ?( T: f' G( S4 o( Z: h: J, Z
首先调用RCC_AHBPeriphClockCmd()函数,进行DMA时钟的初始化。
$ L i- H. v- D% S H/ j" v* e1 W$ L" \5 U4 t8 U* e
" N' p! }& [ r9 Q% C, X' y& O. V
. z+ Q. i7 f1 I/ w: a
可以看到DMA在AHB时钟上。所以我们使用以下语句打开DMA1的时钟。3 l) V9 C8 m$ i) `% I, K" ]
/ N% {4 F! U/ H$ J6 J; S
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//使能DMA1时钟
复制代码
. G2 ?+ `6 i* ?. P' ~4 p+ ~/ N& v 接着在DMA.c中编写如下两个函数。来设置DMA从UART1到内存和内存到UART的传输通道。
& b% v& |2 k5 ?, D3 L3 b% E- /**************************************************************************************
* m9 a3 S2 z/ F3 K2 Y/ H, F - * FunctionName : DMA_MemoryToPeripheral()
6 U9 q+ U7 }6 A - * Description : DMA传输(内存-->外设)0 l$ j! r7 @ ]' @; Z, n2 X
- * EntryParameter : 2 \" D w9 g% N( [7 X- ?# V& u$ u% i
- * ReturnValue : None
0 |$ g9 o; J( B4 Q+ E6 s& T# G0 ? - * Function : ! d9 ] Y" K2 S3 B, f9 {2 s, C
- **************************************************************************************/
) b$ J" o6 \# z1 A& A - void DMA_MemoryToPeripheral(uint32_t MemoryAddr,uint32_t PeripheralAddr,uint16_t BufferSize)) U s7 l" ^. R- p" R
- {
- A( Y& L" Y6 k( N9 N - DMA_InitTypeDef DMA_InitStructure;4 a( w; s4 X9 C4 e
-
) k) P/ z. Z q2 G+ i d/ c: c - DMA_DeInit(DMA1_Channel2);//复位DMA1_Channel2# E( \9 ]% A9 u a& ^; T
- - l& O7 Z/ ~% H" F3 D1 R
- DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址8 e0 x W+ q: ^) D, N
- DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址
' `4 n7 X- G, s" c" X- y" }3 q - DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//传输方向:内存到外设
; d3 U6 ~* l1 q) j# f. D h& j: ~ - DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度5 ?- c% \- x$ U5 d, a: K
- DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO
; O- H& `. q& I# F - DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES6 o+ `' H f2 g3 B
- DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
% H9 t* ~0 ~; y3 c$ Q, I3 [ - DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
& Z3 f& |6 S: [! |% c, T# z - DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO
7 L/ J: U; M0 h, I2 R, }$ s+ t - DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;
% G: `2 S; @; F. D# X - DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO
8 u. e1 h# r6 o' o4 K* g - DMA_Init(DMA1_Channel2,&DMA_InitStructure);
9 F3 y( G0 u' t7 Y1 [' A, c# _7 \ - 4 I8 S2 p8 e% T
- DMA_Cmd(DMA1_Channel2,ENABLE);//使能DMA传输' X, o! k; C. L9 W. j9 Q$ f
-
6 t3 _$ p0 X7 J& K2 ^/ M8 |0 | - }
复制代码- /**************************************************************************************
$ }/ c% q. F# i8 _4 Q5 l - * FunctionName : DMA_PeripheralToMemory()
: I, x' l9 J' d3 g - * Description : DMA传输(内设-->内存); l7 o1 o) G5 ?! _" C! W
- * EntryParameter : + D' W: H( m' f2 Y' P+ ?
- * ReturnValue : None
& x6 J/ ]: f( C* ^ _5 p - * Function : . E+ q' X0 ^( h; F$ b! {, U
- **************************************************************************************/
6 V. w' P- v1 u! w* y) z7 _& F, w - void DMA_PeripheralToMemory(uint32_t PeripheralAddr,uint32_t MemoryAddr,uint16_t BufferSize)
7 k, E8 x) n6 O6 G - {
+ S4 f q y: Z q# O9 D; w4 w - DMA_InitTypeDef DMA_InitStructure;//声明结构体
. Q3 u% R: U y7 S* s" d5 F/ \ -
3 L5 V" X! p! S9 B7 B$ ~* g2 n& V - DMA_DeInit(DMA1_Channel3);//复位DMA1_Channel36 S4 i3 t6 \. a" ?
-
! B4 X' Z" s& y1 V - DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址
0 a/ u( Y) n$ } - DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址
" I$ z, l! ?7 k" p. O) g - DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//传输方向:内存到外设5 @' G' M) M3 Q( G4 q, H1 \2 f8 f7 z2 M
- DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度
+ r# i7 w# }3 q - DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO
/ D4 y9 b+ L7 f# k1 o/ c3 h/ d# c - DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES
: c" w/ X: V9 H3 R4 D - DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
& }" x7 Z5 j) d2 L6 }& t3 w: V# _ - DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
) t* _& u9 p7 n8 i* p$ {( h/ _ - DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO
. x. e t6 s1 s- H1 h4 y( G0 P - DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;
1 |7 B4 f2 F7 z9 T; ?, Q - DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO" j; P( l, f# S
- DMA_Init(DMA1_Channel2,&DMA_InitStructure);: G' ^6 K9 Y1 T* I! A& _8 ^
- ) d0 P+ y! c0 S" d+ R2 e3 c
- DMA_Cmd(DMA1_Channel3,ENABLE);//使能DMA传输" ~3 A$ h* [, l& y
- : D$ y- D0 F. Z
- }
复制代码
1 n+ f: O4 ]8 M# l6 ~9 j, y. R 通过以上两个函数可以初始化两个通道,一个从内存到外设,一个从外设到内存。
! ]( t/ E) ^$ k) O5 f' E; v6 K
1 q( f+ k7 E: U% L% S! E当然在我们调用这两个通道的时候需要知道一些东西。* ~6 ?. D; g- Y1 C L9 ]
, S1 k0 s5 r g+ }1.有关通道的信息:. R$ a5 I6 r5 i2 o
" J5 {$ w* Q0 x! t7 N3 `! y
9 L+ u% |3 ^8 L, D5 _0 x4 {6 q( I" ~) `; {: l R& `/ G
|