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

STM32串口中断接收不定长报文并解析

[复制链接]
STMCU-管管 发布时间:2020-10-20 15:21
STM32串口中断接收不定长报文并解析

0 S# R* t0 V; e( e" t6 G4 R- E9 p) P# c4 z6 M3 g( W" M
功能实现背景介绍
8 }8 n6 n" y4 S# `; ]7 q7 Z( b! d( {本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。
7 f) N$ w, Q( T
使用的报文规则如表格所示0 a1 B  s% w; r! N7 o( i
11.png , `: h0 {) |2 j4 q9 L
板间报文的通信协议,校验使用的是和校验
9 N% D) h% h5 P: c% [+ G" c/ d7 z4 r
  1. <font size="3">U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    0 H1 h2 O: D- n8 s! ^& E7 L
  2. {
    9 Q/ |1 |! @: F
  3.     U8 i, ret = 0;
      [9 l6 c9 B; A
  4.     for(i=0; i<len; i++)
    & j$ V; x/ h  l5 e
  5.     {
      T! e0 j' ~5 A- {( y; a; U
  6.         ret += *(buf++);
    ' U; h' s* B3 V9 ~3 U$ V
  7.     }% [& V8 }* D- ~/ ~# c. L6 l
  8.      ret = ~ret;; P% R/ n6 S* g8 ^. M& @$ J
  9.     return ret;1 L, J# N* O' A( ~3 s7 i
  10. }: h: E* I/ e# a! N" y) h
  11. U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度0 K) e# C5 W2 i, v
  12. { ( ~+ u3 V/ A7 P0 o- X; Y2 I! h
  13.     U8 i, ret = 0;, g! S  v& ~6 u3 U
  14.      for(i=0; i<len; i++)# Y4 O. m& Q! @
  15.     {5 p! B1 v& U  h* }5 L% |4 A% i
  16.         ret += *(buf++);. K! `' [" p5 O
  17.     }
    ' V/ Z9 M1 u5 l
  18.     ret = ret;# A6 K! l. m8 ~9 k# o
  19.     return ret+1;
    . ]2 J2 w& ^4 X* u7 x$ r
  20. }</font>
复制代码

; g0 y8 S+ t' P0 W1 H" `+ N; x
9 ?- F/ H% v, n7 L4 `  `( h发送和接收的报文要满足不定长
. s; a4 t3 {  L: p' e) eHAL库的中断接收函数
. I3 u# ^7 Z: x# J6 @如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数
' R0 v0 G( |# _5 {* |3 J8 {" R
  1. HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA
复制代码
- _5 E1 c7 ]0 u( g

( ?4 _% F$ u: F0 S- I在使用时,选择串口,选择接收的缓冲区,选择接收长度。
2 N5 B- g3 W! \3 n. N( h& ~2 d( W2 M% o; r- y

: W- a- n) S' p6 z$ d
  1. /**
    5 K5 R' S2 y6 K
  2.   * @brief  Receives an amount of data in non blocking mode.
    ' Z% h" k' l9 E4 S, l* S
  3.   * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),7 ?; j% h5 Q) o- P0 i. }
  4.   *         the received data is handled as a set of u16. In this case, Size must indicate the number
    $ Q; A9 G8 d( f0 Q0 y
  5.   *         of u16 available through pData.
    % R- m2 I/ F2 ]7 a& D
  6.   * @param  huart Pointer to a UART_HandleTypeDef structure that contains1 L  f! A! K' P/ A' X" k
  7.   *               the configuration information for the specified UART module.
    * ?, D, \" h9 n1 D* n) A
  8.   * @param  pData Pointer to data buffer (u8 or u16 data elements).
    1 z$ i* n7 [4 @6 N5 F& i+ @# D4 ^
  9.   * @param  Size  Amount of data elements (u8 or u16) to be received.1 l/ I+ M0 s! H3 G; _
  10.   * @retval HAL status
    ) D7 V# p  |5 b; t) R- C
  11.   */1 F" a4 M& C9 v8 ?
  12. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)6 }" ^: o+ O3 W5 z$ v
  13. {* N# m6 L. C/ ~$ o' [2 e7 g
  14.   /* Check that a Rx process is not already ongoing */
    8 K) v) J; X; x3 D. a1 A
  15.   if (huart->RxState == HAL_UART_STATE_READY)
    4 V: g4 W* r9 A
  16.   {8 {3 A3 C% s$ z. I- C1 [
  17.     if ((pData == NULL) || (Size == 0U))
      b  I( j8 q6 M2 d0 s
  18.     {7 N/ ]$ n  ~3 P' q  f
  19.       return HAL_ERROR;  l% L' @& I* }: D* h
  20.     }
      l' G4 \9 p3 O' O6 ~5 f( W

  21. $ g3 f% j3 F' t& t; T
  22.     /* Process Locked */$ [: [  m0 F0 C) Q# S# Y
  23.     __HAL_LOCK(huart);
      ?6 T1 T4 N  M* k1 k' S9 Q
  24. # O4 \2 k5 n7 B( X$ s' |$ G7 v6 Y# z
  25.     huart->pRxBuffPtr = pData;% z  o! B9 w% q  w3 d
  26.     huart->RxXferSize = Size;  \7 _2 E3 }: I7 @
  27.     huart->RxXferCount = Size;
    ' w( r) i, ^9 w7 J3 t# P( Y4 S9 s

  28. . ]4 P& F- ~6 |5 r0 {5 `0 d
  29.     huart->ErrorCode = HAL_UART_ERROR_NONE;# g0 |: F% w% z# B# `" a# b
  30.     huart->RxState = HAL_UART_STATE_BUSY_RX;1 a* @" J- p* O+ i
  31. 4 H, W2 \! K7 Q9 ^
  32.     /* Process Unlocked */0 Z; ~: ?( e. x  D* v3 U' h( I6 w
  33.     __HAL_UNLOCK(huart);
    2 n  T% |& W; U5 c# V" T+ s& z
  34. ) G3 _; h" z, z' z6 \% i
  35.     /* Enable the UART Parity Error Interrupt */, @: b' ]' Q+ `7 ~$ [
  36.     __HAL_UART_ENABLE_IT(huart, UART_IT_PE);" O; U3 M5 I6 j+ }0 c, c

  37. 4 W; i9 Q1 D: B: \9 J8 u
  38.     /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */% S' Z& T& z( \) k
  39.     __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
    3 l( u8 f5 L* Y# U
  40. , P8 E9 `% w; ?5 M; d& P' l5 a9 K, B6 a
  41.     /* Enable the UART Data Register not empty Interrupt */
    + _/ ?9 U5 ^% \2 M
  42.     __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);% {$ \: k) Z) n2 x
  43. 1 n/ Z8 V/ D& |6 S
  44.     return HAL_OK;
    * L: G" [4 C+ B( b  K+ [+ z
  45.   }
    2 Z- ~; ?1 ?- }7 P
  46.   else
    5 X7 M( K3 m: I+ @8 E: {
  47.   {
    # y' E# D! i' N- M1 n
  48.     return HAL_BUSY;2 ~. ?+ D* s8 _% \0 r
  49.   }  Z# z. n. v4 R- o/ h
  50. }
复制代码

4 x1 d1 O4 }) F: M+ V# V$ J$ c" u" _
. p2 l* e* a0 Q# f! F' k
这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。* e$ ?% V! t. \
我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。
4 \9 M; @; \- k: k. Z% m- P' I状态机的运用* @' d& O, ^& F2 z' a
对于不定长数据的接收,使用了状态机,分两次中断来接收数据

) H9 I% _7 |: p
12.png
& T2 j" C7 }& G) A
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    , M' P& o' a2 ]! p) y: l
  2. {' o" o2 f" [4 w4 ?% ~4 n$ d' e6 n
  3.         if(huart->Instance == USART6)                                         // 判断是由哪个串口触发的中断( K! e# a  R9 g1 k' j
  4.         {) x' h) E6 `' ^2 \
  5.                 if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验
    ! a  O8 T- A  m5 p; r0 a) F) K% ~+ ~
  6.                 {        4 V6 J/ T8 ?" v* D! e
  7.       if(re_flag6 == 1)
    2 a7 D. c3 C/ P) c6 |
  8.                         {5 s/ X% s; ]9 ?1 z0 @$ G
  9.                                 UART6_RxCounter = 6;
    * P& m5 ~" ^6 x- y* j
  10.                                 re_flag6 = 0;
      v' W' e5 O9 B
  11.                         }       
    / \2 r5 O8 a5 Q( B4 L
  12.       else/ q" ?5 V1 ]+ w, o6 |# ?% `
  13.                         {' h: u& i- D- x( \, W7 }
  14.                                 len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  4 U' j5 O+ x3 t+ e! A' g
  15.                           if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)        9 K% f! y2 ~# U
  16.                           {
    , t4 [' o' f+ u0 o- [4 B" k1 o% m: m
  17.                                   UART6_RxCounter = len_counter6;. Y5 h' k% ?& f+ R3 E% h
  18.                           }        ( u+ n/ Y5 b; }' R& x- ?
  19.         else5 T) H. T+ r8 c: I5 j% J" B
  20.                           {7 P- E& ~7 j1 H/ z- Q
  21.                                   memset(UART6_RxBuffer,0,0x400);* k/ `3 w2 c6 K2 H9 v
  22.                                         UART6_RxCounter = 0;: M* i+ _# u  V) ~8 R5 I, Q
  23.                           }                + V( u7 b( F+ M8 }: s" s; g. K5 _
  24.                         }                               
    1 C! G/ P' n4 B. J, j
  25.                         ?+ M+ F. c- W7 A, g
  26.                         StateMachine_USART6 = 0;                                   //状态机为0
    , S0 u$ q5 G) I0 \
  27.       len_counter6 = 0;                        : C" w. L- s0 @- |
  28.                         HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);               
    3 y4 C/ K, O/ L8 U1 F% l5 d6 w
  29.                 }
    : }% X2 D, f  ^% h4 R3 H' d7 T8 h" [( K
  30.                 else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节+ U6 D/ \+ ~) j6 U( u* W
  31.                 {                                        2 q3 q. M# V8 ?( ]$ X* a9 V, ~: C
  32.                         if(UART6_RxBuffer[0] == 0xAA)" ?0 l: M+ C' p+ ?
  33.                         {- r4 U$ t/ c! M- D+ u, a
  34.                                 StateMachine_USART6 = 1;. R; x6 w" Q: H
  35.                                 UART6_RxCounter = 5;6 B1 v+ ^! G! C- }; B! V. C
  36.                                 if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
    0 ?- S( O. C3 v9 L
  37.                           {1 Z, y0 U. d2 \
  38.                                   HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);
    . R& L" Z, J% {
  39.                                         re_flag6 = 1;
    + [. V& w' v' I5 c4 E2 m# I
  40.                           }
    + w$ h& B8 A7 F3 `# A
  41.                           else
    1 o2 @5 h% L7 y: |9 \2 P- n
  42.                             HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));6 g) q3 R5 N3 P6 _- I: d0 C
  43.                         }
    , u+ I" N7 j3 f; k6 r; F2 ^8 v
  44.                         else# n/ ~# g% |0 @8 |7 f) {5 `9 ^
  45.                         {' a! Q& M# X+ m: ]  L. `
  46.                                 memset(UART6_RxBuffer,0,0x400);
    , Y* _/ c; k0 I8 J# D
  47.                                 UART6_RxCounter = 0;
    ; G( _# r, k7 r" |4 {
  48.                                 HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);% R+ F+ s; E1 s* y
  49.                         }
    2 _- T4 e3 g$ d  h2 t; ?
  50.                         ' [  K9 ^& Q/ i4 n6 \1 t$ S
  51.                 }# K: W: @. H$ r; Z; E0 R, C4 h
  52.         }
    & ]7 A5 m1 \- z
  53. }
复制代码
4 z' Q5 k! [2 y
" _+ V3 r: A% F# t) t- ]
核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。8 i3 u: y0 s5 N) F- g

) N) v' g6 U- S6 G, D. V

' a6 K+ y2 Z! w+ e/ }: f) w4 r0 J
- T+ P0 \7 O! `8 Z5 E  z
5 s* Q' R, C* G" |+ h2 d( ]; Z, K
文章出处:Outsider Hub( I& f& z2 C% K. J( y! K6 T
赞 收藏 1 评论0 发布时间:2020-10-20 15:21

举报

0个回答

所属标签

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