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

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

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


功能实现背景介绍
本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。

使用的报文规则如表格所示
11.png
板间报文的通信协议,校验使用的是和校验
  1. <font size="3">U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
  2. {
  3.     U8 i, ret = 0;
  4.     for(i=0; i<len; i++)
  5.     {
  6.         ret += *(buf++);
  7.     }
  8.      ret = ~ret;
  9.     return ret;
  10. }
  11. U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
  12. {
  13.     U8 i, ret = 0;
  14.      for(i=0; i<len; i++)
  15.     {
  16.         ret += *(buf++);
  17.     }
  18.     ret = ret;
  19.     return ret+1;
  20. }</font>
复制代码


发送和接收的报文要满足不定长
HAL库的中断接收函数
如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数

  1. HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA
复制代码


在使用时,选择串口,选择接收的缓冲区,选择接收长度。


  1. /**
  2.   * @brief  Receives an amount of data in non blocking mode.
  3.   * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  4.   *         the received data is handled as a set of u16. In this case, Size must indicate the number
  5.   *         of u16 available through pData.
  6.   * @param  huart Pointer to a UART_HandleTypeDef structure that contains
  7.   *               the configuration information for the specified UART module.
  8.   * @param  pData Pointer to data buffer (u8 or u16 data elements).
  9.   * @param  Size  Amount of data elements (u8 or u16) to be received.
  10.   * @retval HAL status
  11.   */
  12. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
  13. {
  14.   /* Check that a Rx process is not already ongoing */
  15.   if (huart->RxState == HAL_UART_STATE_READY)
  16.   {
  17.     if ((pData == NULL) || (Size == 0U))
  18.     {
  19.       return HAL_ERROR;
  20.     }

  21.     /* Process Locked */
  22.     __HAL_LOCK(huart);

  23.     huart->pRxBuffPtr = pData;
  24.     huart->RxXferSize = Size;
  25.     huart->RxXferCount = Size;

  26.     huart->ErrorCode = HAL_UART_ERROR_NONE;
  27.     huart->RxState = HAL_UART_STATE_BUSY_RX;

  28.     /* Process Unlocked */
  29.     __HAL_UNLOCK(huart);

  30.     /* Enable the UART Parity Error Interrupt */
  31.     __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

  32.     /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
  33.     __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

  34.     /* Enable the UART Data Register not empty Interrupt */
  35.     __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

  36.     return HAL_OK;
  37.   }
  38.   else
  39.   {
  40.     return HAL_BUSY;
  41.   }
  42. }
复制代码


这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。
我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。
状态机的运用
对于不定长数据的接收,使用了状态机,分两次中断来接收数据

12.png
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  2. {
  3.         if(huart->Instance == USART6)                                         // 判断是由哪个串口触发的中断
  4.         {
  5.                 if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验
  6.                 {       
  7.       if(re_flag6 == 1)
  8.                         {
  9.                                 UART6_RxCounter = 6;
  10.                                 re_flag6 = 0;
  11.                         }       
  12.       else
  13.                         {
  14.                                 len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  
  15.                           if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)       
  16.                           {
  17.                                   UART6_RxCounter = len_counter6;
  18.                           }       
  19.         else
  20.                           {
  21.                                   memset(UART6_RxBuffer,0,0x400);
  22.                                         UART6_RxCounter = 0;
  23.                           }               
  24.                         }                               
  25.                      
  26.                         StateMachine_USART6 = 0;                                   //状态机为0
  27.       len_counter6 = 0;                       
  28.                         HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);               
  29.                 }
  30.                 else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节
  31.                 {                                       
  32.                         if(UART6_RxBuffer[0] == 0xAA)
  33.                         {
  34.                                 StateMachine_USART6 = 1;
  35.                                 UART6_RxCounter = 5;
  36.                                 if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
  37.                           {
  38.                                   HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);
  39.                                         re_flag6 = 1;
  40.                           }
  41.                           else
  42.                             HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));
  43.                         }
  44.                         else
  45.                         {
  46.                                 memset(UART6_RxBuffer,0,0x400);
  47.                                 UART6_RxCounter = 0;
  48.                                 HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
  49.                         }
  50.                        
  51.                 }
  52.         }
  53. }
复制代码


核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。




文章出处:Outsider Hub
收藏 1 评论0 发布时间:2020-10-20 15:21

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版