直接存储器存取(DMA)用于在外围设备和内存以及内存到内存。数据可以通过DMA快速移动没有任何CPU操作。这使CPU资源对其他操作保持空闲。DMA控制器有5个通道,每个通道专门用于管理内存访问请求。来自一个或多个外围设备。它有一个仲裁器来处理DMA之间的优先级请求。+ f# k5 @& _% P
) C! \- G& k0 g
配置过程详解:
9 M2 |5 ~0 @- X3 I( _1 q/ K- |4 e0 V Y `. Z; I2 [1 K% h/ F$ U6 n
& Y9 Y2 B' P% x
* Q- T. A% S2 j( d# N' G7 U6 q& A
% B2 j9 I* X `- N/ U首先调用RCC_AHBPeriphClockCmd()函数,进行DMA时钟的初始化。 2 R* N8 l2 i9 F' `5 c
4 V1 | \7 Y; J4 ]' _ _5 W; T5 [# D1 j- q1 w. h
( ~. s+ g9 X$ u5 l% h可以看到DMA在AHB时钟上。所以我们使用以下语句打开DMA1的时钟。3 Y% I) F1 n# R
2 J+ |7 x6 R/ I; R, Y- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//使能DMA1时钟
复制代码 & i* _- j6 k. l4 V! z& W) c y
接着在DMA.c中编写如下两个函数。来设置DMA从UART1到内存和内存到UART的传输通道。
, d3 }4 `% ~& o% N+ @( r3 @- /************************************************************************************** ; M9 P4 z: {4 O7 b4 f+ w
- * FunctionName : DMA_MemoryToPeripheral()
2 Z3 l1 Z+ x' N% | E - * Description : DMA传输(内存-->外设)
# D7 s5 }4 Y& u5 Q8 d U - * EntryParameter :
3 @3 e6 j2 N: h6 o. u o! ~ - * ReturnValue : None # Q6 D2 I4 T$ X! ?5 q% |
- * Function : + J2 A- t7 C6 {/ J: o
- **************************************************************************************/
' V( P8 c* f& i/ P- E3 X+ C - void DMA_MemoryToPeripheral(uint32_t MemoryAddr,uint32_t PeripheralAddr,uint16_t BufferSize)% H5 j3 `* F- ?
- {
( {# G3 s. F8 J9 n" q+ J( P - DMA_InitTypeDef DMA_InitStructure;0 c( I" W* |( _& I5 ^3 j
- & I Z d" S. n1 p: e
- DMA_DeInit(DMA1_Channel2);//复位DMA1_Channel2
* B+ E! p6 Y7 b -
! M: [0 j& F# x- s( [( { - DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址. J+ O- Z7 M6 H; H7 e# q
- DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址
+ p$ ?/ \" U u - DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//传输方向:内存到外设( S( M9 a N3 G! z
- DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度
7 S0 Y' W3 F$ b/ X! k - DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO
/ N2 @' L* y! m. {0 Z) A: @ - DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES
/ w+ j4 e U$ F% J6 Y9 l9 l - DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
0 Z& c. O3 x7 O - DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
; b& i0 A* ~5 O' H. w5 l6 r+ A/ ^ - DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO* m& D+ J9 f, [: q1 |
- DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;
# h- s& U* Y) ~8 C" e5 F3 m - DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO) @! x) n, P5 Q G+ R
- DMA_Init(DMA1_Channel2,&DMA_InitStructure);! x% Y' l8 p/ P. m) s* q0 B7 j! Q
-
1 K" o+ S. v9 z7 d; G6 Q4 I8 _+ o - DMA_Cmd(DMA1_Channel2,ENABLE);//使能DMA传输
: [, D: B8 A5 A# q2 b/ o -
4 z. P* I# }9 `( |, L7 O6 p - }
复制代码- /**************************************************************************************
; }( e6 ]' @: }) u# G - * FunctionName : DMA_PeripheralToMemory() ( O- s7 X4 d) k/ }
- * Description : DMA传输(内设-->内存)9 D7 I C3 K- B! ~0 @' z9 B
- * EntryParameter : d* W! Y' P/ Y6 V0 o- V: u7 Y: {) w
- * ReturnValue : None
9 u( b/ ?9 s9 |0 V! f, {, r - * Function : 1 {7 M) s% k/ }! ]$ B8 V4 d6 h- o+ F
- **************************************************************************************/" \8 J0 j7 O8 v- `9 P) Z
- void DMA_PeripheralToMemory(uint32_t PeripheralAddr,uint32_t MemoryAddr,uint16_t BufferSize)
- Z/ d% v, Q V# O: P - {' m/ Z$ L/ T/ Y% | q
- DMA_InitTypeDef DMA_InitStructure;//声明结构体" K$ T+ L, L) W8 ~6 n$ c) P
-
- ~' t% z2 F+ `1 U7 _ - DMA_DeInit(DMA1_Channel3);//复位DMA1_Channel3
! _; u7 G- t d, t. W -
' F$ \/ r" S# @, T- q" Y0 H/ T7 i - DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr;//外设地址
' U4 ~; ~# c0 E5 y+ O( U& V - DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr;//内存地址 H" ]8 `9 l1 ~6 e; r
- DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//传输方向:内存到外设# B6 t$ k8 H# _: i
- DMA_InitStructure.DMA_BufferSize=BufferSize;//传输长度# @4 L' g) ~5 V! B5 d" V% ?* H" o
- DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设累增:NO
/ G: t+ t. n9 F - DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//外设累增:YES# d/ y! j- }0 G" z) a5 e; w
- DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;; x2 M3 }& ` X2 o0 }
- DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;3 d2 F" T1 h" w+ O' Z- M* e- {% u0 H
- DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//循环模式:NO
+ V$ [6 ^% @$ l6 b0 A4 b - DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;
% Y( G5 p9 {4 `$ ^. k" v8 H - DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//内存-内存:NO
; y3 Q1 V& G0 m- b% x9 C, g - DMA_Init(DMA1_Channel2,&DMA_InitStructure);
, v) J+ [2 i5 h - ( f& I1 ~3 F5 d' h
- DMA_Cmd(DMA1_Channel3,ENABLE);//使能DMA传输
9 }; H1 z% |% u, G, _4 m5 z - N3 ?. `& W# X4 x: o$ t3 z
- }
复制代码 - a# @) M6 H" U9 t: i( V5 G
通过以上两个函数可以初始化两个通道,一个从内存到外设,一个从外设到内存。) W d3 [' ]0 E0 r. V' W
+ _/ D7 C, f1 R; I1 u: v+ n# N& g
当然在我们调用这两个通道的时候需要知道一些东西。& @6 Y6 R& u, I1 ` \, D
) ]# m2 y, k/ i! [! l1.有关通道的信息:. _- D4 }) ]9 l2 u0 s
0 M/ z8 e6 V3 X- ~7 N. s
' N5 _4 B6 Z9 J) @" _
5 I2 Z* y- F* f' U |