一、DMA请求映像
6 F- p( a- L- p3 d* s* u8 C, y$ J T" p6 @, b6 B2 l
+ X" \$ o; }9 @8 @* s. p" d+ I
2 P T; m$ F) Z( \! C3 r
6 Z2 P. t. C9 w1 l
4 Z1 w1 Y" c8 E由此我们知道如果需要使用串口1的发送功能需要用到的是DMA1_Channel43 T! D Z0 V. X+ ~' `
( q2 G C" ? P' U使用串口1的接收功能需要用到的是DMA1_Channel5
' S' m" U a( a: b6 R: X- c; J( a) `- n3 k7 n9 \+ r6 {2 J+ g [
( w" L3 X- @5 ]" X# U7 \二、怎样配置软件来使用DMA 把数据传到串口发送?# ?) U3 u: t, {; M' K3 h
8 F( n" Q+ d- O: X2 L4 z. j
(1)配置dma. y+ O( s6 j3 X! r4 T# A
v4 D1 g6 U# u- /**************************************************************************
' m" h/ D/ B, g7 {2 ? - *函数名称: Dma_Init : |: r# d' w0 ~9 g+ z3 _" v0 b
- *功能描述: 利用DMA 把内存的数据传输到串口发送达到高速传输的目的6 z4 u: Y$ J* O' L
- *
- }. I% `& d* R/ }% r1 m* F l9 s - *输入参数:无
( J. X0 D, u! V2 O. l$ R$ | - *返回值 :无
' X, h& A4 V3 _: p' [, P' a9 ~% I - *其他说明:无
y5 n4 S( I' W; O, {. Z0 |5 a6 A1 O - *当前版本:v1.0 1 c/ [3 ~) ^. n- q6 O* l" j
- *作者 :尹宣
. d* w3 F, J- ^( r" R, H - *完成时间:2013年12月1日- C/ p7 o' k3 F6 z7 ^; l% q% v
- *修改日期 版本号 修改人 修改内容
% T* Q% {, Z8 e }5 R+ |3 d! f! y - *-----------------------------------------------------------------
4 ?$ T! l! _1 e; ]& p - * 2 U% X% M1 i& Q4 H7 U9 `$ n
- ******************************************************************/ 3 j5 x9 a ~# K
- #define UART_RX_LEN 5
. b, d4 @ R; Z7 \! j4 Y& _ - u8 Uart_Send_Buffer[UART_RX_LEN] = {0x12,0x34,0x56,0x78,0x90};
2 A2 D2 T! X* F - u8 i=0;
, o- l( G3 ?' ?/ Q/ s - u8 Flag_Uart_Send=0;
+ ^/ c v4 n0 F* I8 L - 8 w m' Y* H% k9 P0 i5 p
- void Dma_Init(void)0 U$ T3 o, ~' l: [$ e
- {3 x/ S6 U7 g3 ]: U. |
- DMA_InitTypeDef DMA_InitStructure;& G7 q. N1 ^0 s; N
/ v9 k5 A* [- B, s1 M. B- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
1 _" q0 r* i0 `* g6 t# J1 x - /* DMA channel6configuration */
! h! r! H! C+ r2 D4 Z9 u. h3 y - DMA_DeInit(DMA1_Channel1);7 N. L( f2 } w+ {2 w
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); //外设地址4 Q( Q7 O1 |& q0 `) W1 \, @" \
- DMA_InitStructure.DMA_MemoryBaseAddr =(u32)Uart_Send_Buffer;, \2 j. Y# h& `7 s% c
- DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST; //外设作为目的地址 //DMA_DIR_PeripheralSRC; //外设作为DMA的源端
* O' M9 D0 r" D m4 D - DMA_InitStructure.DMA_BufferSize =5; //BufferSize; //传输大小! C0 {( J: J+ B/ o$ ]
- DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; //外设递增模式禁止 DMA_PeripheralInc_Enable; //外设地址增加6 Q5 Y0 p3 C8 h8 E% h B- o
- DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable; //内存地址自增
7 E' Q S' f0 _ - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //传输方式:字节 DMA_PeripheralDataSize_Word; //字(32位)1 I( J2 i( s! v8 y( D
- DMA_InitStructure.DMA_MemoryDataSize =DMA_PeripheralDataSize_Byte; //内存存储方式:字节 DMA_MemoryDataSize_Word;
( t# Z- N7 [) o' J$ e3 T" d# v - DMA_InitStructure.DMA_Mode =DMA_Mode_Circular; //DMA_Mode_Normal 正常模式,只传送一次; DMA_Mode_Circular:循环模式,不停的传送;
# R [* N9 B. p' L - DMA_InitStructure.DMA_Priority =DMA_Priority_High;
8 I( _) a, t/ t - DMA_InitStructure.DMA_M2M =DMA_M2M_Disable; //DMA_M2M_Enable; 5 n7 I0 c3 X3 l* p
- DMA_Init(DMA1_Channel4,&DMA_InitStructure);% R5 k% V5 Z% Z, K. U: D, W
& v" i/ Q8 q0 ?- /* Enable DMA Channel4Transfer Complete interrupt */) \$ L% `' E6 A" x; y: z, }" T8 P' e
- DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);0 L4 N7 g* ?+ A! B, E
- //
* A9 G7 L6 t& A4 S3 I" k - // USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //串口接收器DMA
) ?2 L8 R! c- X: @2 q9 J: k, o/ r - //采用DMA方式发送
1 I+ l( O- z; C b - USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); 8 ]) {: D$ f, y! m. p8 t
- //启动串口 4 q1 M2 \0 ~- B1 u9 ?- z& X
- USART_Cmd(USART1,ENABLE); - M& h7 J* |4 ]6 d8 U1 ^) B c4 d
7 E6 y; N8 I# d, S5 I- ! h0 I4 h I- @ |
- DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);2 R- o5 l0 M" d
- 传输完成则进入DMA1_Channel4中断;
复制代码 ! g* C1 U2 ~0 b" i
注意这句话:USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); 这是使能指定USART的DMA请求;(不同的外设都有这个 xxx_DMACmd()请求;)- e* G! x# a. \' @* q
, F* G1 z5 I- O8 lUSART_DMAReq_Tx:发送DMA请求
- A# z9 h' F7 o! s* c5 X& h/ }. O6 ]6 b( [% D% {
USART_DMAReq_Rx:接收DMA请求
7 A/ S1 A/ n7 C1 Z( e7 A, Q9 V' M& N8 s5 n% Z$ a
7 B$ _, {/ y# v& \: S串口配置
3 F0 B# U2 M' l: i$ G; w8 e. P% ^$ L9 B+ M5 Y; Z5 J: V
- /***************************************************************** : G3 I5 y% U8 G& s7 S% a" h, @
- *函数名称: USART1_Init
$ H, }1 V4 Q8 x, x) y - *功能描述: 配置串口1初始化
0 I2 c4 I. K( \, c8 ^) [8 k - * 3 t# n% C* h, A. c; t
- *输入参数:无% ] ~) Q) @' v8 s0 E O
- *返回值 :无+ R8 O( o+ U. j6 P
- *其他说明:无! W( K9 ^( I, W5 K
- *当前版本:v1.0 + O- B; g8 K4 r6 v4 {
- *作者 :尹宣0 I2 ?4 D8 q8 o2 P4 i
- *完成时间:2013年12月1日/ F! v% G, w, e- {# f8 a# Q
- *修改日期 版本号 修改人 修改内容
' n" U: L z7 {& j - *-----------------------------------------------------------------
7 w" [/ H7 i3 }2 z - * ! g% O% W( h# f( k) V" I6 s
- ******************************************************************/ 5 r% ~' W! l# L! O, ?+ l
- void USART1_Init(uint32 baud). o% m8 g6 F0 V t( b# {2 Z1 Z
- {
6 z% f. Y2 s/ [: D - GPIO_InitTypeDef GPIO_InitStructure;
% Y" K2 y) R1 ^& D4 d" Q( K% {7 P - USART_InitTypeDef USART_InitStructure;
& i8 W/ X7 d) @% m/ L - USART_ClockInitTypeDefUSART_ClockInitStructure;
- e A+ P* n# \6 @! g8 Y" ]
$ A$ f: c9 P. X& s7 o6 H- . [9 `1 M. e& p+ R. [+ E
+ s% [; R Z9 ?7 ]8 {9 m: M+ o- //使能串口1,PA,AFIO总线
; H1 V, d C; f9 { - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |/ O$ u* ~* A, z! T5 M
- RCC_APB2Periph_AFIO |4 M/ G$ i# f" A. `! h8 h
- RCC_APB2Periph_USART1 ,
3 b9 N8 Y) e# [) \4 t F! ` - (FunctionalState)ENABLE);1 R% L7 H- Q) [% ]
$ f3 {& [) v- d5 o- // A9 USART1_Tx) q( g2 G! a* `! _4 s; w0 e
- GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;
8 ^9 v f0 D2 T0 W9 _ - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/ |* u F# a3 i( T5 d - GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;) V: |% o% y7 c5 K* i
- GPIO_Init(GPIOA,&GPIO_InitStructure);
& ^2 J; y: K" b, s# }! M, J
9 ?$ V2 N2 z1 E q7 Q5 k- // A10 USART1_Rx
. c3 H+ l9 M# y: H$ I* |4 _ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
& q* R9 h R9 q2 b* z; @; k+ s+ j - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;6 b3 d% L$ h& i4 n5 Y1 i
- GPIO_Init(GPIOA,&GPIO_InitStructure);
8 ?" E7 h4 H5 }* P
7 X+ O5 N% T" q! @! q* z- USART_InitStructure.USART_BaudRate = baud;8 S2 \1 @# U9 F- C8 ^
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;* j3 @8 W4 y! O" i+ S8 c: H M8 H3 h2 y
- USART_InitStructure.USART_StopBits = USART_StopBits_1;8 m% r6 W- x8 d$ J x) B9 y, L
- USART_InitStructure.USART_Parity = USART_Parity_No;* P4 G# g0 h) z8 `( b/ H8 r
- USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
) O$ S( y$ D n( ^1 G% @" t" j! J - USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
* w% X( o; a f( ]8 ^8 ?1 P - * w! U/ X: _" \$ I# Z K( D: }
- USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
6 i/ W" v" b8 H - USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
! E% k, Q* x! l/ p) S7 s - USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
9 x. `' g9 i6 h0 P, f - USART_ClockInitStructure.USART_LastBit= USART_LastBit_Disable;+ F' q3 z0 W; x7 q# x
- USART_ClockInit(USART1,&USART_ClockInitStructure);
% C7 [( ^* \, B6 y3 Y4 {3 F
4 }( ?! P) J% b7 W- USART_Init(USART1,&USART_InitStructure);$ r/ g& \: ^/ }3 }3 F1 j7 N# u
- USART_Cmd(USART1,(FunctionalState)ENABLE);7 r4 H" d2 t0 F% y1 _0 m
- // USART_ClearFlag(USART3, USART_FLAG_TC);
& U: E6 c# @% C ~1 b - //串口1使用接收中断
) D0 Y& H& {0 d8 J) d - USART_ITConfig(USART1,USART_IT_RXNE,(FunctionalState)ENABLE);
4 R/ G/ [9 d* c5 Y' ?; ~ - }
复制代码 0 |+ H3 G: Z7 z' V' P/ k y3 i, X2 Z
2.设置DMA优先级0 o0 N& v! S) ?1 x3 H
! m+ y1 Q! D' a0 C* z" l: J1 R5 U5 ?- /***************************************************************** 4 Y$ t" {+ e4 K1 ]
- *函数名称: NVIC_Config 3 d9 C" w# W' t* M$ x7 v4 Z
- *功能描述: 配置DMA的中断优先级: w. }9 f0 G- f! q
- * : v2 ]. w, {( Y# @
- *输入参数:无
7 Y$ i Y0 E) D8 X3 {& g3 U( z - *返回值 :无( M- h1 e+ }- n9 l0 x
- *其他说明:无
9 D$ V- T1 f3 x4 b. G5 X - *当前版本:v1.0
; Z) i# ?* C, m8 B6 _# a1 I - *作者 :尹宣
+ `% D2 {- ^$ i3 _/ h; o( n - *完成时间:2013年12月1日
; a# A/ y/ [7 i7 F& ?9 K! P; T - *修改日期 版本号 修改人 修改内容: y* q2 ], ?1 X, k- A ?
- *----------------------------------------------------------------- # y- o+ s1 m* C' }, D5 S: H4 p4 M% R
- *
4 d' s# ?( X* c8 [. i - ******************************************************************/
0 u, P. ^5 P6 w# O0 [% S3 N7 w - void NVIC_Config(void)( E. `9 X/ p/ Q" D* o
- {, s0 e2 w, j V7 a; W& n
- NVIC_InitTypeDefNVIC_InitStructure; ( I* p( M l; {3 [1 u
- * @) k5 b' Q+ B8 O9 l0 U# j
- //DMA优先级
# U8 ~, I; d2 x) d& `# { - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);5 b# J3 A q( H5 J; f9 X: q* y* w
- NVIC_InitStructure.NVIC_IRQChannel= DMA1_Channel4_IRQn; 8 x# l) P& W5 K3 B6 E: n) ]/ O
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
% z5 Q: J, ]. E8 V: B - NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
, j o$ I& z4 Y, F( I8 w: B" V8 c: n1 a - NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
# |3 l( ]. L" r- C - NVIC_Init(&NVIC_InitStructure);
7 N: I( k! ]+ _7 M+ | - X1 f' e$ T6 H) }
- * ]" B" |: m% i0 u' r
- /*Configure one bit for preemption priority -------------------------------- */" O! w. T8 _: p0 R+ @# d4 ^% |; a4 K
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
$ z! S) m2 q: ?& j) X
) n0 z7 L v) c! _5 O! L I) Z- /*UART1 -------------------------------------------------------------------- */: m) _5 K! w# n- S5 M' Q( m
- NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;. r9 t# V# I# n2 ^" D' c# w
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;# ^9 m5 G' u1 I; X
- NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;8 H) L5 P: M5 V/ C5 D3 `1 Y4 D
- NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
8 M0 S% G$ _; w" `& u- D5 n, C - NVIC_Init(&NVIC_InitStructure);
5 }9 N/ L) Z4 K/ n
6 ]2 T) }7 d$ g" R+ k% ]- }
+ j: Z: T! ]/ Z% x0 s
复制代码
3 K5 F% z. }/ v% k x8 `
1 `" F+ p& T2 o1 H* X3.在stm3210x_it.c 文件中添加 DMA中断处理函数# y! @8 D$ e' C
5 @4 N! P5 F: {( k; {
- /*******************************************************************************6 z$ Y) Q/ e# I, v+ Z; v
- * Function Name : DMAChannel1_IRQHandler' W2 r6 k" J# g, ^$ M1 i
- * Description : This function handles DMA Stream 1interrupt request.# k$ `/ j" B7 i; y
- * Input : None: O7 J/ O3 `7 G1 V8 g6 j8 u! B8 \
- * Output : None9 S0 R0 M. Q) z; K( ~
- * Return : None
9 J f0 J9 @- Q X0 k( B: @, @ - *******************************************************************************/
5 u. Z. b5 J. l7 ?, ~. b% h9 \ - //串口1 DMA方式发送中断
* F* J0 p, @2 N - void DMA1_Channel4_IRQHandler(void)
) J# V" P/ V0 X+ e- o3 \# I - { 8 g G. T5 E' K* F
- : N7 h& \' [+ r
- //清除标志位3 y8 A) r* |$ v9 A6 y: i- ~- z
- DMA_ClearFlag(DMA1_FLAG_TC4); ( {! F9 T$ H+ U7 B5 B6 R) r3 o, N; x n
- //关闭DMA
' B& L; x B1 J z7 L - DMA_Cmd(DMA1_Channel4,DISABLE); ) C6 b! J) G/ `# Z }7 @
- Flag_Uart_Send = 0;
1 y! \- g' g! z: M9 ^/ [. O - . w5 Z& I9 G% X. J! Q
- }
复制代码
2 i" }0 F7 Z! |, f, ~0 W2 _3 b4 | i7 A* J+ D$ @
如果DMA是正常模式DMA_Mode_Normal时,传输结束后将不再产生DMA操作;所以需要在传输完成的中断中暂时把DMA关闭—即:DMA_Cmd(DMA1_Channel4,DISABLE); f% Y, E9 i4 d6 q3 l& s3 \5 J, w. }
$ ^3 Y/ h. z* [5 ^
之后在main函数的while(1)循环中打开DMA_Cmd(DMA1_Channel4,ENABLE);进行下一次的传输;1 K6 X' a; h) B! U
$ y3 g6 N( @" b7 F B6 q/ s
+ O6 C( h6 x& q/ R0 {( q) H2 @' b测试:
! Y+ q6 Y+ B4 N p' k6 @) n* C
, G/ `6 ^! T% _: m/ ~. @' H) C2 q. M数据源地址为数组Uart_Send_Buffer ,它的定义如下:
! H# O7 k# A# Q. F
% _" i7 W6 _2 \7 B( |5 P5 e#define UART_RX_LEN 5
p2 b ^- @) o& ?0 L
9 F5 W; }/ ?, U1 Hu8 Uart_Send_Buffer[UART_RX_LEN] ={0x12,0x34,0x56,0x78,0x90}; ! c+ X9 F+ o$ C
! U6 B# ?( t+ X( X
6 ]" a' L! i7 d# x5 U4 p
8 h/ P; y1 I8 O# ?当程序开始全速运行时,串口助手打印* c! T" j, D4 @" i( ~3 k
3 M {) }/ G' s. [4 _6 }+ |
$ s; s' v" b" Z2 [% c, y6 u
7 ^8 u; c" ^; s. E" `
2 m7 n; u5 b7 n( a |