Modbus RTU主站移植到stm32 hal库

  1. 传统 modbus rtu主站源代码port串口是采用单个字节发送,但是stm32 hal库提供一帧发送、一帧接收,同时提供完成的中断处理。如果不直接采用hal库会带来不必要的工作难度
  2. 因此,修改modbus rtu主站代码,使其适用于stm32 hal库
  3. 整体思想:
    1. 不使用原中断服务函数xMBMasterRTUReceiveFSM,将对应功能移植到合适地方
    2. 不使用原中断服务函数xMBMasterRTUTransmitFSM,将对应功能移植到合适地方
  4.   portserial.c需要修改
    1. 串口使能函数
    2. if( xRxEnable ==TRUE)/*串口接收使能*/
          {
              HAL_GPIO_WritePin(UART3_DE3_GPIO_Port, UART3_DE3_Pin, GPIO_PIN_RESET);
              //        __HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);
      
              //获取接收buffer的地址
              vMBMasterGetRTURcvBuf( &pucFrame );
      
              //由于需要发送数据的地方都调用了该函数,因此作为统一的收、发接口
              //使用hal库自带的串口功能(中断模式)
              //由于每次不会接收到完成长度,使用前要复位以下状态机
      //        huart3.RxState=HAL_UART_STATE_READY;
              HAL_UART_Receive_IT(&huart3,pucFrame,MB_SER_PDU_SIZE_MAX);
      
      
          }
      
          if( xTxEnable ==TRUE)/*串口发送使能*/
          {
              HAL_GPIO_WritePin(UART3_DE3_GPIO_Port, UART3_DE3_Pin, GPIO_PIN_SET);
              //        __HAL_UART_ENABLE_IT(&huart3,UART_IT_TXE);
              //        prvvMasterUARTTxReadyISR();
      
      
              //获取发送bufer的地址
              vMBMasterGetRTUSndBuf( &pucFrame );
      
              //获取需要发送的长度
              SndBufferLength=vMBMasterGetRTUSndBufCount();
      
              //由于需要发送数据的地方都调用了该函数,因此作为统一的收、发接口
              //使用hal库自带的串口功能(中断模式)
              HAL_UART_Transmit_IT(&huart3,pucFrame,SndBufferLength );
      
      
          }

       

  5.  hal_uart.c需要修改
    1. UART_Receive_IT函数
    2.         //主站
              if(huart ->Instance == USART3)
              {
                  //切换SndState,这样下次进定时器中断才不会认定为超时
                  xMBMasterSetSndState(STATE_M_TX_IDLE);
      
                  //切换RcvState,这样下次进定时器会认定为接收完一帧
                  xMBMasterSetRcvState(STATE_M_RX_RCV);
      
                   /* Enable t3.5 timers. */
                  vMBMasterPortTimersEnable( );
      
              }

       

  6.  添加串口发送完成回调函数HAL_UART_TxCpltCallback
    1.    //主站
          if(huart->Instance==USART3 )
          {
              //主站发送完成后处理函数
              xMBMasterForHalTxCpltCallback();
          }
      
      
      
      
      
      
      /**
        * @brief  给 HAL_UART_TxCpltCallback()回调函数使用——接收完成
        *            由于很多变量都是.c文件内部static变量,不能外部调用,淫才采用该方法
        * @param  None
        * @retval None
        */
      void xMBMasterForHalTxCpltCallback(void)
      {
          xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
      
      
      
          eMasterSndState = STATE_M_TX_XFWR;
          /* If the frame is broadcast ,master will enable timer of convert delay,
       * else master will enable timer of respond timeout. */
          if ( xFrameIsBroadcast == TRUE )
          {
              vMBMasterPortTimersConvertDelayEnable( );
          }
          else
          {
              vMBMasterPortTimersRespondTimeoutEnable( );
          }
      
          /* Disable transmitter. This prevents another transmit buffer
       * empty interrupt. */
          vMBMasterPortSerialEnable( TRUE, FALSE );
      }

       

  7.  mbuart_m.c需要修改
    1. 定时器中断服务函数   xMBMasterRTUTimerExpired
    2. case STATE_M_RX_RCV:
              //接收完成,从huart结构体复制数据
              //接收完成后,获取接收帧的长度
              usMasterRcvBufferPos=(huart3.RxXferSize)-(huart3.RxXferCount);
      
              //切换状态机,否则下次调用HAL_UART_Receive_IT  不会进去
              /* Rx process is completed, restore huart->RxState to Ready */
              huart3.RxState = HAL_UART_STATE_READY; 
      
      
      
      
      
      
      case STATE_M_TX_XFWR:
      
              //切换状态机,否则下次调用HAL_UART_Receive_IT  不会进去
              /* Rx process is completed, restore huart->RxState to Ready */
              huart3.RxState = HAL_UART_STATE_READY;
      
      
      
      

       

  8.  
  9.  
  10.  
  11.  
  12.  
  13.   
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  

你可能感兴趣的:(笔记)