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

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

[复制链接]
STMCU-管管 发布时间:2020-10-20 15:21
STM32串口中断接收不定长报文并解析
  e# a+ y0 {5 F/ F+ `; ~8 ?* H
) `8 _# o9 x! A! t/ L& X9 V+ ~
功能实现背景介绍
8 H( ~5 k  f) X/ C3 `( \8 f5 y. O本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。
- _, I0 S# _9 d* Q% y' V
使用的报文规则如表格所示' N  y" A* c+ e  F4 x% f+ q9 v" n
11.png
3 k: F1 J( ]5 Z7 |, P7 v板间报文的通信协议,校验使用的是和校验
. c4 j: h% B& [  M& z$ c
  1. <font size="3">U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度. x; C& l+ m8 T7 Z' _
  2. {
      Q8 t9 [4 Z5 ^# V, L
  3.     U8 i, ret = 0;3 z0 a5 `7 z+ M- h6 J
  4.     for(i=0; i<len; i++): f) l/ Z8 C; n/ n
  5.     {
    : \% M* V1 J% a
  6.         ret += *(buf++);  h  `. t- q  }: Z  I5 l+ K- F& k9 g
  7.     }0 e  `+ V/ P* q
  8.      ret = ~ret;
    # \- w; F; o7 W6 ^- ?: `# @' r
  9.     return ret;
      c/ l1 @& D) R' `) O$ I
  10. }4 W$ A1 `6 h0 b. g
  11. U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    / s8 M8 h, {- z7 m8 S/ e2 u
  12. { # h0 @1 ?8 N$ @
  13.     U8 i, ret = 0;2 i; Q9 j. A( m: a( o
  14.      for(i=0; i<len; i++)7 w7 i9 k5 i+ L% }7 ~# \
  15.     {4 S1 s3 K$ @! ~
  16.         ret += *(buf++);: ~- w9 @" o" G* S+ `0 K) V2 E
  17.     }
    ; \. g  f& _% F; ]
  18.     ret = ret;3 W  N5 E- |# V0 B6 O& x1 I
  19.     return ret+1;
    " N6 ?5 I7 A" S9 o9 D7 v
  20. }</font>
复制代码
9 ]* Z3 Z) @+ L* ?# [; U; x% k0 N

1 K5 F6 ?* c( s! z1 S8 K发送和接收的报文要满足不定长
# f8 {# m* y$ V' q0 N3 lHAL库的中断接收函数5 o( o% e" Z! G7 a+ C- Q
如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数

7 O# ^/ M) Y& i/ {
  1. HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA
复制代码

2 g: U. ]9 P3 J! k+ T0 R8 ?# q0 y' x+ o0 F* x3 R2 v
在使用时,选择串口,选择接收的缓冲区,选择接收长度。
$ r: Y# g" A# h: R4 v: O5 E! o
3 M0 |( `: r' `1 R1 e

8 D0 E; {) x. _% D5 s" `- ]! Q9 `
  1. /**
    " Z9 a% \5 d9 M1 R9 k' Y
  2.   * @brief  Receives an amount of data in non blocking mode.
    7 j; Z5 K; w7 x$ Y7 E
  3.   * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),. ^1 M& [9 _: H* u8 {' W- f+ I/ A9 q
  4.   *         the received data is handled as a set of u16. In this case, Size must indicate the number) u3 ^) l& C. T
  5.   *         of u16 available through pData.8 E6 z0 J2 Y& Z" H2 v9 p- T1 n* u$ W
  6.   * @param  huart Pointer to a UART_HandleTypeDef structure that contains
    - N1 U5 p/ V3 v9 |. v
  7.   *               the configuration information for the specified UART module.
    " c! H6 b8 E4 X. i1 }; S
  8.   * @param  pData Pointer to data buffer (u8 or u16 data elements).3 g. J4 s4 j/ f$ l: H/ k
  9.   * @param  Size  Amount of data elements (u8 or u16) to be received.
    " C  `4 p6 K# f: N
  10.   * @retval HAL status1 b8 |6 ]5 n% {2 f
  11.   */
    5 ]) N1 I( M* S
  12. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
    7 Z( q1 M5 ]. J' y# B
  13. {1 d0 K( j1 w* w: U
  14.   /* Check that a Rx process is not already ongoing */
    1 ?; b- @  Z, c/ D, W
  15.   if (huart->RxState == HAL_UART_STATE_READY)  d8 S% G- H0 D, S9 I' B! J
  16.   {  c  U& r" u, d9 Q( J6 k7 ^% T
  17.     if ((pData == NULL) || (Size == 0U))& \) A& b# z9 Y+ P
  18.     {' v7 _' g2 S0 W4 d) Q/ b
  19.       return HAL_ERROR;- ^. @$ _" c; H
  20.     }
    ) L9 Z# B* P8 g1 L' x  ?: M% X' ?

  21. $ ?0 _( g+ I0 w/ x8 ~
  22.     /* Process Locked */6 \& G7 f" b+ R- Z3 A2 [; [) O
  23.     __HAL_LOCK(huart);+ C. Z3 f6 O3 F$ v5 @6 g/ B; e1 M
  24. " Z3 Z8 `  g9 k4 ~% e  }# R
  25.     huart->pRxBuffPtr = pData;
    8 E! ^2 u4 n  w0 |1 a
  26.     huart->RxXferSize = Size;
    4 r4 U- P( o! [8 S* s& B3 p
  27.     huart->RxXferCount = Size;
    ) L# s% b+ ]; o
  28. 2 a1 R- c5 t( \1 w" Q1 @9 l
  29.     huart->ErrorCode = HAL_UART_ERROR_NONE;
    , n. X3 R9 v* u$ g1 k- `
  30.     huart->RxState = HAL_UART_STATE_BUSY_RX;
    6 u9 N& I& |% d% K0 N
  31. # w6 w) h) i8 s0 X8 G) h
  32.     /* Process Unlocked */
    9 e) I* U0 c( t9 a- A2 L" J
  33.     __HAL_UNLOCK(huart);6 K$ a* U! G/ s" J2 D* M; @: ]

  34. - m2 j; s: U# y1 \* f0 W1 o4 l
  35.     /* Enable the UART Parity Error Interrupt */
    . G4 n. K: c8 f7 p4 S8 Y
  36.     __HAL_UART_ENABLE_IT(huart, UART_IT_PE);1 G: ^" ?) d3 `4 X. A& ~; `

  37. ; e. c* N- A" I" F
  38.     /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */! B+ @0 ~: s) ^0 P) \" O  v- `! j8 E
  39.     __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
    ; l# p9 Q# @+ a% B( C

  40. ' _  F, z1 |" f' y1 {8 x
  41.     /* Enable the UART Data Register not empty Interrupt */: Z5 W: h& J8 U( ~" L
  42.     __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);3 ?; F6 y7 L1 z; [: Q/ P. ]: a/ Q, z

  43. 9 w; k+ }- B* q9 s! F) ~2 J
  44.     return HAL_OK;
    0 l5 i: W6 D5 c
  45.   }8 I# i! J1 c% ]1 J- k( X
  46.   else
    ; I* K' }. U/ [# L
  47.   {/ }3 x' A% B" g. m
  48.     return HAL_BUSY;
    " l6 a7 y1 v& \& z! @) z& N
  49.   }
    6 ^9 e& K4 I. {. e
  50. }
复制代码

# e- T+ E1 T! N" ]
0 W- t7 M: G9 p
这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。# d4 ^6 s, W  X0 e5 r5 B& w7 d
我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。
" x, Z" k4 [% R; W& e2 K$ d状态机的运用
+ X$ T+ B/ w8 z对于不定长数据的接收,使用了状态机,分两次中断来接收数据
; z! `" F7 [2 v6 F& v
12.png - u& L2 @$ B( ^  p! s! d
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)' H  X/ X* V% \' \9 d
  2. {
    / e% G( H& q0 {& d1 H
  3.         if(huart->Instance == USART6)                                         // 判断是由哪个串口触发的中断
    % M: f; ~' p5 ~" D/ H
  4.         {
    ! S+ k" s. _5 r+ L1 i
  5.                 if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验
    5 a+ N7 Z5 b* H7 U, F0 _  o
  6.                 {       
    ( e' ]9 h/ z! G% v
  7.       if(re_flag6 == 1)' W( ~9 K5 A" r/ A. x& R
  8.                         {
    8 p$ p8 c4 {+ B* E
  9.                                 UART6_RxCounter = 6;
      s- A. ?' A$ h: t2 e5 x6 d
  10.                                 re_flag6 = 0;
    4 P6 H0 {! s$ n5 Y4 n
  11.                         }        : W5 w/ n" @1 G5 J$ q- F1 G" I
  12.       else
    5 W' o. Z- Y' b: a
  13.                         {, D* |" n/ Z3 L5 u. G( f$ V
  14.                                 len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  # x, K- A4 @8 E4 b5 D  q: k! q9 M/ \
  15.                           if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)        1 Z- B- h5 A# R9 s% X# d$ I+ S% B
  16.                           {* m* D, \! i. j- f0 [
  17.                                   UART6_RxCounter = len_counter6;! O; n  K2 x8 H4 c8 b! p$ e
  18.                           }        & V4 s3 M9 V4 ~' @
  19.         else% s/ d& A' x% i- j% f: f
  20.                           {  q* m) A! W& Q: o' v
  21.                                   memset(UART6_RxBuffer,0,0x400);
    . q+ k3 L. _0 P' p9 C. j2 a
  22.                                         UART6_RxCounter = 0;8 H9 [" F0 |; R
  23.                           }                4 i8 P9 [- T, Z% M; j9 N
  24.                         }                               
    ) X& h" G! f/ E  B, |" e) \8 G! i
  25.                      
    " s5 d' X7 P4 p% ], _- F/ w2 s% s& l
  26.                         StateMachine_USART6 = 0;                                   //状态机为0' g6 e0 T" q2 {
  27.       len_counter6 = 0;                        * D. A, G! {# l" t9 M" f
  28.                         HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);               
    ' {% E& a! e6 V7 ]8 s
  29.                 }
    3 s' B) I$ @3 }: U3 e$ Y3 R
  30.                 else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节
    1 I( E3 I9 C9 v+ }4 a$ [" J3 U2 `' \
  31.                 {                                       
    4 C  s  j. [* }
  32.                         if(UART6_RxBuffer[0] == 0xAA)! ~/ g. \0 P7 p2 c2 w
  33.                         {
    * F3 z3 f5 f; z1 B' @
  34.                                 StateMachine_USART6 = 1;
    : g0 e1 z1 V4 O$ H. k# h) e4 k
  35.                                 UART6_RxCounter = 5;, z6 _2 t& j9 g, b- w* K
  36.                                 if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
    " L4 Z+ _/ \8 K/ x- L3 g
  37.                           {4 a6 z7 @9 [2 \5 Y" f! ~9 R
  38.                                   HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);- O8 f; g9 r! d8 f/ u7 f
  39.                                         re_flag6 = 1;
    0 r: F' ?7 Z3 s8 n7 V$ U% l
  40.                           }# I  ^' p- U/ [" @8 Z% k6 b
  41.                           else
    . O8 r* L; Y/ M. c( a7 k
  42.                             HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));
    , }( W& X8 r4 |. b5 U) w$ E( _
  43.                         }) ^! J( ]/ t8 V! a
  44.                         else
    1 v8 T* W. H: m/ ~% [, l
  45.                         {! o5 f) ?# n, x" e( B5 G' C6 h; ]
  46.                                 memset(UART6_RxBuffer,0,0x400);
      k5 z6 _8 |2 I# t- |. Q
  47.                                 UART6_RxCounter = 0;
    : u) x' E. m0 N+ R% o4 G
  48.                                 HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
    " r" Y; ~. `* O, S8 {1 U
  49.                         }* l5 A5 d- H' ?. P; {) k; [1 y
  50.                        
    0 }0 `! P% x1 C" y! u9 b5 `
  51.                 }4 @' Y1 J3 V& N0 \
  52.         }7 B# e. ?- c( S; j, F. f6 ]
  53. }
复制代码

$ @; I3 Q7 o2 h4 B) x$ y

0 Q# o! I& p& D& ?) G7 L0 G核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。
3 b6 Y$ P- Z, w7 z& q# N$ m
  y( B6 h4 b) E4 z; v" y6 Q1 q

8 B2 [3 y; a" S& D- S: Y  ^  h( @3 ~& Q* D, T6 v: D( c9 R8 f

- Z8 O4 B4 D% Q: a文章出处:Outsider Hub
8 M) M' \8 z' |
赞 收藏 1 评论0 发布时间:2020-10-20 15:21

举报

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