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

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

[复制链接]
STMCU-管管 发布时间:2020-10-20 15:21
STM32串口中断接收不定长报文并解析
( s8 r) z" \  W: N
2 C# z- d" |0 t* e& f
功能实现背景介绍6 R+ p' ]. T' V: q( ?/ I
本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。

" _) P, @) I2 \; b5 ]使用的报文规则如表格所示; E7 f) |7 C( O
11.png 1 s' w8 y% ~) w0 r; C' s
板间报文的通信协议,校验使用的是和校验
- G: o0 O, T3 c& ]  j3 y- G
  1. <font size="3">U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    ' R: {( U- D/ [- _
  2. { 6 x* B9 p4 n! s- Q; L# ~
  3.     U8 i, ret = 0;
    - J) ~7 ], e- {( Q
  4.     for(i=0; i<len; i++)% z0 w# {) |& m4 m# s5 M7 j
  5.     {
    5 a$ }  [% {0 d! T4 A6 `
  6.         ret += *(buf++);
    : U5 F4 w5 V$ ^7 S
  7.     }
    0 i( w% M% ^7 U5 b, v' ~9 u  P, b
  8.      ret = ~ret;
    - {6 ]: }9 v% Z' B1 a" v" W5 {
  9.     return ret;, n+ e+ N+ @  N; H
  10. }7 L8 ~/ i- w) Z5 M! C* b
  11. U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    9 d. v, U9 R9 q+ O: ]5 |& I; c
  12. {
    & R1 d8 a" [2 f6 Y2 E
  13.     U8 i, ret = 0;: Q. Q! D: D+ o" x
  14.      for(i=0; i<len; i++)
      N/ b  h1 F& L7 K) O
  15.     {) P- M) S: ^% [2 B& f& }
  16.         ret += *(buf++);  Y! C, R; B+ `% I
  17.     }; e; B7 M+ a! y2 A% |" J
  18.     ret = ret;
    8 l6 K0 G4 g! p. [5 j$ J1 g* C
  19.     return ret+1;
    . L+ u5 q% ^1 r9 e: A7 s
  20. }</font>
复制代码

& ~1 F- M9 b' U' O% {
. y5 o: R3 {7 z9 }发送和接收的报文要满足不定长
  ~; H4 r( b* c, _- ^6 hHAL库的中断接收函数& O; d. U9 N! F( Y/ @7 k
如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数

! z1 g" ]! h' g  U9 ~
  1. HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA
复制代码

- o& Q; a8 U# c. Z4 {
4 g. ~2 u! Y3 G7 \: K" t9 @在使用时,选择串口,选择接收的缓冲区,选择接收长度。( z) s; y8 l% s$ M# Z) h
- t" Y! ~! O* S* m

3 I% |- i" D+ ~4 R
  1. /**
    ! _9 v# g9 b( W7 l2 _
  2.   * @brief  Receives an amount of data in non blocking mode.# h4 V" C- X. g  W" [
  3.   * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),* {7 d/ o0 x8 X  O( H+ `- l
  4.   *         the received data is handled as a set of u16. In this case, Size must indicate the number
    + J+ a: d; p, C6 z
  5.   *         of u16 available through pData.
    ! J' M: {& ^8 V; A0 {: i! |- t
  6.   * @param  huart Pointer to a UART_HandleTypeDef structure that contains
    $ S( \5 l  C& G* u- d- m1 r) _2 D
  7.   *               the configuration information for the specified UART module.: u" {2 m5 e% @
  8.   * @param  pData Pointer to data buffer (u8 or u16 data elements).' i* `# B3 G4 L! Z" |% a
  9.   * @param  Size  Amount of data elements (u8 or u16) to be received.
    ; d/ ~. z' [$ V& |; h1 }2 s: _' X
  10.   * @retval HAL status+ `% }9 L7 _( v# C
  11.   */
    5 }4 U' H5 t# f! R! Q  {# F; J
  12. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)% a- [5 H4 Q2 Z3 D* Z  D
  13. {8 o, Z- }& F9 f  W
  14.   /* Check that a Rx process is not already ongoing */( o7 z  P. T' K9 ~1 {3 M* K/ y
  15.   if (huart->RxState == HAL_UART_STATE_READY): [. X  c; G: J: _2 F
  16.   {4 ?1 U% k" j' o
  17.     if ((pData == NULL) || (Size == 0U))2 ?5 j! E+ Z  E- Y8 ~
  18.     {. K# w6 N7 V* h: r& E6 B5 i
  19.       return HAL_ERROR;6 ?9 D" S: L! C. Z& ~
  20.     }7 y! \& P; \" n6 d6 }
  21. 8 W' R1 v5 D* y3 q3 j+ _  ?
  22.     /* Process Locked */( p  {- N6 t' t3 M8 n# {
  23.     __HAL_LOCK(huart);
    , l! F: l* W4 w) H+ n

  24. " c/ h# q! G7 r- A$ E% f/ s( N
  25.     huart->pRxBuffPtr = pData;
      A& P3 V3 a* A  K! ~/ }  s
  26.     huart->RxXferSize = Size;
    4 Y) h- \5 B! s( ^- i: x1 [& Q
  27.     huart->RxXferCount = Size;
      V2 I" L+ i% f# `: A6 D

  28. + I2 W  f$ H; P: L, @( u
  29.     huart->ErrorCode = HAL_UART_ERROR_NONE;
    2 W$ ?; P& N; g* L
  30.     huart->RxState = HAL_UART_STATE_BUSY_RX;
    ' r2 B& h# k# t3 B& d
  31. # d! s( h, f6 |
  32.     /* Process Unlocked */
    & Z3 Q' c5 f, ~& i
  33.     __HAL_UNLOCK(huart);6 G; }9 B( [/ P0 x- _& d
  34. 9 g# c0 o/ |! Z7 ~4 u) o) x; j
  35.     /* Enable the UART Parity Error Interrupt */
    ) B5 l3 b  M& @& V& F% Z
  36.     __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
    1 p* V' S6 u% W; ?; O
  37. ! U6 ^, B5 w. F2 f% P
  38.     /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */2 _- {' t# N3 V2 r- `; \  J
  39.     __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);( p$ F, }) n& b9 @5 H/ t

  40. 5 ~# I4 Y4 q0 _  A1 ~7 {
  41.     /* Enable the UART Data Register not empty Interrupt */0 V9 U2 \' w/ V& p
  42.     __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);5 C) C/ U2 j9 l, t8 H, a) j

  43. ) k) s9 S( |+ U" `9 }4 H" I5 q( V9 M2 k
  44.     return HAL_OK;
    6 K1 e4 ^/ v; Z( H& n
  45.   }' x! D. j+ i  j- l
  46.   else
    ) f3 v$ ]- b+ C4 }+ _3 S
  47.   {
    + w. {& o& i2 E! Y6 ?- L
  48.     return HAL_BUSY;) ]! V, G* x" i. k4 D- b; e
  49.   }' f! ^( Q6 @  S% @5 T# h: ^
  50. }
复制代码

$ a9 `/ d7 K% b5 m- Y: R9 I
2 i5 J* X  W5 U3 N- g/ b
这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。# K) ]( L, R  |) j, F( T( E# x
我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。
. f0 _. c9 M" |  @6 \$ f. k: \状态机的运用
3 \- \' y8 @) Y对于不定长数据的接收,使用了状态机,分两次中断来接收数据
% Z$ K! V8 e2 c1 [! w% n
12.png
- Z6 r0 ~0 F+ z6 Y" ~( a) E
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart), z3 U- g9 T% Q
  2. {
    / F% T1 J- p! c* N8 i$ O/ S
  3.         if(huart->Instance == USART6)                                         // 判断是由哪个串口触发的中断* w% x9 i- U( D# R* G5 s2 t7 D
  4.         {2 ~, Y% R8 |3 U9 [! H
  5.                 if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验
    " }8 i$ Y7 O/ C
  6.                 {        * ?' l- `8 f: z" l: a+ I
  7.       if(re_flag6 == 1)
    % H1 z5 u2 z! t; L' M; ?% Y/ y
  8.                         {
    : c; h7 n$ i! e" u. _. A
  9.                                 UART6_RxCounter = 6;+ `+ M- B5 F0 S- [; F
  10.                                 re_flag6 = 0;
    " C: `' V6 {# W. R7 \
  11.                         }       
    : J) J& P+ R  K
  12.       else$ D7 C% _, I1 p1 v7 J6 `
  13.                         {
      L  c: n) b: n" L
  14.                                 len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  
    # W, R! y% `- T& U% O4 {/ i
  15.                           if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)        . V* {* J+ Q& D0 u# r# |
  16.                           {) B6 r/ w* E* H  v5 t% [( q
  17.                                   UART6_RxCounter = len_counter6;
    : o% G* [; H" V1 c4 k, o: u
  18.                           }        ; G$ B. l+ Q3 w
  19.         else
    7 n9 [3 z+ ]) d! c* b! w- Z! p
  20.                           {: K5 U: J" r3 `
  21.                                   memset(UART6_RxBuffer,0,0x400);9 [" c. U3 `: Q; {
  22.                                         UART6_RxCounter = 0;
    6 j( x8 p& M7 p- k" S/ }+ @
  23.                           }                * }0 T- W4 j7 W+ o! k
  24.                         }                               
      D: n! H8 p# Z! P' q
  25.                      
    + o! ^2 i; e0 c8 P7 e# S7 d
  26.                         StateMachine_USART6 = 0;                                   //状态机为09 |+ a. J+ o) g  Q- w/ I
  27.       len_counter6 = 0;                       
    7 S. s. Q6 i! F2 Q" m
  28.                         HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);               
    : t: T  k4 s% ~
  29.                 }
    4 H' I" O' E+ f) S
  30.                 else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节; R* `, O4 M+ I4 c$ n, f4 j' ]
  31.                 {                                       
    & Y) ?! _- k9 K* E4 g6 h
  32.                         if(UART6_RxBuffer[0] == 0xAA)& I' ^3 x" M/ w* l  C4 ~; q- F
  33.                         {
    ) q# l3 X& s" h% Z7 ]5 {3 e) x& E/ F
  34.                                 StateMachine_USART6 = 1;$ i& C8 k6 ~$ H5 i
  35.                                 UART6_RxCounter = 5;( T' e6 I' p- V/ |& |3 N9 ?
  36.                                 if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
    . m0 `' x+ j7 o% Q* y
  37.                           {
    ' t  [, p( N2 L
  38.                                   HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);4 }5 E, P6 z  `+ q* S
  39.                                         re_flag6 = 1;
    . u0 k2 Q% B) w" t, i# e
  40.                           }1 {2 T2 P) l# ~2 L
  41.                           else4 t! _& D! b& z  r2 y# I6 s9 e
  42.                             HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));
    , X! u" K! W: }1 r9 ]- M
  43.                         }
    6 t4 W2 T6 I- [- g5 |. A$ V: n& p
  44.                         else& K! `4 I+ e' j5 ?9 f: y" V! G  t  o1 L
  45.                         {0 b6 F1 s; ^9 V! E
  46.                                 memset(UART6_RxBuffer,0,0x400);
    # c3 J9 w* p; N6 F
  47.                                 UART6_RxCounter = 0;
    4 l' ~$ J* m* M
  48.                                 HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
    3 a, a! z; S4 U& b
  49.                         }8 M+ a8 q9 v6 U/ M0 X& \. c9 |
  50.                        
    ' k& T6 V" N3 I6 ?7 l
  51.                 }
    % L2 Y7 ~5 {+ G1 ^6 Z) y) c
  52.         }
    0 U4 I- Y5 v: `/ L$ \
  53. }
复制代码
9 W* i6 w' _+ i0 e

& {/ v" n9 K- K: O# V+ N& n核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。
& L% k4 M2 S9 J. `/ p. l' X; Q$ o7 u) a4 w3 M$ f$ A

0 i  {) _; ^* Y- b/ o3 {# n) ?" ]3 ^3 N, H( H

% U: Q/ }, z4 Q6 J( j: P- ?文章出处:Outsider Hub* a( W/ g6 a* p8 X! T3 K
收藏 1 评论0 发布时间:2020-10-20 15:21

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版