直接存储器存取(DMA)用于在外围设备和内存以及内存到内存。数据可以通过DMA快速移动没有任何CPU操作。这使CPU资源对其他操作保持空闲。DMA控制器有5个通道,每个通道专门用于管理内存访问请求。来自一个或多个外围设备。它有一个仲裁器来处理DMA之间的优先级请求。: l& v) J3 g; v5 x
. q7 C9 @, v4 @+ g' V配置过程详解:
" d, u' B9 H! c! W+ \' D# \$ z8 U( s( y" T, B
) R$ S( x. @' P' n1 }
# u3 }- y- O, h I5 K
- E& j- S* w5 Z1 g T/ g, W首先调用RCC_AHBPeriphClockCmd()函数,进行DMA时钟的初始化。
O# M2 F9 ]6 V- _! {, f) z
0 {3 V+ z' J0 M+ B( i. U) G6 ?: T
! ]3 l5 F: w, E/ k( T
% m& z E7 J* o4 H6 f/ M( S可以看到DMA在AHB时钟上。所以我们使用以下语句打开DMA1的时钟。- u% B/ k$ J1 ?7 F: W6 w( ?
8 U: M+ U j+ E: ]
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//使能DMA1时钟
复制代码 0 L" b/ R$ h4 V3 `0 s7 i
接着在DMA.c中编写如下两个函数。来设置DMA从UART1到内存和内存到UART的传输通道。
$ s( A- n6 o$ l+ r5 E: D- /**************************************************************************************
) w( K8 J/ p, j% ~% f; U* X, ?1 L% } - * FunctionName : DMA_MemoryToPeripheral()
, |) c, |/ ? w' a - * Description : DMA传输(内存-->外设)
: t0 a: a5 e6 y) u0 I4 I. T+ m7 n - * EntryParameter : . z3 `: ~0 I. Z& I
- * ReturnValue : None 5 P: w8 \0 P5 Q* v5 u8 c
- * Function :
) W# {& ^7 ]4 r9 \( Y - **************************************************************************************/
4 D. T( o9 @5 M% ?" {5 h5 i - void DMA_MemoryToPeripheral(uint32_t MemoryAddr,uint32_t PeripheralAddr,uint16_t BufferSize)- L1 C# U9 a0 l4 G ]6 I
- {8 @% ]. B6 D; U. D) T
- DMA_InitTypeDef DMA_InitStructure;
4 H8 @% D0 D- T0 p - 8 i- K7 }7 a" _
- DMA_DeInit(DMA1_Channel2);//复位DMA1_Channel2. X) h" K' v! g
- , A1 a0 Z( A. U
- DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址' o, g- z' N% C" ?6 X
- DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址
0 u- d E4 ]& _) G) P% J4 y - DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//传输方向:内存到外设
2 F4 e4 s/ ~- ^- j - DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度. A% q9 W, w r. o o U7 A
- DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO' l9 P3 F) u: @" n, t
- DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES D0 {" a5 V3 E; h( { |
- DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;1 ]# ^; U3 l5 V# ]5 y1 {4 H
- DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
2 d; x0 ^2 t. e# P" t! ~ - DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO8 \3 ^2 {) O! s/ _/ X$ U% s
- DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;/ G6 h& e0 V4 B% G( L% \0 s- f, v- ^1 o
- DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO2 x! j2 @( ~) I3 d f
- DMA_Init(DMA1_Channel2,&DMA_InitStructure);
7 k6 O P+ h% E/ j* g" T -
! i& T' S x7 A# m& m - DMA_Cmd(DMA1_Channel2,ENABLE);//使能DMA传输
, U" `8 R' M' J - ! {' ~0 I b% ? a0 w! X S
- }
复制代码- /**************************************************************************************
4 Z3 _/ p2 L6 U6 }& I2 x, c - * FunctionName : DMA_PeripheralToMemory()
9 O: T0 a: y8 |; r& v g- U - * Description : DMA传输(内设-->内存)& j8 x4 {' X+ s* K
- * EntryParameter : o- v6 b3 }) X2 O
- * ReturnValue : None + W V3 G% l; K8 s" W
- * Function : 0 F% w, n) q# g0 n1 q
- **************************************************************************************/: b D( E! ]7 L, i$ h$ n4 n
- void DMA_PeripheralToMemory(uint32_t PeripheralAddr,uint32_t MemoryAddr,uint16_t BufferSize)2 c+ `+ I+ h! \- |/ A6 v, N
- {
5 q3 ^8 G$ J* Y - DMA_InitTypeDef DMA_InitStructure;//声明结构体
& c, x. ?+ N( p2 d% U; X; r. @ -
. V$ ?$ A+ o3 c - DMA_DeInit(DMA1_Channel3);//复位DMA1_Channel3
2 L. W/ G9 O' T5 M9 t - 3 a7 A5 [3 @, l7 b: v6 W9 R1 Q/ A
- DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址
: B2 F( \3 A" k! q - DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址
# w6 a# K- R& T/ i - DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//传输方向:内存到外设
- g# M! _0 [# h - DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度
9 Y3 f% [7 A, n# v - DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO% w/ s( E* J* S0 G# |
- DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES% E" B, M2 s y
- DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;" }# Q( I: w: ^$ j3 l
- DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
( a8 x8 C! D D1 ? - DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO; B' ~6 T7 k" X
- DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;5 r* ~, w3 w8 z% V3 C
- DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO
9 Q4 j7 R$ ]/ _% S: j - DMA_Init(DMA1_Channel2,&DMA_InitStructure);0 C; N7 Y9 K, I( b# X
-
7 |* v" v. M- }. H6 o3 v - DMA_Cmd(DMA1_Channel3,ENABLE);//使能DMA传输
' j7 `; k! u4 _& m2 | -
+ g Z0 c& ?9 Q3 X# J5 j& j - }
复制代码
5 q3 b$ R M: n: l. q' k 通过以上两个函数可以初始化两个通道,一个从内存到外设,一个从外设到内存。
8 M: u: V! O2 Q4 s9 R% y# ^" A
* k9 S+ a, Y+ f+ I1 ]' X当然在我们调用这两个通道的时候需要知道一些东西。
) M( a# v# a+ a* G m+ Z( j: f0 G5 F9 m
1.有关通道的信息:
/ g- e( a$ A# v' }+ g4 x! k c
) s0 r! T- W& U3 j: z3 d/ O- s) E8 b! u2 E( L1 ~$ m
9 e/ G9 n7 c! }% m- t0 J+ Z |