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

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

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:07
1.配置系统下载程序方式9 ~2 T9 v, M1 W+ S& x" g
8 [' @# V7 k2 S- [+ J1 ~
20200901143057124.png

0 T' c' Y6 f* [
, |$ m3 {& `% X  V8 d 2.RCC外部晶振
: I+ U; M, p9 r" y, _2 [; S% r! \
20200901143329762.png

! I/ ^( n" ~- O: A! ]4 B
  c, H- w% E$ S. O6 i" P6 p 3.串口声明
  C$ u0 Y  {2 U+ t& l
, f! s6 E3 j) y! b
2020090114343042.png

" m/ G5 W# I! W) Q( y- W
8 n/ c/ q/ `& N* ~
2020090114350548.png
& u3 {; C6 O4 O/ ^( d9 @! d4 X0 \

9 k& Q6 j7 X, D! \
20200901143544740.png

7 k9 x( V0 O! ~  G% M5 c) U$ g& _) C2 r! g$ k& M) g  ]
4.系统时钟) ]8 [! K! S  j
3 c1 x- e6 i  W. p9 ^% m; C( Y
20200901143654748.png
$ R( p7 K/ @: F0 l& Q& o" U
2 r8 {6 g8 p* R. b- e
5.生成文件根据自己需求配置
+ v7 B/ S1 ^$ c9 U  B7 ~; {1 W8 e1 n& _8 @# p& v
20200901143817649.png
0 l9 g" a6 C  B8 k5 x( l

: `2 J" F+ W% n: L! s% p0 q 我这设置了所有库,可以选第二个仅需求的' K1 Y+ c' W( X( w
8 q6 q% r1 X; |5 z' C; p
20200901143845598.png
3 n5 D2 B/ a, |) b

( }( d: `& W; ]9 D7 i) i 还加了其他功能,这里可不参考,DMA要放在串口前
  k" D# H4 R. R& ]' f7 a7 {8 N- \/ _! z) j5 u+ z
20200901144049245.png
$ j9 u6 {7 p0 s, i" f: |
  ~6 b) Z9 a5 H; I6 U7 g& H' [
6.生成后修改
6 h3 p5 @* S: H  V' G0 b( w
2 `6 v2 @0 \8 n, t$ b4 G& y6.1 usart.h" P. r2 Q8 C' Z, Q) W
; K% i: P7 m) H
  1. /* USER CODE BEGIN Includes */
    6 O$ U0 i# @* }! S: |
  2. #include "stdio.h") g# u1 O( w  W
  3. #include "string.h"/ D' {& @! ~. ?) `2 h: J) e
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN Private defines */0 R8 t2 g# p7 D; _/ e: V8 l
  2. 3 X- B# N: \9 ?$ J0 Q% \! B
  3. #define USART1_DMA_REC_SIE 256
    " K0 l+ |6 G% {
  4. #define USART1_REC_SIE 512) M, H& h) y; l1 q' C' v$ b
  5. #define USART_DMA_SENDING 1//DMA发送
    2 K( J# Y+ B' u/ q
  6. #define USART_DMA_SENDOVER 0//DMA发送结束/ |; c" f0 t- S$ T5 r* ?  |) l6 {
  7. typedef struct4 @; C" \! L7 J! X
  8. {- ^" r" ?* m' s! O/ K9 Q, d( u6 G
  9.         uint8_t UsartRecFlag:1;//接收标志
    ! N- q0 i. y" W7 {5 d2 {2 m& Y8 `
  10.         uint8_t dmaSend_flag;//发送标志
    4 d) ^% O9 z2 Z
  11.         uint16_t UsartDMAReclen;//DMA接收长度6 D; h- F- |! W, o$ @
  12.         uint16_t UsartReclen;//串口数据缓存长度2 N7 P% ?6 K$ `) k3 {6 t5 u
  13.         uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
    " `, w5 i) a" R2 {. ]+ R
  14.         uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
    . z& I, d0 d% B, x
  15. }teUsart1type;  W  p# @, z5 v: _0 S# n, E7 F
  16. % |5 Z6 k4 b% i9 J/ w' `$ d
  17. extern teUsart1type Usart1type;//定义数据
    - P/ _# |. H% w& h# R, ~% g; @! M

  18. & [2 e' D& ^6 E: s
  19. void UsartReceive_IDLE(UART_HandleTypeDef *huart);, [* S+ J3 S* @" C# n( }' v/ M+ V
  20. void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
    6 n( l9 p" M& Z; {3 T, q
  21. void Analysis_Serial_Data(void);8 t' @# \9 @" V9 r' K- c- X6 A
  22. void EnableUsart_IT(void);
    6 P) v  \) ?5 A8 c$ g2 `5 a
  23.   `3 F1 y9 z/ @& ~. q* P
  24. /* USER CODE END Private defines */
复制代码
" `0 Z$ w. `% w. z
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。3 L' R% v- N. ]2 _1 B
% ~0 _* _% Y* r( y: h9 Z- {
  1. teUsart1type Usart1type;
    : F6 P: s) Q7 u, S1 s5 \
  2. /*****************************************************************************
    % p0 T8 y8 |2 f, k  ?# |- e* l
  3. * 函 数 名  : EnableUsart_IT
    - @$ Z: p$ C( \1 c# x, V- q
  4. * 负 责 人  : by6 ^% i: H9 P9 s7 q
  5. * 创建日期  : 2020年8月26日! t1 w9 Y9 V9 o; @/ ^8 Z5 n
  6. * 函数功能  : 串口2初始化函数,空闲与DMA中断+ r$ m  p- I8 i8 J+ p+ y9 t- s
  7. * 输入参数  : 无
    0 Y  j. H& ]. ?
  8. * 输出参数  : 无4 }% @1 A0 M/ X, r% s" ]3 {
  9. * 返 回 值  : 6 d" H' a6 Y# M7 u& B' D
  10. * 调用关系  : ( e+ ]3 _) D2 ?8 F
  11. * 其    它  :   
    . K% r2 p, r3 |1 U+ I
  12. *****************************************************************************/
    7 _4 ]7 q' g1 V* L! D5 M7 m
  13. void EnableUsart_IT(void)
      @* u4 C8 o; O9 p* Y" E8 b+ f
  14. {   0 k3 @, x$ H+ S6 L6 B
  15.     __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
    7 o# V: N3 a( B4 g5 s
  16.                 HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断( V5 u9 A0 Q& @; h$ k
  17. }
    & O# C, ], c0 ]2 H) O- ^
  18. /*****************************************************************************
    3 y7 y2 s# Q3 _6 h. [
  19. * 函 数 名  : Usart1SendData_DMA
    , O) q. E3 e  O3 X$ M
  20. * 负 责 人  : by
    0 s( A' U6 a& {. Y0 }" M; D
  21. * 创建日期  : 2020年8月26日, M& S; z) a, ]2 x) F9 E# H
  22. * 函数功能  : 串口2DMA发送函数
    8 }! H& L" c" t$ u
  23. * 输入参数  : 无
    7 M1 F2 L2 T* s9 F
  24. * 输出参数  : 无. v6 V) O8 `0 }' Z5 g( h
  25. * 返 回 值  : , x6 |7 P3 d+ @+ V5 ^6 z
  26. * 调用关系  :
    " v6 A1 \- D" A6 e3 \
  27. * 其    它  :   4 F5 _4 @. R* s
  28. *****************************************************************************/  W3 c6 x, W6 D" Q
  29. void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  
    ) l& h) S( c2 h2 q$ `
  30. 8 O: G0 a% Q8 Z  a/ p
  31. {  
    , m- @9 l8 o* G/ E. ]7 h. Y* T3 x
  32.         //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
    ) F; x5 T( |4 I- U
  33.         Usart1type.dmaSend_flag = USART_DMA_SENDING;  
    - }' b% h0 m: L3 F' \
  34.         HAL_UART_Transmit_DMA(&huart2, pdata, Length);  : s' T7 G6 ]. e. ^( c
  35. }  
      k+ ^0 {/ U8 X. X
  36. /*****************************************************************************
    + \7 X; C' a4 w
  37. * 函 数 名  : HAL_UART_TxCpltCallback
    8 [0 y/ y' i' X/ ~& ^
  38. * 负 责 人  : by
    . Z- p+ m3 c1 b2 e$ Y1 z9 G2 I9 E
  39. * 创建日期  : 2020年8月26日! b# x  A/ x% V' D' k: C
  40. * 函数功能  : 串口2DMA发送回调函数
    ) s4 e+ b% y- N9 F/ ~) x% T* {+ k
  41. * 输入参数  : 无
    * ?7 X3 B/ x2 k; f  a1 C! C
  42. * 输出参数  : 无
    9 s/ c1 ^; A; {* J
  43. * 返 回 值  :
    9 x& X3 K! T  B5 m7 L& P% d6 v
  44. * 调用关系  :
    # f& P8 [9 x9 a/ |& c
  45. * 其    它  :   
    . v6 Q6 Y5 n* N- n' C+ ^
  46. *****************************************************************************/) p) d4 Z$ p6 `
  47. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)    ?8 c: g) L4 u) O& K( A1 ?
  48. {  , C7 O+ B0 ^; b" i# D0 h/ W$ J! [
  49.     __HAL_DMA_DISABLE(huart->hdmatx); / i, n5 K! z$ b3 c9 [, x, ]
  50.     if(huart->Instance == huart2.Instance)        
    % d4 Y0 x' ~) s- z0 V
  51.     Usart1type.dmaSend_flag = USART_DMA_SENDOVER;  
    ; B4 ?' F! O, A& U$ ~$ h2 H5 N
  52. }  # C3 r# {( {+ x  _2 j, b
  53. /*****************************************************************************) j. a2 Z' _2 Y
  54. * 函 数 名  : UsartReceive_IDLE
    , m3 r- }( Z! l9 @! n
  55. * 负 责 人  : by
    + s: H3 W( K: W8 F8 `
  56. * 创建日期  : 2020年8月27日
    ) c' N5 M6 G' i; [
  57. * 函数功能  : 串口接受空闲中断处理函数
    4 K8 s8 y+ X" F3 A" |
  58. * 输入参数  : UART_HandleTypeDef *huart  串口句柄  ?, C. i$ ^7 v
  59. * 输出参数  : 无
    " C' s" l  N) h+ o1 [8 o( h/ J
  60. * 返 回 值  :
    , _6 w8 `3 M* d  U. e
  61. * 调用关系  :DMA接收的数据缓存在USART接收中,释放DMA继续接收
    ! Z# f: L# b1 b+ h8 p3 ^0 \5 U
  62. * 其    它  :
    ! J8 G6 a& D& q
  63. *****************************************************************************/- @9 x$ R  P2 g+ f0 M, t; N7 H- i
  64. void UsartReceive_IDLE(UART_HandleTypeDef *huart)  \, z* s) X+ a' }9 I
  65. {+ b$ }8 K, t. n! B
  66.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))1 L3 v" M" z  C+ S5 P7 P" r' b% r
  67.         { 4 X' C' [; O4 v% h
  68.               if(huart->Instance == huart2.Instance)//判断是否为串口2
    . f- U% A$ U. h, B
  69.                 {+ I: {1 Z6 m* |. {
  70.                  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //是否为空闲中断- m8 H( c9 k, D2 B% N
  71.                    {" V3 w' O: ?: @( N, z
  72.                    __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //清除空闲中断
    7 `; b* O2 v( O, Q) ?  ^
  73.                    HAL_UART_DMAStop(&huart2);                                                     //停止本次DMA传输
    . z/ T  F  c( O# `$ u
  74.             Usart1type.UsartDMAReclen  = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR;   //计算本次传输数据长度& @2 z  ]' O. W  Z2 g+ d; N
  75.                                                 if(Usart1type.UsartReclen>0)
    1 S$ e7 A5 }6 e/ D# U0 m2 D
  76.                                                  {; h3 G3 M, y: G) o
  77.                                                         memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);/ P4 g* ?9 ?& C7 \/ [' x+ t
  78.                                                         Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;* h4 d9 i+ O& H  W  R4 z- R. X
  79.                                                  }
    # m) ^! }8 k# k8 R
  80.                                                 else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录5 Z6 x" u& [0 o+ b2 h5 F
  81.                                                  {
    + H1 `- \: k& d# E
  82.                                                          Usart1type.UsartReclen=0;; i1 L6 p' g% g. W! t" Y
  83.                                                  }
    - z0 N- |3 ~2 X$ y% R8 w
  84.                                                 else
    7 l) x  o; k8 _0 e3 O$ H- n
  85.                                                  {
    2 c4 g0 @8 M) B, H+ R2 G
  86.                                                         memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);* F) x5 J- T- v
  87.                                                         Usart1type.UsartReclen=Usart1type.UsartDMAReclen;, O5 y/ ^- g, G/ x7 O+ ~
  88.                                                  }                                        - N) f2 A7 Y+ j3 D! J4 Y
  89.                                                 memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零                                                                                
    6 Q& z7 I( d7 Z7 N" b& ^
  90.                                                 Usart1type.UsartRecFlag=1;//空闲标志位置1
    $ L9 `, m* t3 p. o2 d& s2 g. D
  91.                         HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA  p0 b- J1 `3 b
  92.                                         }               
    / U* T( M  B6 X) R( A3 T
  93.                   }# U* L, e4 [+ u) n' E. I. h
  94.         }2 d/ h# i9 Y% N3 @+ x
  95. }8 S# s7 g9 u+ ?9 k+ [" g
  96. /*****************************************************************************
    ; W9 P9 D% o7 @: e
  97. * 函 数 名  : Analysis_Serial_Data! G. z! X+ L2 Y: |1 _4 m! V1 d
  98. * 负 责 人  : by
    ; {, i. f/ |+ I9 G- @/ r
  99. * 创建日期  : 2020年8月26日
    7 o; |3 S* Z) r, ~
  100. * 函数功能  : 串口接收数据直接打印
    4 d5 W& U' W2 X- r. h& G
  101. * 输入参数  : void  无
    2 }' P: L) `: M. ], M& R
  102. * 输出参数  : 无
    ( U( C1 A6 ?* a. F
  103. * 返 回 值  : void
    , X5 U# E. j2 e& C; N: D
  104. * 调用关系  :
    * u, S3 O  s) n) a3 s
  105. * 其    它  :
    ! M) a% q0 ?+ v/ w4 p
  106. *****************************************************************************/  b" x* C, \& f
  107. void Analysis_Serial_Data(void)
    ; ?# y7 p! o% Y  A: \. c2 O2 q
  108. {
    4 i7 E, D) t5 |/ l* u
  109.                  if(Usart1type.UsartRecFlag)2 ]: g) j  u7 Q. X
  110.                  {                                 7 i6 Y! P; Q, X' v) m/ E
  111.                          Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);        
    ; b5 N8 M6 }4 c: j! x" i
  112.                          Usart1type.UsartRecFlag=0;/ b, \- N1 D' o+ A# u: i
  113.                          Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理         ! T  H) b: }( O# G/ s8 s8 a
  114.                  }
    $ X9 Q: G% ~8 K0 e, e& K" }
  115. }
    ) g# F, U+ D/ N+ U
  116. /*****************************************************************************1 y8 @+ c3 T7 ~+ l) J
  117. * 函 数 名  : fputc4 Y& O  Z1 M; i. H
  118. * 负 责 人  : by
    + s3 I0 |3 a. J+ x4 K
  119. * 创建日期  : 2020年8月26日
    " }* q, {+ p8 q
  120. * 函数功能  : 串口2 printf重定义
    ' y% T# c4 c5 g, |% s
  121. * 输入参数  : printf(d%/s%/%c,a)
    4 b& i3 A1 j7 h1 P; u
  122. * 输出参数  : 无
    $ H! E! Q9 @' L) c/ e8 q# B3 P# h
  123. * 返 回 值  : - ]; O2 N* P2 O8 [( V2 c
  124. * 调用关系  : 1 G& |; T- n1 Y: E0 W
  125. * 其    它  :   2 T8 S& K; a8 e$ ^) Q6 Q
  126. *****************************************************************************/
    * O  |5 b0 P6 L1 E8 i
  127. #ifdef __GNUC__6 J: {- t9 ?" W# \) J) B

  128. : `1 @! f7 W0 P( ~# J
  129.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    3 g+ P& q1 a1 o; ^+ ]$ Z3 z
  130. set to 'Yes') calls __io_putchar() */
    ) n  o( r' P3 \6 L4 @, N4 M
  131. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    " X2 h: `% e/ l/ K
  132. #else
    % Z- b+ ?: A- Z" t

  133. ) e- w( O1 |% Q- u" N# ?( Q
  134.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f), w8 I1 ]* H; q
  135. #endif /* __GNUC__ */
    . j8 L  K% p4 D/ \4 c7 M
  136.         & f6 t! N  R& e
  137. PUTCHAR_PROTOTYPE
    5 l! R6 C0 O& v+ R, y2 `0 Z
  138. {- \: `; ^8 _( k! m+ a
  139.         HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);% `1 w* L: c4 r+ E& @9 n5 t
  140.         return ch;
    ' Y1 Y4 k: L6 y
  141. }
    9 e7 j9 D) B. x' y) x) T2 j

  142. 1 ~* W2 k$ G: q* @* `7 @
  143. , D: v$ }4 ?/ @
  144. /* USER CODE END 1 */
    ! E; K, l# Y/ J1 V* C+ Y7 o* `' p
  145. DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。$ K, y' v6 r$ A% ?$ a: A9 W+ `
  146. . B) n1 R; C5 Y8 L( g# v
  147. //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
    * i; i7 `& y; J
  148.     Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
- l( U& y8 ~# D6 L( Z+ L

0 \# E: c5 c5 b( k# {, ]* C+ e6.3  主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数
  1.   /* USER CODE BEGIN 2 */( |4 J0 S& U6 z& p& K1 ?
  2.   HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/. h, U+ a- k( a5 Q/ m% w
  3.   HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/8 s0 u: p3 p& X. V; q' U
  4.   HAL_CAN_Start(&hcan1);/*can初始化*/
    2 }3 ]: k) M  J; C- L3 n* s4 Q* u
  5.   HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);                        0 w* h5 U) P( z$ ^* q
  6.   EnableUsart_IT();/*串口初始化*/2 r+ S/ F4 o4 b0 I- w
  7.   CAN_User_Init(&hcan1);        % D/ m' u. ?/ K
  8.   /* USER CODE END 2 */
复制代码
4 B/ \8 S& |/ |; c( q- w) y5 ?2 M
循环,对应数据输出
  v9 r/ l. F( I6 ]# R, x" D! O% W
# D! h: I! w9 h& F" v
  1. /* USER CODE BEGIN WHILE */+ Q. N/ S' Q) j4 z) p3 k% ?5 R
  2.   while (1)
    4 p: o; H+ c8 A  M/ K# w0 ]
  3.   {                  ?2 k1 B1 s: I7 a0 y( L" j' N
  4.      Analysis_Serial_Data();
    # k0 [2 \% I5 f( y: v3 |
  5.     /* USER CODE END WHILE */
    9 M) v) Q. s( h5 @: Z5 i  M

  6. : H9 X8 a+ I3 V0 W" J& u
  7.     /* USER CODE BEGIN 3 */
    % ]& Q5 Y) V6 D
  8.   }
      f; c" n2 i" P7 o, D! H
  9.   /* USER CODE END 3 */0 ]: {+ V. J& Q4 U2 N
  10. }, T7 q8 ?! @7 w
  11. 7
复制代码

6 i( d/ L. e2 v7 i、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误3 }) p) ~4 L7 D% v9 N6 v
' T6 m. Q5 I1 f+ n
2020090115084313.png
, w+ C$ [- i6 W4 ~8 n: V  h
1 D& B- R. Z) W6 p% b9 p

: x* @5 v7 t$ l  e" U8 D4 J3 k0 s
收藏 评论0 发布时间:2021-12-14 10:07

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版