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

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

[复制链接]
STMCU-管管 发布时间:2020-10-20 15:21
STM32串口中断接收不定长报文并解析
, M/ A7 @5 y" F0 W
/ R' x: Z4 C2 J6 {5 f  I
功能实现背景介绍
$ l# Z8 v% z# ?本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。
9 o, r4 M+ z5 S3 O4 M- z. A( L
使用的报文规则如表格所示6 m7 w5 x5 [8 B' g1 J  G8 G
11.png
: S  a: F: ^) b板间报文的通信协议,校验使用的是和校验
: _- l4 E& Z5 c, F6 o  O( G
  1. <font size="3">U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    : b+ \- b5 w- i+ q
  2. {
    : g7 @7 L  X4 s/ Y" C! U
  3.     U8 i, ret = 0;
    + D+ D+ l  G7 _2 h7 H2 L6 p
  4.     for(i=0; i<len; i++): @& b* ?; n* p9 Y
  5.     {1 U2 w" U& \9 M. U' H
  6.         ret += *(buf++);5 d6 A( i2 W" W: I. @% G% \
  7.     }
    # Y$ C8 O8 F3 A" ~5 y. {
  8.      ret = ~ret;
    / p4 S+ F' h/ p( h" k9 q
  9.     return ret;
    ) H6 M8 l. A5 A; z6 a, y
  10. }7 f( x9 o; F& S4 f# G) A
  11. U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
    9 ]! Q) g3 P) d# Y9 K
  12. { 7 w4 q3 }8 l, b) N1 e# c
  13.     U8 i, ret = 0;( K9 l% K" P" A: \
  14.      for(i=0; i<len; i++)
    & }. n9 X2 G! i# M% x/ G
  15.     {
    6 _+ Y/ l' j" b2 u
  16.         ret += *(buf++);: o  G5 u6 q7 X1 q  r
  17.     }5 R) P! L9 J4 x4 C: c4 ?; B! Q
  18.     ret = ret;$ b) \5 A1 ]% }; I
  19.     return ret+1;
    ( `! X. B8 f0 y$ e" L
  20. }</font>
复制代码

# C" S$ Q4 r2 d, Z' o+ E7 `9 k$ z4 G$ N# h4 Y
发送和接收的报文要满足不定长
; I, N: O5 g8 \. Q% A$ |9 T# I! ^HAL库的中断接收函数0 E+ @9 [1 ]) \: ~: t7 {$ z
如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数
7 _* g9 I2 N2 g4 U  B2 C
  1. HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA
复制代码
( j7 m1 G1 f. [0 I) h/ p6 W

: ^5 Y# L) Q( P2 Q在使用时,选择串口,选择接收的缓冲区,选择接收长度。
; \& Z3 \$ p' T) w5 d. i7 V. K
# J) |( [5 f: R; A4 T

- ^/ p; b7 _; S. r+ _! J( W0 X
  1. /**6 g' ^& L5 ?$ n* T# D" |! u1 K
  2.   * @brief  Receives an amount of data in non blocking mode.0 H6 u% {9 C* `4 F
  3.   * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),+ ?( ]* C. \' a! u. n" H+ T1 Y
  4.   *         the received data is handled as a set of u16. In this case, Size must indicate the number9 b  _. x8 x# G$ T' T( M
  5.   *         of u16 available through pData.( @+ v( q6 F( P3 e; D/ V
  6.   * @param  huart Pointer to a UART_HandleTypeDef structure that contains
    * E+ c2 M( S3 b
  7.   *               the configuration information for the specified UART module.
    ! d6 n) C" J3 V
  8.   * @param  pData Pointer to data buffer (u8 or u16 data elements).! j  Y+ z# i  X) z
  9.   * @param  Size  Amount of data elements (u8 or u16) to be received.
    . @- P8 r" r7 K0 @' V0 e! @( w; d8 p
  10.   * @retval HAL status
    # j" C3 F+ J  j' g" r. s7 Y" b
  11.   */4 h1 q$ \( X% o. j, o" W; i
  12. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)) P% w: a3 g$ u: ~) p9 Z5 k/ j
  13. {. j: b: e4 o( L! c
  14.   /* Check that a Rx process is not already ongoing */) M2 o0 d( V5 T) m) T* k% ]/ L$ R
  15.   if (huart->RxState == HAL_UART_STATE_READY)2 U& R* Q% x" Q" h  H& v' ?7 Q& _
  16.   {
    5 g2 u$ {8 x9 F! X
  17.     if ((pData == NULL) || (Size == 0U))
    # p3 Y+ q6 ?7 @
  18.     {
      m& u6 ~* p* |; q. `7 V
  19.       return HAL_ERROR;$ P6 y5 b7 B$ F8 Q' D1 d; R! S
  20.     }
    ( h- U$ x8 k0 r0 X

  21. 2 S/ R# M6 i. I
  22.     /* Process Locked */* H0 B$ c& o' ?. u4 K
  23.     __HAL_LOCK(huart);7 f8 A6 _9 T  }! `  K

  24. 3 y8 s. n* y4 ]2 o6 j
  25.     huart->pRxBuffPtr = pData;1 F: p. E) X- L4 v. x2 @; q" ?
  26.     huart->RxXferSize = Size;4 s% e1 q, d+ z1 C
  27.     huart->RxXferCount = Size;' K; u$ e* u2 u: T' l1 c3 B# s

  28. 0 O& q% A) P# `
  29.     huart->ErrorCode = HAL_UART_ERROR_NONE;/ `! r- I- I5 M" v8 e* K; L, L2 z5 N
  30.     huart->RxState = HAL_UART_STATE_BUSY_RX;$ f5 x6 T3 Q) k3 g& f% M( C( P
  31. 0 F8 z7 }- K) O5 s! [
  32.     /* Process Unlocked */
    ) P! R  O/ c1 N0 }' }/ `, V
  33.     __HAL_UNLOCK(huart);
    $ z# ]2 y- U! y
  34. + M* o) M" ?0 T- ^. c* A
  35.     /* Enable the UART Parity Error Interrupt */7 m: q3 s) E/ [
  36.     __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
    7 i4 g( D8 r5 C, Q

  37. 2 f" e+ h: }5 ^% E7 T
  38.     /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */$ U3 p8 i# T$ l3 p
  39.     __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);# V6 g8 M  w! |7 P0 \9 Y
  40.   n* Q! e/ x9 j4 ^- Y
  41.     /* Enable the UART Data Register not empty Interrupt */% B) g- C- j9 F- [$ ~8 u$ g; V
  42.     __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
    + ]8 k  q; Z, V/ L# R
  43. / n5 P" b5 T7 q* C8 W6 [
  44.     return HAL_OK;( Y' I' x5 _6 h2 w
  45.   }
    9 @( k4 k5 q3 V8 L9 Q* X6 C! Z
  46.   else
    7 v5 {8 n& s, y' N1 w$ ^; d# t- q
  47.   {/ G# P2 E2 A  q- H8 w4 A" G
  48.     return HAL_BUSY;
    " |1 T: h+ P3 S6 A- @
  49.   }
    2 \" }$ ~( L, G  f
  50. }
复制代码
3 B* ^" a9 [  c3 k1 t, g# Y7 V; T
" \/ I- ]% W( _/ I0 C
这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。
, ~( R1 K! ?6 V我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。% Z2 ~% R, z+ V4 T
状态机的运用
9 I: U& A+ P  F: q7 e# J对于不定长数据的接收,使用了状态机,分两次中断来接收数据

" X  {2 E5 J# \. k& @( ]5 {
12.png ; I" B( F( Y7 I8 N) q! E
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    % C$ |3 y0 ~4 S( c
  2. {4 N0 {' {1 S/ G5 M* S
  3.         if(huart->Instance == USART6)                                         // 判断是由哪个串口触发的中断, H$ T* A2 n3 ~+ r- {
  4.         {# a  l  ~2 U0 d9 g# F
  5.                 if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验
    ' f9 o( z! \* F
  6.                 {       
    1 m$ m1 @' Q* Q; i& N- C, ?
  7.       if(re_flag6 == 1)
    6 F0 i# Z% Z) E# f
  8.                         {
    ; ?' u* m# K9 N& d. @
  9.                                 UART6_RxCounter = 6;
    4 f3 l* e: _2 X$ p7 _: A% s
  10.                                 re_flag6 = 0;6 H8 X7 \4 m+ I, ^# K1 ~2 v
  11.                         }       
    6 d& [" ?3 ?* F7 q  v
  12.       else* N( q8 \: ^' E" n
  13.                         {9 F6 n9 o2 T# c
  14.                                 len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  
    ' h3 W% }' V4 s( p% M9 R1 s
  15.                           if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)        1 r4 N4 s0 N5 }0 K  r* G8 M
  16.                           {* @9 `' G' ]! ?' T! D5 O4 `) G
  17.                                   UART6_RxCounter = len_counter6;
    ! ?4 c* `! ]  u2 \
  18.                           }       
    ) x$ z) @, ~1 E) C, h8 g: \
  19.         else
    ' r+ Y8 P8 I" k3 F( I. W5 z3 E9 Y
  20.                           {
    + g% u& j  F# v8 b! R' i2 `! h% x% ~
  21.                                   memset(UART6_RxBuffer,0,0x400);" U2 d, c7 F: [
  22.                                         UART6_RxCounter = 0;
    - z) M/ }- h: B( X0 s6 \/ F
  23.                           }                # _0 ^6 I4 p! v  s
  24.                         }                                # K. @* x6 }! r6 p) V+ V" H) d
  25.                      
    5 k0 E! J' ^( D% Z6 |  [0 m
  26.                         StateMachine_USART6 = 0;                                   //状态机为00 E, m4 [  a6 N6 J' h5 L) q4 c$ n
  27.       len_counter6 = 0;                       
    3 o) \- V  `! [1 L+ m6 X' r& f! m  t7 Y& M
  28.                         HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);                * L* v8 J" {: O7 x
  29.                 }3 N+ ?, `8 d5 n; `5 g
  30.                 else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节
    $ ^3 I, P0 p$ s' J
  31.                 {                                       
    9 d' `! @/ [4 x! o4 [. w4 T$ Q
  32.                         if(UART6_RxBuffer[0] == 0xAA)6 h* t! k+ {* n. d" A( {! w
  33.                         {
    9 _) q+ Y6 `" l( i1 d: [0 T9 S
  34.                                 StateMachine_USART6 = 1;
    . K' T: \! D- j$ F8 g' b# w9 P, D
  35.                                 UART6_RxCounter = 5;! K2 l5 B8 K& r8 I
  36.                                 if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
    1 a/ D& |: I7 N$ F1 h
  37.                           {
    ! b5 E- `( D4 @7 ]8 X% _4 ]
  38.                                   HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);* ~$ k/ T* x4 C! k
  39.                                         re_flag6 = 1;
    ' t3 @) g( e9 |" V
  40.                           }1 o" U* r: F: C: o; c* z
  41.                           else/ z$ o' B; u3 j# E4 ]4 C
  42.                             HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));2 l$ _# F4 ^0 T  W' }9 A- A# @9 o
  43.                         }
    : d5 @6 P& I0 t- N+ I$ W0 a
  44.                         else
    . v3 R" t& ~/ \' a$ ]% M/ [' M- j6 U8 S
  45.                         {
    * x) C% c0 w9 ?& @
  46.                                 memset(UART6_RxBuffer,0,0x400);. T5 l( M" h, a  F: N+ I3 Q
  47.                                 UART6_RxCounter = 0;" x* [; P6 M% K  e! _
  48.                                 HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
    : {0 v/ d' Z- D% D5 c( ~% L
  49.                         }
    ' j/ `7 p; W3 G. P
  50.                        
    8 U4 z# q. G: r6 L
  51.                 }5 M! r% }, V7 a
  52.         }# K$ l& P. H5 F9 c9 K+ G: [
  53. }
复制代码

4 Y9 D5 w, i: Q$ j" @7 ]
' I  g2 m8 A! M: d0 M" a
核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。
- w) X' m4 K. L' b+ f7 M2 q$ P
# \) Y2 V" G6 Z* T, B5 h

& q' X8 |3 P! e3 s% @+ @# m% ]3 T9 n+ m

/ ~4 y( ]3 s# m4 p$ E$ {/ B文章出处:Outsider Hub
+ i% h9 b6 y8 B  F. h2 Q# f
收藏 1 评论0 发布时间:2020-10-20 15:21

举报

0个回答

所属标签

相似分享

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