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

【经验分享】stm32CubeMX+STM32F7串口空闲中断+发送DMA

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:07
1.配置系统下载程序方式
! R5 }: I2 K. L+ Q! g5 q2 ~+ c
20200901143057124.png

$ a5 }+ B0 v0 y6 l8 z6 M6 [' B0 a! d% u
2.RCC外部晶振
) y8 ^  W, z4 l) Y: y* O$ u8 P9 j/ U, w4 Y6 [$ i" b
20200901143329762.png
% D" d7 T4 w% [3 G4 c
6 V# y4 w3 _+ \; L4 g! H
3.串口声明
5 _& r& B4 ?* f" F' ~
' L# q- }; |/ I/ G. E
2020090114343042.png

) r: H$ E9 U2 b* ^( D, W2 `! k1 K* ?# h7 B$ L: N! _  k
2020090114350548.png
! f! S. F3 Z' ~( ~0 C" v6 T

! q! A! z6 `" k2 T# a! r4 G+ C6 j
20200901143544740.png

/ Z6 M! P. X& F& K# M! p' C$ }$ _6 G* q
" E3 ?* A  p& N* b1 L7 u- C9 e4.系统时钟
& m( K+ d6 n. Q" D' @
, e4 J3 e3 {0 m' G  ]2 T; n
20200901143654748.png

8 v" s0 g' `  S5 e2 w
' T' w2 q- ~" R( l, f* V5 e 5.生成文件根据自己需求配置
; V- J& n& U5 P/ a' f( O
* Z' `! z5 U. O: L' A. I
20200901143817649.png
; m8 }9 m1 R' z9 N1 U

8 a  \. f) l$ ?0 M' v 我这设置了所有库,可以选第二个仅需求的
" a  K: @* @( J9 N0 o
) e$ E1 R* s0 v5 l  ]3 _$ u
20200901143845598.png

4 R$ q& U3 u7 [: A
' B; D2 g* ?9 X6 {1 P  Y) w, z/ x 还加了其他功能,这里可不参考,DMA要放在串口前0 D2 I: e! V* w% P5 Y. {
9 r4 g2 i; @8 Y' K' @5 v0 d4 r
20200901144049245.png

1 |$ S4 z& J# @/ E8 D& e- P& f$ E2 P
6.生成后修改8 ]: v; Q* J3 s6 u) E+ Q

- g" I# v1 T* T! C. V+ e" z6.1 usart.h: m1 v8 B) F: r' s6 I2 W. t
) S8 D9 _( F# D' N9 f6 a- O
  1. /* USER CODE BEGIN Includes */
    + X0 c$ }+ ?5 Y
  2. #include "stdio.h": p. g  l  Q, ?0 T1 i: |2 w; V% S, t
  3. #include "string.h"
    * v$ q$ V3 g8 O# {
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN Private defines */8 k: T. x' C2 a& e' C! y8 D
  2. 2 T) B; A/ U+ z  O9 T  p9 ?% |# B! n  l
  3. #define USART1_DMA_REC_SIE 256% h/ g* }% J6 _9 @' _
  4. #define USART1_REC_SIE 512
    8 U, x( ^7 d3 E
  5. #define USART_DMA_SENDING 1//DMA发送
    ( s; a3 _5 w" k' s' R- i$ b1 z
  6. #define USART_DMA_SENDOVER 0//DMA发送结束
    1 w% C  g/ \; N# @" J/ `- ^
  7. typedef struct
    . |7 j# F$ \! ?+ K' S+ G# L6 h
  8. {7 g! g$ S4 T" r- J. g7 ?; J9 v
  9.         uint8_t UsartRecFlag:1;//接收标志! N0 g% R: s' x5 j
  10.         uint8_t dmaSend_flag;//发送标志
    ! B" l3 E2 q/ H1 G5 ~+ }
  11.         uint16_t UsartDMAReclen;//DMA接收长度0 q( p- [$ X4 p& M8 T- h' d
  12.         uint16_t UsartReclen;//串口数据缓存长度
    9 {9 y0 K3 D+ G8 }' t1 r
  13.         uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
    . p0 _& [/ y0 T: W& y+ J+ w
  14.         uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
    0 V+ s) t" {+ J5 |
  15. }teUsart1type;
    : }& c# V7 M* ]# n

  16. , K. N  Y" ^( E: g3 |
  17. extern teUsart1type Usart1type;//定义数据
    + i; R! }* B+ ?) z4 u; [

  18. 4 x2 ~6 R0 ~4 e; z
  19. void UsartReceive_IDLE(UART_HandleTypeDef *huart);
    - N8 M: f  x. D" b; j- Q
  20. void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);( V* J) _" Q0 t- |7 T. x
  21. void Analysis_Serial_Data(void);- u; g/ _$ ]$ g. \; D) M
  22. void EnableUsart_IT(void);, d. K, X. j: `* R9 c' d9 L7 I2 `
  23. - X& N% E( {4 x3 p
  24. /* USER CODE END Private defines */
复制代码
% @4 E8 q1 A' i3 _
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
+ n0 W$ |$ P5 o0 m9 _5 d' N9 x, p1 Z, D5 |: G" d* [
  1. teUsart1type Usart1type;4 H4 V0 V" U/ _1 ]
  2. /*****************************************************************************9 p7 g- q* P7 U1 ?7 B
  3. * 函 数 名  : EnableUsart_IT: }! y5 k4 X1 ]0 i0 Z& G( [6 W+ |
  4. * 负 责 人  : by
    6 ^! I: I7 G  \' i: A9 K
  5. * 创建日期  : 2020年8月26日( f3 [9 D  _1 ~! m, r( @
  6. * 函数功能  : 串口2初始化函数,空闲与DMA中断
    2 u7 B4 Y7 y5 u8 J/ I
  7. * 输入参数  : 无
    ! F- |8 z6 m/ w' y( b! G
  8. * 输出参数  : 无
      w+ R& w: K& P  D# R6 }
  9. * 返 回 值  : 5 t: F) L* ~8 T* w9 [% o+ o
  10. * 调用关系  :
    : Q- r" D3 N4 H5 V
  11. * 其    它  :   
    ; o, _) Q+ r+ c2 V2 I
  12. *****************************************************************************/
    7 e( Q. j/ |0 M: A% z# J2 }
  13. void EnableUsart_IT(void)
    , M7 H* `: P1 i* j% H9 A3 H$ I
  14. {   
    . S: i2 n6 T, a. m7 d2 W; Q- s
  15.     __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断* R9 `9 ?0 j! T- G, M, L  R
  16.                 HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
    ) i0 r4 j, s4 |# t; s" x
  17. }2 Z! f7 i) W* w  Z$ _  s# Q6 b
  18. /*****************************************************************************
    " ~( x4 ]6 B. W) N" J3 F  \
  19. * 函 数 名  : Usart1SendData_DMA/ \- g$ z8 V6 w; e. _, N
  20. * 负 责 人  : by2 r$ y# E7 n7 ]6 e& C
  21. * 创建日期  : 2020年8月26日
    * h: {+ Q2 [% b* ^. A7 N6 i
  22. * 函数功能  : 串口2DMA发送函数4 ~# y5 _: K4 t7 f# `+ \  K
  23. * 输入参数  : 无
    5 D" I% c$ G) o5 k( i6 T
  24. * 输出参数  : 无
    7 m+ Y. K6 L$ L& H
  25. * 返 回 值  :
    7 a5 A: Y* p- v
  26. * 调用关系  : 3 D8 Q+ E! T' N- f1 K
  27. * 其    它  :   
    # r: P3 l8 @/ s0 V* J# i! P6 Y
  28. *****************************************************************************/- Q' v6 U7 D! F3 [) O
  29. void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  
    : {3 F7 N0 T; g  Z4 @! x
  30. & f9 Q  W: O6 o8 _; f
  31. {  
    ( U$ Y0 ?4 N$ O  H
  32.         //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  $ j( G6 M; k+ M! F: X- q9 c
  33.         Usart1type.dmaSend_flag = USART_DMA_SENDING;  8 f( {+ n3 [9 u6 l5 L' ~1 F2 X
  34.         HAL_UART_Transmit_DMA(&huart2, pdata, Length);  + H4 u4 A4 M0 T# s
  35. }  
    % N# }1 O, w9 n1 p% ^
  36. /*****************************************************************************" [8 A1 ]( E3 a
  37. * 函 数 名  : HAL_UART_TxCpltCallback0 X. _, z% l% ^5 L8 _7 K4 W
  38. * 负 责 人  : by
    5 f, ~/ i  l' t$ k2 ~
  39. * 创建日期  : 2020年8月26日
    ; w2 X! V) ~/ B  m" G% s
  40. * 函数功能  : 串口2DMA发送回调函数& H" F' {8 o0 s: L4 c
  41. * 输入参数  : 无
    ( z: Q% [3 j: a  T! _  E
  42. * 输出参数  : 无$ @& K2 o8 v- ]6 t, K
  43. * 返 回 值  :
    0 g3 b# E# Z5 z" \( s4 ^+ |
  44. * 调用关系  : . E& z# |: s; C, g1 @
  45. * 其    它  :   3 M0 K/ n# ?" M  ?( h+ T. c
  46. *****************************************************************************/9 P6 d. [" ]  J
  47. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  
    - C! q/ H3 m: T5 A/ G8 c- b
  48. {  6 i% S3 c3 e+ q
  49.     __HAL_DMA_DISABLE(huart->hdmatx);
    4 E3 w7 F# @+ E8 e
  50.     if(huart->Instance == huart2.Instance)        
      h* T$ b8 h* L' E9 f/ D
  51.     Usart1type.dmaSend_flag = USART_DMA_SENDOVER;  " j$ S: m" m- W6 B& M
  52. }  7 W$ m8 W4 {4 ?& ~% ?5 m; l( m, ?; a
  53. /*****************************************************************************4 c0 Q9 W9 x5 H+ [( \9 l
  54. * 函 数 名  : UsartReceive_IDLE/ Q& G9 ?" j* R
  55. * 负 责 人  : by
    ) s5 M* k: @( n; B4 G# k6 g9 T
  56. * 创建日期  : 2020年8月27日
    # D) W& _- m6 U' o- P
  57. * 函数功能  : 串口接受空闲中断处理函数5 v5 d7 v# t* B6 K% N" P
  58. * 输入参数  : UART_HandleTypeDef *huart  串口句柄. r7 z, E9 o; ]
  59. * 输出参数  : 无+ [* d: ?% P) N5 d. o7 M
  60. * 返 回 值  : 4 m" o# V! `7 N6 e5 ^9 @
  61. * 调用关系  :DMA接收的数据缓存在USART接收中,释放DMA继续接收
    1 d) a5 O; [8 q/ _. O" h+ C
  62. * 其    它  : ' P5 T; I9 [! T; r3 Q# i
  63. *****************************************************************************/
    7 P) t) S- b  A$ Z6 g8 X+ P3 S3 W
  64. void UsartReceive_IDLE(UART_HandleTypeDef *huart)  y$ g+ f/ K, T  X7 w0 P
  65. {6 b/ |4 j* q1 d! h# s7 r% u
  66.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))5 C- C9 o& p, O0 q
  67.         { ( Q, p1 z. b) |' N: ^. |
  68.               if(huart->Instance == huart2.Instance)//判断是否为串口2' ?; k5 w+ _( r/ f2 S6 _
  69.                 {
      |# _# ~7 R+ y4 x% D1 }6 d, I7 f
  70.                  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //是否为空闲中断
    3 [! \/ ~# J) Z2 O
  71.                    {4 u* u9 y! `% c8 h* n8 d+ B
  72.                    __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //清除空闲中断3 h1 a8 {  x1 q) \
  73.                    HAL_UART_DMAStop(&huart2);                                                     //停止本次DMA传输0 l# k& L2 q/ V7 h, |  N- \
  74.             Usart1type.UsartDMAReclen  = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR;   //计算本次传输数据长度/ J3 e3 M/ e& K. t8 P+ @
  75.                                                 if(Usart1type.UsartReclen>0)
    - B2 p( m  k* ]- J/ \& j9 q
  76.                                                  {
    7 f$ j, O2 z# z( Y( j$ h
  77.                                                         memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
    & H9 t- o3 K# m) F
  78.                                                         Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
    * ~8 o6 ~9 d! K1 ?6 ^/ j" I
  79.                                                  } . u' F4 ?/ b6 o5 a' d* R
  80.                                                 else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
    / y) A( ~3 O6 X; Q7 |2 b
  81.                                                  {
    ! q* G( Q! @1 k* R0 A4 J2 i& U! @
  82.                                                          Usart1type.UsartReclen=0;
    5 N7 w3 V" ^& E9 c: w! e! @
  83.                                                  }
    7 x& p( E. u9 L  Y7 Z8 f
  84.                                                 else. u4 G# k. G: T7 |+ c
  85.                                                  {
    2 _* g# g5 `" u4 t& G
  86.                                                         memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
    " d  O. ^# Z8 k2 u- z2 j
  87.                                                         Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
    8 v( C5 o, t. g( N+ K+ [, |
  88.                                                  }                                       
    # S+ M8 G% t7 Z, _5 H8 d
  89.                                                 memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零                                                                                  d3 `  f" p; m% r3 [2 U5 V+ w
  90.                                                 Usart1type.UsartRecFlag=1;//空闲标志位置1
    $ \) X0 [( \: T9 Q0 [. o' |
  91.                         HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
    : i$ K4 C3 V. R# i- W8 @
  92.                                         }               
    ' v" R3 j# X6 E0 i2 d0 |1 ]
  93.                   }7 y; a5 ?# ]+ o* P
  94.         }
      u6 n7 g1 _. e# X9 ~+ O3 w1 X
  95. }0 k% ]) F4 L$ ^4 v9 A, U" Z& w
  96. /*****************************************************************************
    ' Z- X. R! s" u# Q; N9 N! j
  97. * 函 数 名  : Analysis_Serial_Data0 g7 u, H$ b+ x+ R% K0 s
  98. * 负 责 人  : by
    + B  T9 M" C  z+ Q. N. E+ t
  99. * 创建日期  : 2020年8月26日0 ^% K7 @2 a9 t+ O1 s( g
  100. * 函数功能  : 串口接收数据直接打印3 {+ i9 `9 w+ [: U, d
  101. * 输入参数  : void  无
    - Z1 V9 v' a9 B$ o) i* B/ d7 x
  102. * 输出参数  : 无
    , E% v% I: h0 g! S7 I
  103. * 返 回 值  : void
    # \( t5 @$ V8 x" C& _. V
  104. * 调用关系  :
    6 j  I# O; H- P2 ]# y
  105. * 其    它  : " a$ p5 H9 l' g! Y2 y1 H0 j/ z! p
  106. *****************************************************************************/- d/ o, K: |1 E% y
  107. void Analysis_Serial_Data(void)
    2 i0 c9 N! t+ I; N) z& Z0 w
  108. {
      ?  c& D! v- |7 y4 }5 t8 |
  109.                  if(Usart1type.UsartRecFlag)- n" n/ V  N; P: l! r2 V, V! A
  110.                  {                                 
    2 w, R5 i/ [7 A) b- S
  111.                          Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);        
    ! I/ Y$ G! K( e2 c  f, D
  112.                          Usart1type.UsartRecFlag=0;$ t+ |; f: E8 ]
  113.                          Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理         * `3 U) i. l& x+ g8 D9 z# u. K0 ?
  114.                  }
    , Y) ]5 L! l9 f1 b8 H4 R0 f; K
  115. }. `" |+ D1 z1 _
  116. /*****************************************************************************
    : F* \/ B! G: S; s* U
  117. * 函 数 名  : fputc4 G3 V* {) P% B% ]. @7 U, W
  118. * 负 责 人  : by4 i% [# C* `- N' s" d9 a
  119. * 创建日期  : 2020年8月26日/ p, ?' G) b5 C; E
  120. * 函数功能  : 串口2 printf重定义
    : p* q. n$ D9 D7 M3 H/ D" k! J
  121. * 输入参数  : printf(d%/s%/%c,a)
    ! q5 E, d: _# n7 K  ~( Z
  122. * 输出参数  : 无' B4 W2 I5 k% Q; J
  123. * 返 回 值  :
    + M; l, \2 R" b- y0 n: R8 Q, t# k
  124. * 调用关系  :
    8 I/ y4 l6 _7 g8 O( Q
  125. * 其    它  :   / u1 T! H1 Z  S7 [4 e# j
  126. *****************************************************************************/
    ; |& i7 l; Z' j2 g1 B, a/ L
  127. #ifdef __GNUC__
    $ R! ?  T% Q! c: i# [+ {

  128. 8 W- S( P$ Q- T, v
  129.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf7 `6 o, N' |+ m. F! l
  130. set to 'Yes') calls __io_putchar() */
    0 I8 K$ |+ |6 _8 z
  131. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch); h$ N, L, q9 G8 t
  132. #else! j$ A# Y1 O4 q. @' V
  133. : K4 B  f0 ~7 l$ O6 ]% e: J+ m
  134.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)2 @; j4 e7 a8 C6 A/ ~6 H
  135. #endif /* __GNUC__ */
    1 Z0 E' H9 b) i& V* I1 y9 _
  136.         % S& u4 H# Z7 F3 {2 A
  137. PUTCHAR_PROTOTYPE6 `9 b  H- F! G, |" a
  138. {
    # l, j- C; R. W! y5 S
  139.         HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
    2 d- G' x& T3 c0 A" @
  140.         return ch;
    ( x- O% D/ p3 a
  141. }5 m4 [6 a* x$ a, @) U% q

  142. % D5 ~0 c% d# C& v( A

  143. 0 G) J9 `, u* V% d* a3 [4 Q
  144. /* USER CODE END 1 */( a8 L" y) r. f( M& N7 g/ `( d
  145. DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。( O2 A' }0 ?( T# Q" j& J5 w

  146. + G: f4 u; X3 x! W) }7 e; |; `
  147. //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
    & a' @; T+ u. c0 C; E: \: m
  148.     Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
% O7 |3 e3 B' q) J: Q' L

5 l0 @  b: K! s6.3  主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数
  1.   /* USER CODE BEGIN 2 */
    0 k  k) |& s# R" K6 [$ j! j7 Q
  2.   HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
    ) e' S6 d# N$ m9 @- R: i$ k
  3.   HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
    # `; J/ F# [1 D8 g/ h
  4.   HAL_CAN_Start(&hcan1);/*can初始化*/0 c; X1 B  X$ S( ^9 `' Y+ D/ E
  5.   HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);                        ) s9 j  P0 O& B. u/ b
  6.   EnableUsart_IT();/*串口初始化*/
    5 |: r& R. ~# n) M" J4 x
  7.   CAN_User_Init(&hcan1);        
    * s" U! F) C+ r* |
  8.   /* USER CODE END 2 */
复制代码
0 c9 L- E+ `7 W* ]8 t* v/ ~
循环,对应数据输出9 `) z1 J* f* [4 B4 o
2 p0 \; p" G# ]" d0 r0 J
  1. /* USER CODE BEGIN WHILE */
    . S7 [( \" F* Q5 G' B8 f& m
  2.   while (1)4 g" y$ r  |+ \
  3.   {                3 ~( ]# n+ }+ P2 T
  4.      Analysis_Serial_Data();
    - @" [3 a% O2 w3 K  ]& N/ d/ q' a- x# ~
  5.     /* USER CODE END WHILE */4 N, y$ w% n8 N( r8 {6 {

  6. 1 k& m% `4 n1 K9 V+ m
  7.     /* USER CODE BEGIN 3 */
    6 w: V3 X# a3 w
  8.   }. [+ t2 a2 z9 D- B# {1 J
  9.   /* USER CODE END 3 */
    * K! c1 C9 s( \4 c
  10. }
    2 B* m+ Q( B- L  Q
  11. 7
复制代码

3 x, }  ]2 ~& ^( G: L, \、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误+ P3 m+ ?) I. A" f1 ?  P

9 ~7 M; r( k7 b0 B
2020090115084313.png

% Z! E* T  J' F  x7 i* H
% m8 @1 g! Q' `8 h6 B4 j; y; V. N7 p. B$ k: [$ x4 m8 g
赞 收藏 评论0 发布时间:2021-12-14 10:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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