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

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

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:07
1.配置系统下载程序方式
3 P, ~2 l1 p+ y5 k) `2 {
: m% m( X% w: M9 ], L; u# n
20200901143057124.png

3 A# x1 h/ W0 D: k/ ^. I3 y% t5 D) k4 |+ @( k2 Y
2.RCC外部晶振& C3 Q0 P* e; W
# I/ B& w, [5 @% u0 W0 a
20200901143329762.png

% R/ S; `* h3 n' l% F$ D
) j- X, O1 |# K% h8 S- V 3.串口声明
+ X0 V2 [6 ~) N. v. D9 c6 \& E( s: O0 r- ^
2020090114343042.png

1 g! q/ O, A( V5 G$ I: i
6 I) c% I7 A; Y) b: Z6 s1 U' P
2020090114350548.png

- Y* `3 e3 b0 j$ Q! L1 f- Z. Y+ W) b% H! W! n
20200901143544740.png
: Q1 @0 _( M! @" |8 W1 C# b

" ?8 D* w3 a) R% {! G% [4.系统时钟2 a3 J) |3 K- E- `8 G% k5 H

2 L# W8 g' y3 D- [- z1 ]3 d
20200901143654748.png

0 {: a. O$ f: M
. r5 `0 B* \/ [$ Y6 Z5 I8 i" g# K 5.生成文件根据自己需求配置
& ~6 f1 T6 F7 V+ ?  R
( x- ^# j- W0 Q& Q" f& R
20200901143817649.png
; g, O6 C$ F- x( [' S& P9 P* {
+ L0 G* U- [2 G1 P( }! P
我这设置了所有库,可以选第二个仅需求的
" V4 W: A) u( `" ^( @: l1 L/ J0 s
8 q% K& ]$ _9 T& }# t2 m
20200901143845598.png
5 J$ B  R) X/ ?( B

4 C" ~0 |1 H6 w! B 还加了其他功能,这里可不参考,DMA要放在串口前# C$ j& e( w6 r1 q9 r' J
7 Y. ~, c8 M  L$ k& Z
20200901144049245.png

1 d* Z( ]2 _% P! B  j  m0 ^9 C+ ?+ f( H$ P+ g
6.生成后修改
* b( j2 ]" q& }, A% j
! ^: \6 R2 S2 a; p  Y9 w0 o" x6.1 usart.h
1 {- Z9 O. G0 G# F6 k
# Z9 G- ?  A# {, Y
  1. /* USER CODE BEGIN Includes */
    7 C( V8 }& p$ W' C/ \
  2. #include "stdio.h", t3 Q/ k# i3 V4 y
  3. #include "string.h"* w/ C. D* N6 E( R
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN Private defines */
    . e# I; r4 C, p$ M) Y' S
  2. , L5 I  `9 ]+ u" a
  3. #define USART1_DMA_REC_SIE 256
    + Y3 w# ~4 V4 g+ [
  4. #define USART1_REC_SIE 512" a' W1 {0 w. d: r1 O& K# |( C/ g! A
  5. #define USART_DMA_SENDING 1//DMA发送 * P! o- Y. I  z. L7 v( g. X  }
  6. #define USART_DMA_SENDOVER 0//DMA发送结束
    : T% ]2 m  ]) d
  7. typedef struct
    ; |+ d5 [  c0 F8 g. I
  8. {
    9 D* K1 P7 c* _4 s; n# T9 n+ v
  9.         uint8_t UsartRecFlag:1;//接收标志
    ! }* Q( }& w/ R7 A/ z  _
  10.         uint8_t dmaSend_flag;//发送标志  T: G  ]. Y) `! U5 e; b
  11.         uint16_t UsartDMAReclen;//DMA接收长度8 `9 C6 @( d3 O4 h; V' r# P" q: G9 y
  12.         uint16_t UsartReclen;//串口数据缓存长度& H, w+ Q( O/ f* \
  13.         uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据9 o0 V; l2 i0 c4 L9 s
  14.         uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据6 w. ]) ~$ s# u% K% x
  15. }teUsart1type;3 i% W* v; l. F) |6 {6 K+ ?
  16. 3 g/ {' M0 _& w8 C
  17. extern teUsart1type Usart1type;//定义数据0 A' s# E$ N" Y* ]- v2 V' M" Z

  18. ' t, z( [- ^! S1 C: M' Y8 J
  19. void UsartReceive_IDLE(UART_HandleTypeDef *huart);
    " `' r2 c2 r: l6 j! ^4 w0 |
  20. void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
    . D* V$ O0 Z. b8 `' _8 z: O9 ]3 @
  21. void Analysis_Serial_Data(void);
    3 i) E0 M( [5 k, M) G, S
  22. void EnableUsart_IT(void);
    7 u- ]5 m8 _) \2 {

  23. - \- W2 Q8 X0 m
  24. /* USER CODE END Private defines */
复制代码

3 e* j! U! d$ D# Z( n4 Q6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
8 x$ D1 l) i& R( v
8 E8 ?* H& C8 @: v
  1. teUsart1type Usart1type;
    + b3 s9 T7 v! d$ T/ f) ^9 g+ M
  2. /*****************************************************************************0 X" _% N; C/ Z
  3. * 函 数 名  : EnableUsart_IT
    6 F" y% o2 v1 T2 H  p+ ^
  4. * 负 责 人  : by* ~7 I9 P( u% ~4 [6 Q6 H: S
  5. * 创建日期  : 2020年8月26日
    : S: [- t- Y0 W" O  @0 P: e
  6. * 函数功能  : 串口2初始化函数,空闲与DMA中断
    $ w7 t: B5 Q( Z2 o% V. h# Z
  7. * 输入参数  : 无
    5 h. z, V$ Z! o6 }2 m1 ]( X4 S
  8. * 输出参数  : 无
    " l; c" n- l" K
  9. * 返 回 值  : ( w5 d# L3 w$ B( `4 ]+ F2 y
  10. * 调用关系  : 5 |6 c" C1 u" V- i# \3 Y
  11. * 其    它  :   # h" f' F5 k% E  V
  12. *****************************************************************************/9 z8 C( ^+ s2 p! f: h
  13. void EnableUsart_IT(void)5 ^8 T; e' D0 }! L5 t
  14. {   
    % X# D0 V9 l, Y; H! ]! Q' H
  15.     __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
    ' t  h8 m, k5 W. G
  16.                 HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断1 y6 [# A2 ~9 B; Z7 H: B/ L
  17. }
    7 D9 v( X( X, W& _1 f2 \+ y' }8 o
  18. /*****************************************************************************& R- I5 G& B) I% E. C: [! L$ |. z5 S
  19. * 函 数 名  : Usart1SendData_DMA
    5 a$ N0 z. W2 }# Z/ L
  20. * 负 责 人  : by- ]; k' `* N9 C0 ?1 r8 V
  21. * 创建日期  : 2020年8月26日
    9 s( }6 I8 a4 K4 z
  22. * 函数功能  : 串口2DMA发送函数
    ( w4 @* E# k' T- f5 y: a7 `  K' m( E
  23. * 输入参数  : 无
    % `  T% Q! R* Z# y" ?# t+ t
  24. * 输出参数  : 无( _/ A6 Y, `" K* ?/ M
  25. * 返 回 值  :
    . a0 |) P3 y5 y4 f- B" P
  26. * 调用关系  : 5 y/ l+ G& @7 c( Z% m" F
  27. * 其    它  :   
    3 o/ w0 A- k6 b9 M2 t
  28. *****************************************************************************/
    $ X6 H: e; v' }7 j" [
  29. void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  0 x* W, c6 C; v# y: S9 n* N9 z

  30.   s+ u& b4 W) }0 b" Q$ v3 x% k
  31. {  3 B. @: D2 j& A4 H
  32.         //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  % r) B8 L# M+ x
  33.         Usart1type.dmaSend_flag = USART_DMA_SENDING;  8 q* _, Z: e" i5 ?0 a. U, r. a
  34.         HAL_UART_Transmit_DMA(&huart2, pdata, Length);    i! i5 i2 n) F
  35. }  
    1 Y& f, i- [* n$ Z
  36. /*****************************************************************************4 K: G: d% u" `: q7 C  [
  37. * 函 数 名  : HAL_UART_TxCpltCallback
    6 E. F2 c1 C: l  ~- m
  38. * 负 责 人  : by
    , m- l  E/ y7 Z$ u
  39. * 创建日期  : 2020年8月26日
    % ~2 n% u1 p& P9 q- t
  40. * 函数功能  : 串口2DMA发送回调函数
    - J  V' d/ i1 @
  41. * 输入参数  : 无! X0 S/ E/ C: O  `
  42. * 输出参数  : 无
    ( D) G/ F9 R! N2 m! B
  43. * 返 回 值  : 6 y" }1 A/ F0 }4 j) t
  44. * 调用关系  : 7 h2 S+ `& Q$ C, d6 C# }5 e
  45. * 其    它  :   - W' Z% c+ L2 v$ P1 N6 `" N- T
  46. *****************************************************************************/2 S% _" J7 c1 O3 K
  47. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  
    : p+ @0 e6 L5 |6 J: K
  48. {  
    & y& @4 H; c# f- ~/ l
  49.     __HAL_DMA_DISABLE(huart->hdmatx);
    0 F! T, ]2 e9 b5 i3 k. {
  50.     if(huart->Instance == huart2.Instance)        ! W0 T) @% T2 N8 E  H0 J4 X
  51.     Usart1type.dmaSend_flag = USART_DMA_SENDOVER;  : J# [: N/ I& H+ O. b- E0 Y
  52. }  
    0 k' j" h2 L. k! T' ~& s8 I1 z
  53. /*****************************************************************************/ p$ T' ]( G7 w" A# T" L
  54. * 函 数 名  : UsartReceive_IDLE4 J9 w4 s! j: B: h0 q; o
  55. * 负 责 人  : by$ i. \6 x- x5 \) P0 Q
  56. * 创建日期  : 2020年8月27日
    ' u8 u; A: G9 |/ i2 K" W
  57. * 函数功能  : 串口接受空闲中断处理函数8 ?" {+ t2 m' w' ?) ?1 d
  58. * 输入参数  : UART_HandleTypeDef *huart  串口句柄0 `4 H! a6 k7 E! f
  59. * 输出参数  : 无- N- h8 K% H# ~1 X) E6 ]
  60. * 返 回 值  :
    * I3 @7 O5 j8 K* T- L3 J7 L$ _
  61. * 调用关系  :DMA接收的数据缓存在USART接收中,释放DMA继续接收
    7 T6 @' i& g* d& |. G" U: [
  62. * 其    它  : 0 ^( M  d; T% w; D/ _: W) Z/ s
  63. *****************************************************************************/
    : G" r  [1 k5 J/ C& r7 ?8 f  A
  64. void UsartReceive_IDLE(UART_HandleTypeDef *huart)
    3 C6 w3 o6 H- L: {
  65. {
    " i  Z+ d3 S5 S) G
  66.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
    / R2 \0 T' l' r9 Q1 }& x) h7 @0 ^
  67.         {   H9 K( r$ O3 _  e$ u$ p" x
  68.               if(huart->Instance == huart2.Instance)//判断是否为串口2
    . [: H1 p. X; I" l
  69.                 {3 U3 ~3 F% a7 W- u7 |* ~) J5 u3 e) f
  70.                  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //是否为空闲中断' X6 q1 V" A1 Q/ ~+ `# F+ l
  71.                    {
    4 i4 G5 P  F! |' `( H" u
  72.                    __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //清除空闲中断
    + ?) r! |. b6 h8 f: K. s
  73.                    HAL_UART_DMAStop(&huart2);                                                     //停止本次DMA传输7 k# F* t3 i% q' d
  74.             Usart1type.UsartDMAReclen  = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR;   //计算本次传输数据长度2 m5 H! L- a+ ?1 }
  75.                                                 if(Usart1type.UsartReclen>0)5 o, J6 }, {& x
  76.                                                  {" f; l; m" k6 ?! i
  77.                                                         memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);  b) f3 k' p3 a0 k( N6 P
  78.                                                         Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
    # N& d# M. I$ V
  79.                                                  } : o) f, }/ f5 b9 J6 R
  80.                                                 else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录" ~0 G- Y% j3 m& l; s0 l3 Z
  81.                                                  {
    * n! v% H) K( b' j  }9 v! r
  82.                                                          Usart1type.UsartReclen=0;, P3 |- g* A$ D9 A9 b# w- N
  83.                                                  }
    & h" L2 c: S. x* L3 b! P6 F2 j
  84.                                                 else
    4 Z+ R, i* S! G. V, d
  85.                                                  {
    / z3 E7 y+ _/ s+ @' u& V
  86.                                                         memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
    8 i& [8 F2 J% H1 I, v
  87.                                                         Usart1type.UsartReclen=Usart1type.UsartDMAReclen;& ?! Y6 I. X) a. e$ O
  88.                                                  }                                        6 f& q$ N9 [: h/ P% J
  89.                                                 memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零                                                                                5 w6 i( ]$ i1 Q/ z) ]- R! s
  90.                                                 Usart1type.UsartRecFlag=1;//空闲标志位置1
    1 `0 `- X0 y+ W! r* l5 @. |* d
  91.                         HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA$ C- X3 w- K8 o7 N- @( E9 ]7 q& W
  92.                                         }                5 S5 Y2 C7 z3 X& O
  93.                   }
    ) j  v% n: x! u& p" Y5 h
  94.         }7 b$ M3 U; Z4 _* F$ ?/ F
  95. }
    3 @# b% z  {& F4 y/ b
  96. /*****************************************************************************
    ; x  A: ^! S/ r1 R" A4 G! a
  97. * 函 数 名  : Analysis_Serial_Data
    , ~  D) n! k1 x& |5 {+ u+ o
  98. * 负 责 人  : by# ^  K# Q5 ]. u+ L
  99. * 创建日期  : 2020年8月26日( q4 b; \1 b' h) c
  100. * 函数功能  : 串口接收数据直接打印
    - i* s1 [, L, s
  101. * 输入参数  : void  无/ b/ ]! Q' a6 K6 r$ o) I" n1 z# T/ m0 X
  102. * 输出参数  : 无* Q2 ~7 [3 {  Z* J
  103. * 返 回 值  : void
    9 ~. N6 A3 a% X7 _, D3 w
  104. * 调用关系  : ) f, s! }2 K. Y1 m6 U& k, u
  105. * 其    它  : 4 d7 E4 r9 h# _$ d/ B
  106. *****************************************************************************/
    6 o3 k$ h0 I6 y  F% W
  107. void Analysis_Serial_Data(void)
    - E( r3 x/ Q7 j0 ^
  108. {" Y. `0 c" m7 I& u5 y' E
  109.                  if(Usart1type.UsartRecFlag)
      t( B2 @* C! U+ ]% }
  110.                  {                                 
    8 `- n$ J, f1 U" @
  111.                          Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);        , z' K7 U, W! V+ H# G
  112.                          Usart1type.UsartRecFlag=0;
    4 E8 Y& y) e- ^/ I6 t7 |% }$ @
  113.                          Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理         5 i$ T5 c/ u& ]
  114.                  }8 l; @" ?' C' E; M& v4 \
  115. }/ k( H& s6 A  {
  116. /*****************************************************************************6 m2 e( M& T" {% C3 m) t5 d
  117. * 函 数 名  : fputc/ I+ `2 I7 h1 N8 U$ U* `
  118. * 负 责 人  : by
    % M! ]4 T2 S0 u9 U  H" {" Y
  119. * 创建日期  : 2020年8月26日& R- u1 ^; g3 J$ v$ p8 K, H
  120. * 函数功能  : 串口2 printf重定义& H. D5 Y/ Q9 t# T, `2 H7 I, o
  121. * 输入参数  : printf(d%/s%/%c,a)) }# b) I9 n9 h1 D4 @0 a2 S
  122. * 输出参数  : 无- X* H/ ~$ m4 T  T( }
  123. * 返 回 值  : 2 u1 v: ^/ N3 z( Y: ^4 p
  124. * 调用关系  : 3 g) N. {) B. u
  125. * 其    它  :   9 W5 b' r: \2 ]
  126. *****************************************************************************/
    2 c0 Q- J  J1 G% c7 y% x! Z$ X) Q
  127. #ifdef __GNUC__# _% D. A$ I8 `) V7 A  X

  128. / J" ?2 H" G! |  Z3 x8 M4 A
  129.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    / t& x" ]+ l  E. s( i
  130. set to 'Yes') calls __io_putchar() */4 M9 o  Z) a' a2 b
  131. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    , E3 y1 n; Q+ R& B2 Y: |# }
  132. #else  ^* M5 b* {- N( i9 d! f
  133. # @) k' d' B& _, h5 z( ^, v
  134.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    " l7 z1 p4 @* F  A) W
  135. #endif /* __GNUC__ */
    ; @1 f- x  I# ^4 e
  136.         3 {8 {, X+ L' D* c
  137. PUTCHAR_PROTOTYPE
    5 h& n% X) z6 o- F* b; ?  b4 K7 N  Y
  138. {0 I, s* U/ K( T5 _; J7 F
  139.         HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
    ; s2 E7 H# x- I1 F; W0 T& Y  D' l
  140.         return ch;
    + Y9 Z8 w+ a+ ]; A- }; R2 o$ _/ }
  141. }
    , W! }9 ^8 d5 A# ^( q0 A4 Z, ~
  142. 8 s. e/ n) a; c5 P( T  p6 n! c
  143. . D7 E4 h# }! _0 P) }7 D$ m
  144. /* USER CODE END 1 */3 B6 y. O8 R( g% n5 d! W8 x, D
  145. DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。  X9 j4 ?. e; K4 _. z  {
  146. / i7 ]" e$ c* X$ {5 l, j
  147. //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
    3 T4 E% ^$ Y& L
  148.     Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码

$ x4 [. W# T3 y3 r6 F" o/ @  g/ ?6 Z1 v! N0 ~9 d
6.3  主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数
  1.   /* USER CODE BEGIN 2 */
    / g. S: A& [6 }! |; e  ^8 P  }8 E
  2.   HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
    2 r4 J0 j9 a( u
  3.   HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/1 j; k9 j2 V0 `  v
  4.   HAL_CAN_Start(&hcan1);/*can初始化*/9 u: U1 S: p$ L1 l; o$ h7 `
  5.   HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);                        2 j0 }+ B, e+ e1 p/ X4 I
  6.   EnableUsart_IT();/*串口初始化*/6 e( u. L: }3 ]0 }$ f6 c/ b
  7.   CAN_User_Init(&hcan1);        8 }" X7 E7 n; W. v
  8.   /* USER CODE END 2 */
复制代码
. A  P2 P% N6 x2 a1 r$ ~  s/ T" g
循环,对应数据输出6 ?; l* ?" {& I6 Z" ^* Z
6 W( d, h. f$ X7 I$ |- @
  1. /* USER CODE BEGIN WHILE */
    5 s! z- u/ m" N
  2.   while (1)) E6 f$ H$ P% i, }- g" b
  3.   {               
    & y% V- u. W. g# x
  4.      Analysis_Serial_Data();
    8 F" u" P4 p$ K" H" w3 z
  5.     /* USER CODE END WHILE */9 P* L& ]+ P8 k$ K6 @

  6. + c, T" {: F! K6 C3 s4 t% O
  7.     /* USER CODE BEGIN 3 */
    : |* A% ~: }& L
  8.   }
    : c; s1 C. g: Z. b
  9.   /* USER CODE END 3 */2 c! H" l' x, D, w; V: d( |
  10. }/ l8 S' X0 Q0 S% w9 ~5 K# G
  11. 7
复制代码

7 b0 }; t+ a! }) S$ j  T" z、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误) I# V, O# x. |; e6 y* i% {; R

2 Y% ]$ s% \# a
2020090115084313.png
# p. |3 m4 U) S  }

* x. b: O/ g. j: `1 s: h% p% w- D, ~0 v9 o
收藏 评论0 发布时间:2021-12-14 10:07

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版