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

【经验分享】STM32 DMA 应用之 DMA 串口 数据传输--发送

[复制链接]
STMCU小助手 发布时间:2022-5-23 22:00
一、DMA请求映像
6 F- p( a- L- p3 d* s* u8 C, y$ J  T" p6 @, b6 B2 l
1YLUE2RBGHV5F8@~8WSCQKK.png + X" \$ o; }9 @8 @* s. p" d+ I
1VJ8YBP37AR3OVN}HCXSYI4.png 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
  1. /**************************************************************************
    ' m" h/ D/ B, g7 {2 ?
  2. *函数名称:  Dma_Init : |: r# d' w0 ~9 g+ z3 _" v0 b
  3. *功能描述: 利用DMA 把内存的数据传输到串口发送达到高速传输的目的6 z4 u: Y$ J* O' L
  4. *  
    - }. I% `& d* R/ }% r1 m* F  l9 s
  5. *输入参数:无
    ( J. X0 D, u! V2 O. l$ R$ |
  6. *返回值  :无
    ' X, h& A4 V3 _: p' [, P' a9 ~% I
  7. *其他说明:无
      y5 n4 S( I' W; O, {. Z0 |5 a6 A1 O
  8. *当前版本:v1.0 1 c/ [3 ~) ^. n- q6 O* l" j
  9. *作者     :尹宣
    . d* w3 F, J- ^( r" R, H
  10. *完成时间:2013年12月1日- C/ p7 o' k3 F6 z7 ^; l% q% v
  11. *修改日期              版本号              修改人              修改内容
    % T* Q% {, Z8 e  }5 R+ |3 d! f! y
  12. *-----------------------------------------------------------------
    4 ?$ T! l! _1 e; ]& p
  13. * 2 U% X% M1 i& Q4 H7 U9 `$ n
  14. ******************************************************************/ 3 j5 x9 a  ~# K
  15. #define UART_RX_LEN     5
    . b, d4 @  R; Z7 \! j4 Y& _
  16. u8 Uart_Send_Buffer[UART_RX_LEN] = {0x12,0x34,0x56,0x78,0x90};
    2 A2 D2 T! X* F
  17. u8 i=0;
    , o- l( G3 ?' ?/ Q/ s
  18. u8 Flag_Uart_Send=0;
    + ^/ c  v4 n0 F* I8 L
  19. 8 w  m' Y* H% k9 P0 i5 p
  20. void Dma_Init(void)0 U$ T3 o, ~' l: [$ e
  21. {3 x/ S6 U7 g3 ]: U. |
  22.   DMA_InitTypeDef  DMA_InitStructure;& G7 q. N1 ^0 s; N

  23. / v9 k5 A* [- B, s1 M. B
  24. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    1 _" q0 r* i0 `* g6 t# J1 x
  25.        /* DMA channel6configuration */
    ! h! r! H! C+ r2 D4 Z9 u. h3 y
  26.   DMA_DeInit(DMA1_Channel1);7 N. L( f2 }  w+ {2 w
  27. DMA_InitStructure.DMA_PeripheralBaseAddr       = (u32)(&USART1->DR);  //外设地址4 Q( Q7 O1 |& q0 `) W1 \, @" \
  28. DMA_InitStructure.DMA_MemoryBaseAddr                    =(u32)Uart_Send_Buffer;, \2 j. Y# h& `7 s% c
  29.   DMA_InitStructure.DMA_DIR                                      =DMA_DIR_PeripheralDST;   //外设作为目的地址   //DMA_DIR_PeripheralSRC;   //外设作为DMA的源端
    * O' M9 D0 r" D  m4 D
  30. DMA_InitStructure.DMA_BufferSize                          =5; //BufferSize;      //传输大小! C0 {( J: J+ B/ o$ ]
  31.   DMA_InitStructure.DMA_PeripheralInc                   =DMA_PeripheralInc_Disable; //外设递增模式禁止   DMA_PeripheralInc_Enable;            //外设地址增加6 Q5 Y0 p3 C8 h8 E% h  B- o
  32. DMA_InitStructure.DMA_MemoryInc                       =DMA_MemoryInc_Enable;   //内存地址自增
    7 E' Q  S' f0 _
  33. DMA_InitStructure.DMA_PeripheralDataSize         = DMA_PeripheralDataSize_Byte; //传输方式:字节   DMA_PeripheralDataSize_Word;    //字(32位)1 I( J2 i( s! v8 y( D
  34. DMA_InitStructure.DMA_MemoryDataSize            =DMA_PeripheralDataSize_Byte;  //内存存储方式:字节  DMA_MemoryDataSize_Word;
    ( t# Z- N7 [) o' J$ e3 T" d# v
  35.   DMA_InitStructure.DMA_Mode                                  =DMA_Mode_Circular;  //DMA_Mode_Normal 正常模式,只传送一次;  DMA_Mode_Circular:循环模式,不停的传送;
    # R  [* N9 B. p' L
  36. DMA_InitStructure.DMA_Priority                      =DMA_Priority_High;
    8 I( _) a, t/ t
  37.   DMA_InitStructure.DMA_M2M                                   =DMA_M2M_Disable;             //DMA_M2M_Enable;    5 n7 I0 c3 X3 l* p
  38.   DMA_Init(DMA1_Channel4,&DMA_InitStructure);% R5 k% V5 Z% Z, K. U: D, W

  39. & v" i/ Q8 q0 ?
  40.   /* Enable DMA Channel4Transfer Complete interrupt */) \$ L% `' E6 A" x; y: z, }" T8 P' e
  41.   DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);0 L4 N7 g* ?+ A! B, E
  42. //
    * A9 G7 L6 t& A4 S3 I" k
  43. // USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                                                                    //串口接收器DMA
    ) ?2 L8 R! c- X: @2 q9 J: k, o/ r
  44. //采用DMA方式发送
    1 I+ l( O- z; C  b
  45.        USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); 8 ]) {: D$ f, y! m. p8 t
  46.        //启动串口   4 q1 M2 \0 ~- B1 u9 ?- z& X
  47.        USART_Cmd(USART1,ENABLE); - M& h7 J* |4 ]6 d8 U1 ^) B  c4 d

  48. 7 E6 y; N8 I# d, S5 I
  49. ! h0 I4 h  I- @  |
  50.   DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);2 R- o5 l0 M" d
  51. 传输完成则进入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
  1. /***************************************************************** : G3 I5 y% U8 G& s7 S% a" h, @
  2. *函数名称: USART1_Init
    $ H, }1 V4 Q8 x, x) y
  3. *功能描述:   配置串口1初始化
    0 I2 c4 I. K( \, c8 ^) [8 k
  4. *  3 t# n% C* h, A. c; t
  5. *输入参数:无% ]  ~) Q) @' v8 s0 E  O
  6. *返回值  :无+ R8 O( o+ U. j6 P
  7. *其他说明:无! W( K9 ^( I, W5 K
  8. *当前版本:v1.0 + O- B; g8 K4 r6 v4 {
  9. *作者     :尹宣0 I2 ?4 D8 q8 o2 P4 i
  10. *完成时间:2013年12月1日/ F! v% G, w, e- {# f8 a# Q
  11. *修改日期              版本号              修改人              修改内容
    ' n" U: L  z7 {& j
  12. *-----------------------------------------------------------------
    7 w" [/ H7 i3 }2 z
  13. * ! g% O% W( h# f( k) V" I6 s
  14. ******************************************************************/ 5 r% ~' W! l# L! O, ?+ l
  15. void USART1_Init(uint32 baud). o% m8 g6 F0 V  t( b# {2 Z1 Z
  16. {
    6 z% f. Y2 s/ [: D
  17.        GPIO_InitTypeDef       GPIO_InitStructure;
    % Y" K2 y) R1 ^& D4 d" Q( K% {7 P
  18.        USART_InitTypeDef      USART_InitStructure;
    & i8 W/ X7 d) @% m/ L
  19.        USART_ClockInitTypeDefUSART_ClockInitStructure;
    - e  A+ P* n# \6 @! g8 Y" ]

  20. $ A$ f: c9 P. X& s7 o6 H
  21. . [9 `1 M. e& p+ R. [+ E

  22. + s% [; R  Z9 ?7 ]8 {9 m: M+ o
  23.        //使能串口1,PA,AFIO总线
    ; H1 V, d  C; f9 {
  24.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |/ O$ u* ~* A, z! T5 M
  25.                           RCC_APB2Periph_AFIO |4 M/ G$ i# f" A. `! h8 h
  26.                           RCC_APB2Periph_USART1 ,
    3 b9 N8 Y) e# [) \4 t  F! `
  27.                           (FunctionalState)ENABLE);1 R% L7 H- Q) [% ]

  28. $ f3 {& [) v- d5 o
  29.        // A9 USART1_Tx) q( g2 G! a* `! _4 s; w0 e
  30.    GPIO_InitStructure.GPIO_Pin   =GPIO_Pin_9;
    8 ^9 v  f0 D2 T0 W9 _
  31.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    / |* u  F# a3 i( T5 d
  32.    GPIO_InitStructure.GPIO_Mode  =GPIO_Mode_AF_PP;) V: |% o% y7 c5 K* i
  33.     GPIO_Init(GPIOA,&GPIO_InitStructure);
    & ^2 J; y: K" b, s# }! M, J

  34. 9 ?$ V2 N2 z1 E  q7 Q5 k
  35.     // A10 USART1_Rx
    . c3 H+ l9 M# y: H$ I* |4 _
  36.    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
    & q* R9 h  R9 q2 b* z; @; k+ s+ j
  37.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;6 b3 d% L$ h& i4 n5 Y1 i
  38.     GPIO_Init(GPIOA,&GPIO_InitStructure);
    8 ?" E7 h4 H5 }* P

  39. 7 X+ O5 N% T" q! @! q* z
  40.        USART_InitStructure.USART_BaudRate            = baud;8 S2 \1 @# U9 F- C8 ^
  41.        USART_InitStructure.USART_WordLength          = USART_WordLength_8b;* j3 @8 W4 y! O" i+ S8 c: H  M8 H3 h2 y
  42.        USART_InitStructure.USART_StopBits            = USART_StopBits_1;8 m% r6 W- x8 d$ J  x) B9 y, L
  43.        USART_InitStructure.USART_Parity              = USART_Parity_No;* P4 G# g0 h) z8 `( b/ H8 r
  44.        USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
    ) O$ S( y$ D  n( ^1 G% @" t" j! J
  45.        USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
    * w% X( o; a  f( ]8 ^8 ?1 P
  46. * w! U/ X: _" \$ I# Z  K( D: }
  47.        USART_ClockInitStructure.USART_Clock   = USART_Clock_Disable;
    6 i/ W" v" b8 H
  48.        USART_ClockInitStructure.USART_CPOL    = USART_CPOL_Low;
    ! E% k, Q* x! l/ p) S7 s
  49.        USART_ClockInitStructure.USART_CPHA    = USART_CPHA_2Edge;
    9 x. `' g9 i6 h0 P, f
  50.        USART_ClockInitStructure.USART_LastBit= USART_LastBit_Disable;+ F' q3 z0 W; x7 q# x
  51.     USART_ClockInit(USART1,&USART_ClockInitStructure);
    % C7 [( ^* \, B6 y3 Y4 {3 F

  52. 4 }( ?! P) J% b7 W
  53.     USART_Init(USART1,&USART_InitStructure);$ r/ g& \: ^/ }3 }3 F1 j7 N# u
  54.     USART_Cmd(USART1,(FunctionalState)ENABLE);7 r4 H" d2 t0 F% y1 _0 m
  55. //  USART_ClearFlag(USART3, USART_FLAG_TC);  
    & U: E6 c# @% C  ~1 b
  56.        //串口1使用接收中断
    ) D0 Y& H& {0 d8 J) d
  57.        USART_ITConfig(USART1,USART_IT_RXNE,(FunctionalState)ENABLE);
    4 R/ G/ [9 d* c5 Y' ?; ~
  58. }
复制代码
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 ?
  1. /***************************************************************** 4 Y$ t" {+ e4 K1 ]
  2. *函数名称:  NVIC_Config 3 d9 C" w# W' t* M$ x7 v4 Z
  3. *功能描述:   配置DMA的中断优先级: w. }9 f0 G- f! q
  4. *  : v2 ]. w, {( Y# @
  5. *输入参数:无
    7 Y$ i  Y0 E) D8 X3 {& g3 U( z
  6. *返回值  :无( M- h1 e+ }- n9 l0 x
  7. *其他说明:无
    9 D$ V- T1 f3 x4 b. G5 X
  8. *当前版本:v1.0
    ; Z) i# ?* C, m8 B6 _# a1 I
  9. *作者     :尹宣
    + `% D2 {- ^$ i3 _/ h; o( n
  10. *完成时间:2013年12月1日
    ; a# A/ y/ [7 i7 F& ?9 K! P; T
  11. *修改日期              版本号              修改人              修改内容: y* q2 ], ?1 X, k- A  ?
  12. *----------------------------------------------------------------- # y- o+ s1 m* C' }, D5 S: H4 p4 M% R
  13. *
    4 d' s# ?( X* c8 [. i
  14. ******************************************************************/
    0 u, P. ^5 P6 w# O0 [% S3 N7 w
  15. void NVIC_Config(void)( E. `9 X/ p/ Q" D* o
  16. {, s0 e2 w, j  V7 a; W& n
  17.          NVIC_InitTypeDefNVIC_InitStructure;  ( I* p( M  l; {3 [1 u
  18. * @) k5 b' Q+ B8 O9 l0 U# j
  19.          //DMA优先级        
    # U8 ~, I; d2 x) d& `# {
  20.          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);5 b# J3 A  q( H5 J; f9 X: q* y* w
  21.          NVIC_InitStructure.NVIC_IRQChannel= DMA1_Channel4_IRQn; 8 x# l) P& W5 K3 B6 E: n) ]/ O
  22.          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
    % z5 Q: J, ]. E8 V: B
  23.          NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
    , j  o$ I& z4 Y, F( I8 w: B" V8 c: n1 a
  24.          NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
    # |3 l( ]. L" r- C
  25.          NVIC_Init(&NVIC_InitStructure);
    7 N: I( k! ]+ _7 M+ |
  26.   X1 f' e$ T6 H) }
  27. * ]" B" |: m% i0 u' r
  28.          /*Configure one bit for preemption priority -------------------------------- */" O! w. T8 _: p0 R+ @# d4 ^% |; a4 K
  29.          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    $ z! S) m2 q: ?& j) X

  30. ) n0 z7 L  v) c! _5 O! L  I) Z
  31.          /*UART1 -------------------------------------------------------------------- */: m) _5 K! w# n- S5 M' Q( m
  32.          NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;. r9 t# V# I# n2 ^" D' c# w
  33.          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;# ^9 m5 G' u1 I; X
  34.          NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;8 H) L5 P: M5 V/ C5 D3 `1 Y4 D
  35.          NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
    8 M0 S% G$ _; w" `& u- D5 n, C
  36.          NVIC_Init(&NVIC_InitStructure);   
    5 }9 N/ L) Z4 K/ n

  37. 6 ]2 T) }7 d$ g" R+ k% ]
  38. }
    + 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; {
  1. /*******************************************************************************6 z$ Y) Q/ e# I, v+ Z; v
  2. * Function Name  : DMAChannel1_IRQHandler' W2 r6 k" J# g, ^$ M1 i
  3. * Description    : This function handles DMA Stream 1interrupt request.# k$ `/ j" B7 i; y
  4. * Input          : None: O7 J/ O3 `7 G1 V8 g6 j8 u! B8 \
  5. * Output         : None9 S0 R0 M. Q) z; K( ~
  6. * Return         : None
    9 J  f0 J9 @- Q  X0 k( B: @, @
  7. *******************************************************************************/
    5 u. Z. b5 J. l7 ?, ~. b% h9 \
  8. //串口1  DMA方式发送中断
    * F* J0 p, @2 N
  9. void DMA1_Channel4_IRQHandler(void)
    ) J# V" P/ V0 X+ e- o3 \# I
  10. { 8 g  G. T5 E' K* F
  11. : N7 h& \' [+ r
  12.           //清除标志位3 y8 A) r* |$ v9 A6 y: i- ~- z
  13.    DMA_ClearFlag(DMA1_FLAG_TC4); ( {! F9 T$ H+ U7 B5 B6 R) r3 o, N; x  n
  14.    //关闭DMA
    ' B& L; x  B1 J  z7 L
  15.    DMA_Cmd(DMA1_Channel4,DISABLE); ) C6 b! J) G/ `# Z  }7 @
  16.           Flag_Uart_Send = 0;
    1 y! \- g' g! z: M9 ^/ [. O
  17. . w5 Z& I9 G% X. J! Q
  18. }
复制代码

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 }+ | QH}2)5_)3TT88A}I$CW3B}I.png $ s; s' v" b" Z2 [% c, y6 u
7 ^8 u; c" ^; s. E" `

2 m7 n; u5 b7 n( a
赞 收藏 评论0 发布时间:2022-5-23 22:00

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版