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

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

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:07
1.配置系统下载程序方式
- _3 U: \9 `6 f- m# v  E6 _2 y0 o* m7 l% ~6 R8 B
20200901143057124.png

, a: z: S# e! \3 I5 _# \6 a, V4 L! c( }1 d
2.RCC外部晶振
$ N2 o. n8 ?6 J& u. \) y; d# x  D& k. C- |% D+ W$ n4 ~
20200901143329762.png
4 I+ N& {" W, o- ^- n' z: V# J
, u/ z/ P4 T2 \/ e& Q1 m
3.串口声明
* |" J8 V2 X5 E! }( J% Q! r4 t3 N; S- k
" [* I% K+ L. M! M! a
2020090114343042.png
3 m2 n3 }4 `. K+ u4 t* j

- @) z) D# j( o
2020090114350548.png

4 _- f5 s1 I: e2 T! P: ~8 I0 \0 b, V
20200901143544740.png

9 `, g, L- q* }7 i7 q+ S- ]6 \; H( J
4.系统时钟- y2 I# ?$ }+ ^1 p& X  A9 i* n

" o: q1 U$ u' w8 _. q  a% {
20200901143654748.png
7 R" E, Z3 n3 z0 I- u
; |. f2 ?, ^, M
5.生成文件根据自己需求配置
; T1 A# z) T: H% h8 L- Y& w
, J2 |6 ]' {2 h, M# G
20200901143817649.png
& p$ H: N( O# R! b& I3 P/ U
1 F( J* o8 x' n  Z. `
我这设置了所有库,可以选第二个仅需求的& `. e- C6 Q- ?* B8 w6 j# n3 Z% M

5 n8 z' |' x6 p4 p4 i: h
20200901143845598.png

7 c. }2 Q! ]+ G2 P) E0 v2 w7 G, J
% e$ d# J  D5 }9 G9 M 还加了其他功能,这里可不参考,DMA要放在串口前
: r% R/ n: {# r
$ G' ]. s8 ~! Q: A/ b
20200901144049245.png
% {3 e, N( X1 h, v' Y* `- ]* G5 `
. w: J+ R2 e( `
6.生成后修改
4 c3 ]) R! F# Q% X3 y( k
0 F0 f9 b% ?5 ^' I  }1 U6.1 usart.h5 L5 M& E" N; l- f: g1 {9 ]& c( M
9 k$ E* F0 x% S9 |. x' _: H; o
  1. /* USER CODE BEGIN Includes */
    7 B; Q: _. X5 T) r4 b( R  n
  2. #include "stdio.h"" F: I0 ]- k5 Y# v
  3. #include "string.h"" X$ K' x: J2 |0 {. i* N
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN Private defines *// ]4 F) V0 c7 i% h8 \
  2. ) h) t) l0 D0 o1 k  i( t5 E9 W
  3. #define USART1_DMA_REC_SIE 256
    1 g; x+ I' L9 r
  4. #define USART1_REC_SIE 512# Y  b# K) r7 c
  5. #define USART_DMA_SENDING 1//DMA发送
    # u9 q+ ]& a* n7 ~, v6 n: R
  6. #define USART_DMA_SENDOVER 0//DMA发送结束
    ' e/ \+ X4 Q: P  y4 {
  7. typedef struct
    , O) X: M7 h$ M9 j& X6 x" A
  8. {9 y! K& k; [# V5 B; l( A
  9.         uint8_t UsartRecFlag:1;//接收标志
    1 X( K) z% f. u8 J/ A/ ?
  10.         uint8_t dmaSend_flag;//发送标志
    ; e5 R& v  ^0 C! v6 J: ~
  11.         uint16_t UsartDMAReclen;//DMA接收长度
    # y; y5 m7 B+ g% F* [, Q: t
  12.         uint16_t UsartReclen;//串口数据缓存长度
    / S' u( T; I; @# S0 T9 F3 X
  13.         uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
    4 w( ?- p: W3 ?  h6 E2 i4 a4 M7 a" W
  14.         uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
    * `. L* a  n# ^3 K6 E
  15. }teUsart1type;
    & c1 {' s, ~* q! W9 o

  16. : j5 x. X. h8 r: Y; X8 v
  17. extern teUsart1type Usart1type;//定义数据7 d6 C+ q2 Y* r. T' \" j

  18. ' j- x2 v. h$ n0 x: }; }
  19. void UsartReceive_IDLE(UART_HandleTypeDef *huart);
    0 n  p! ?# e6 ?/ I- E: f, D; Y, H8 w6 X
  20. void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);& s8 k; F8 C' w* ]0 r5 c# `& k5 T
  21. void Analysis_Serial_Data(void);# ]* e2 E  j. M6 w% ~" u. h
  22. void EnableUsart_IT(void);& Q9 p- k4 a0 C! ]8 ?. o- P7 G
  23. 0 ?: c  U" e1 i* p! J
  24. /* USER CODE END Private defines */
复制代码
% m2 M% m# H' u8 P: Q2 a1 a1 K" l
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。6 t* n* \: T0 P6 [2 ]1 v, S

. k2 G: ^, c0 A* s
  1. teUsart1type Usart1type;$ t( t7 g6 @: H7 p2 ^; ^7 h
  2. /*****************************************************************************
    + S8 E/ A' w5 R" @5 C/ a
  3. * 函 数 名  : EnableUsart_IT8 \0 p" F% {  K. A
  4. * 负 责 人  : by  M  A1 L3 M4 K- [9 ]% O& P
  5. * 创建日期  : 2020年8月26日
    ( e+ V( [% r, ?6 P4 r  K
  6. * 函数功能  : 串口2初始化函数,空闲与DMA中断
    % u* l  N$ U6 J" x0 s
  7. * 输入参数  : 无
      N: w- n, m" A3 r) E1 T
  8. * 输出参数  : 无
    & u3 ^* v6 z% \$ o6 s" ^, s
  9. * 返 回 值  : * P5 D: j5 [6 i7 u$ e. y1 \
  10. * 调用关系  : 9 I( G6 ^) ?, \
  11. * 其    它  :   
    4 g: i3 }$ U% f) N0 U: B% v
  12. *****************************************************************************/  }7 I. l3 E: a
  13. void EnableUsart_IT(void)) R2 Q  U' m7 b6 s7 p
  14. {   2 M: v& h) {! ]" n* ?1 ]& L
  15.     __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断: |% w/ U( ~7 O0 g0 {% Q
  16.                 HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
    7 C$ n- T. I9 z/ d' ~
  17. }6 b+ j5 S; p# k* P; r. R* f3 T4 d
  18. /*****************************************************************************( ^/ ]: j4 R% T* G- {& S
  19. * 函 数 名  : Usart1SendData_DMA$ O( p: \  E% G' q  B3 `
  20. * 负 责 人  : by* e: r3 Y* H* L/ s/ G2 }
  21. * 创建日期  : 2020年8月26日
    : S4 l/ n3 s+ v$ P9 D
  22. * 函数功能  : 串口2DMA发送函数
    " Z3 A2 Q  W5 b5 o0 l$ L
  23. * 输入参数  : 无; o% y. X; T$ E
  24. * 输出参数  : 无
    1 a& m/ R7 A/ O8 v
  25. * 返 回 值  : . s5 x5 ?5 i" ]1 n8 u4 t
  26. * 调用关系  :
    3 o) }. Z4 M5 Q' c+ S6 E
  27. * 其    它  :   # c: @2 ^: N; L: n
  28. *****************************************************************************/
    ( b0 |8 Q. H# ]: E; }( o2 |
  29. void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  
    & [7 c7 Z& @- U$ {

  30. + b8 E2 X& I* a  ~
  31. {  
    ; |6 T- E1 m! ]5 n) x
  32.         //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
    ! n- Q7 H% F$ K, z* \8 M2 i( h
  33.         Usart1type.dmaSend_flag = USART_DMA_SENDING;  
    ; O1 e' p1 V) K7 ?0 Q3 s
  34.         HAL_UART_Transmit_DMA(&huart2, pdata, Length);  
    ' D. M# x; L: V& [8 i5 e
  35. }  ) T. e4 ^" _! y/ E% X( l7 q4 O/ ?, i
  36. /*****************************************************************************
    9 |, O9 ?, g/ [% `- z% B1 K
  37. * 函 数 名  : HAL_UART_TxCpltCallback6 M+ E4 t$ o/ n
  38. * 负 责 人  : by
    5 u& p+ R* ^4 R8 M5 @" g5 w
  39. * 创建日期  : 2020年8月26日1 |$ ]0 y( ^# b: g9 i* i# w3 z2 H
  40. * 函数功能  : 串口2DMA发送回调函数
    ' n: h9 O9 j) _5 ~
  41. * 输入参数  : 无
    % ?1 {: m7 o/ ]; g/ W6 @( W) y
  42. * 输出参数  : 无
    " V" ?% h% ?8 t
  43. * 返 回 值  : & Z7 e/ V; t" t8 U1 {1 N
  44. * 调用关系  :
    8 r( M3 J  I2 W9 k5 p) Y5 n
  45. * 其    它  :   , f$ E/ ~5 Y% U! V9 D3 s& D5 i
  46. *****************************************************************************/# C( e8 m9 Z! `) H
  47. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  6 D0 ^5 U7 L# p( h4 h/ V" b
  48. {  
      k( u: C0 J# ~( O& `6 H
  49.     __HAL_DMA_DISABLE(huart->hdmatx);
    + ~2 ?4 Y9 ?& D
  50.     if(huart->Instance == huart2.Instance)        9 ?8 u" O9 ~& q9 }! ?
  51.     Usart1type.dmaSend_flag = USART_DMA_SENDOVER;  
    & X/ _0 x$ \5 L$ o4 V2 j
  52. }  / K- O: P  n3 x1 R% C& S$ K& ?
  53. /*****************************************************************************
    " X* \5 B* M5 y5 g- `
  54. * 函 数 名  : UsartReceive_IDLE
    / M' `% o( m$ g. ?1 F7 V8 v" k5 N
  55. * 负 责 人  : by
    : f: w2 t4 @7 A. c% x; ~# }
  56. * 创建日期  : 2020年8月27日
    % q/ Q1 o+ W" `, p1 L  K0 `5 g) Q
  57. * 函数功能  : 串口接受空闲中断处理函数: Z: @+ l- u' G+ q0 ^: c6 Z7 z! Q
  58. * 输入参数  : UART_HandleTypeDef *huart  串口句柄
    2 r5 N7 d; l6 ~' m1 A2 x: o3 U
  59. * 输出参数  : 无$ w3 x7 `. o8 S4 e0 p
  60. * 返 回 值  :
    , {% E0 S  L% Y  E3 \  J/ V2 e! B
  61. * 调用关系  :DMA接收的数据缓存在USART接收中,释放DMA继续接收
    + P- m. |9 X, N4 H% E
  62. * 其    它  : 8 n9 q$ e: o* W, c  v* k- l
  63. *****************************************************************************/
    + U3 M( R3 g- v
  64. void UsartReceive_IDLE(UART_HandleTypeDef *huart)- E& M0 ]) E' D. y6 j) ~9 Q
  65. {
    3 n2 x$ {' I  L9 k( W: }
  66.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
    ! B: x4 B( s) b  `% s8 d. j" k
  67.         { / h- q: B2 V  P( F) X9 z( F" i, h& I
  68.               if(huart->Instance == huart2.Instance)//判断是否为串口2/ N4 p8 m3 t2 b4 D9 g
  69.                 {
    ; ~* K- v8 `2 @! d3 f! s
  70.                  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //是否为空闲中断
    3 H; j; t& ~  u$ l
  71.                    {: b7 i4 {8 I- E% f$ @: L4 T
  72.                    __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //清除空闲中断
    7 P& W5 X/ @' H$ g& z$ B7 X
  73.                    HAL_UART_DMAStop(&huart2);                                                     //停止本次DMA传输0 b5 R2 X* P( f3 V, C; r
  74.             Usart1type.UsartDMAReclen  = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR;   //计算本次传输数据长度
    $ M$ B( Y  I/ ?; \
  75.                                                 if(Usart1type.UsartReclen>0)
    % P) i1 B7 I8 C
  76.                                                  {$ L0 P% t! q; a: i- ]+ E
  77.                                                         memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
    9 n! b7 P2 N3 o
  78.                                                         Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;; |1 f8 P$ R* H. k
  79.                                                  }
    8 M* a& A3 o" L/ ^" _5 G, J+ a
  80.                                                 else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
    ; E( N5 [4 f8 O1 J
  81.                                                  {. E/ d, C. L& ]7 u
  82.                                                          Usart1type.UsartReclen=0;) N0 G, y6 l1 l
  83.                                                  }
    : C% G- Y9 C+ Y0 [: J' @
  84.                                                 else
    : j) c* i- G# p5 v& {1 a  ^
  85.                                                  {
    % R1 i& j) a" L3 H# r* a
  86.                                                         memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
    # R8 `9 g7 O9 y" R* Q. X$ C4 n
  87.                                                         Usart1type.UsartReclen=Usart1type.UsartDMAReclen;# t7 U3 u" Z& B* E4 C% X' x
  88.                                                  }                                        7 A4 u0 `) P# b4 W: D% @% T
  89.                                                 memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零                                                                                
    7 J4 }7 k; i4 H: J  v  \' m! _
  90.                                                 Usart1type.UsartRecFlag=1;//空闲标志位置1/ l0 \+ g4 z1 m4 B0 c
  91.                         HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA$ X* {6 J/ U+ ~% w' y
  92.                                         }               
    8 ^( H& h" }& Y  ^: z
  93.                   }
    * j3 w/ G) h+ N+ ~8 o% D
  94.         }
    % t' N6 \; J* U) {6 l( [" E
  95. }
    ! D# n0 u$ l. x, K8 @6 \
  96. /*****************************************************************************+ t3 w* s: q, S
  97. * 函 数 名  : Analysis_Serial_Data
    0 Z* p' C6 p% P7 d$ j
  98. * 负 责 人  : by+ V. o5 h) _: E  g2 I, j% I
  99. * 创建日期  : 2020年8月26日6 ]) U3 Q2 j9 M$ k
  100. * 函数功能  : 串口接收数据直接打印
    4 H! f" g2 E3 I
  101. * 输入参数  : void  无
    2 w0 d4 w; c! }7 w8 a
  102. * 输出参数  : 无# _/ Z; h$ R4 u1 D  Q( `$ `
  103. * 返 回 值  : void7 k+ Q' }6 p1 a) h5 _( ]8 J& I
  104. * 调用关系  :
    1 \. X  p, O& A: p4 ?
  105. * 其    它  : ! ]3 v/ }& ~, _
  106. *****************************************************************************/' j& j% B% v, t& R7 W, B
  107. void Analysis_Serial_Data(void)
    % }$ H* J! v- U* Q, Z0 {( x8 C
  108. {5 t4 g" A# C3 y, M* ~1 Q
  109.                  if(Usart1type.UsartRecFlag)$ A' T* L" `+ J$ O/ u* B5 y
  110.                  {                                 1 K! d+ S# q. i1 z
  111.                          Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);        + m9 T. s1 |+ |. u
  112.                          Usart1type.UsartRecFlag=0;
    $ k6 a* B9 K- [/ Y9 J, E( {
  113.                          Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理         
    5 N* W8 F# E0 }, S% C$ A8 L% a
  114.                  }$ ~, z6 b$ y! c7 d, T6 X, o
  115. }9 }0 ^; T- z3 i' i- l# f
  116. /*****************************************************************************
    ) i9 Z* r0 {- u: S
  117. * 函 数 名  : fputc8 @" R) s  V* l9 m5 e0 D
  118. * 负 责 人  : by9 V( I# i. A* ?2 p; O4 Q/ P3 y
  119. * 创建日期  : 2020年8月26日8 A" e1 p6 W' f( M4 `5 Y
  120. * 函数功能  : 串口2 printf重定义
    . C( m8 X0 l6 c9 B- A
  121. * 输入参数  : printf(d%/s%/%c,a)
    ; w& n4 s  [, V7 M: \& a
  122. * 输出参数  : 无
    8 E/ b8 e4 O5 f  s' D; t1 j
  123. * 返 回 值  : 6 R! A! H# p% q# E  t0 ~- v9 R
  124. * 调用关系  :
    , d! R5 W6 G, Z( }: X: d
  125. * 其    它  :   : F. s. G' N% ]7 K5 Z4 _
  126. *****************************************************************************/
    2 }, B& F! ~/ r% R0 A# y
  127. #ifdef __GNUC__
    + z/ s3 D  z5 T- Q3 X

  128. % V. Y) J; R- f3 W' w9 k! Z
  129.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    " `9 x- F  Y$ V2 Y
  130. set to 'Yes') calls __io_putchar() */
    1 I! @  w; X. h9 K- N: C3 b& z
  131. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    3 w) _5 w) |9 r4 d4 n
  132. #else
    " }7 c( i- S$ f" l4 F: j
  133. 9 m1 W7 A' q/ T$ @4 ]
  134.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    8 z) t) y" o: a1 y, M
  135. #endif /* __GNUC__ */2 H! p! \! n# n7 p
  136.         # P; P8 r& S/ J( K7 j  E
  137. PUTCHAR_PROTOTYPE
    : t4 ~0 ]5 _/ j$ x
  138. {* y8 s* ]9 Y* N: y4 J
  139.         HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);4 l$ o, V* Z. u0 Z
  140.         return ch;
    ! B+ S% P, I6 P4 K* Q' }2 h
  141. }
    ! p0 p. V0 W9 x3 |; y: Q( h" S

  142. 4 P9 f! d% P$ M* L% y. J
  143. ; R: f1 h! e! x0 N9 `0 h, s* L& m
  144. /* USER CODE END 1 */1 ?9 V) r& N! H& D
  145. DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。" z" Q1 B6 _6 V

  146. : U. ~* `+ P/ a, B6 m* N9 }
  147. //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  / W1 l, K( a2 G
  148.     Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码

/ p- t  D. r; ~# q$ B3 }0 V" r6 J
$ c: `& e$ U* A. W( t: ~9 G6.3  主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数
  1.   /* USER CODE BEGIN 2 *// Z# L$ O% {4 T8 I) ]; o! `
  2.   HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
    & C' b# X, T% z
  3.   HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
    & c9 g7 J8 G4 W$ E4 }6 C
  4.   HAL_CAN_Start(&hcan1);/*can初始化*/
    - p( V  v8 t. J7 e1 Y5 N
  5.   HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);                        
    9 T3 S  t0 x& I+ F3 S$ [
  6.   EnableUsart_IT();/*串口初始化*/7 K- ~. J  O6 \' a+ C8 C/ ?
  7.   CAN_User_Init(&hcan1);        
    0 J$ b3 j! z6 J$ |& T$ q0 D) C
  8.   /* USER CODE END 2 */
复制代码

! z* T9 D+ c& m2 t" {& N% _ 循环,对应数据输出1 t/ d# v6 A0 V% @! j
3 p! H7 f5 A6 Z2 u' u0 f
  1. /* USER CODE BEGIN WHILE */6 H* P6 W' j1 s7 x# _. c1 a9 m
  2.   while (1)& p% D+ |7 V! n# j8 }2 y" r
  3.   {                + S% b% a1 m- A4 }1 U! G) D
  4.      Analysis_Serial_Data();  P6 Q+ k4 F4 D& {( `+ u8 n4 r: R
  5.     /* USER CODE END WHILE */4 O/ p& X% n4 D) ?* p

  6. % v7 x4 `1 d5 ^; B# u9 N
  7.     /* USER CODE BEGIN 3 */5 D- Z5 e: @8 x( }
  8.   }5 k. `5 G* S$ l4 |3 E! B( M: X
  9.   /* USER CODE END 3 */6 U6 P6 y% \! O1 r; u* q  _
  10. }0 p+ s' j1 k- L+ J1 Y2 y
  11. 7
复制代码

/ a; L9 `/ `! x2 r/ `、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误
. u: S0 X* D# t3 M- x$ `7 H3 d4 c3 i+ `: a+ B; N+ [2 m
2020090115084313.png
% @7 b  K" B; r' ?; R  L
8 p, i/ N' K6 Q9 `- t8 {

0 h/ [: e% y( {: ]& ^! j9 V
赞 收藏 评论0 发布时间:2021-12-14 10:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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