当前位置: 代码迷 >> 综合 >> Modbus RTU主站移植到stm32 hal库
  详细解决方案

Modbus RTU主站移植到stm32 hal库

热度:83   发布时间:2023-12-18 09:10:43.0
  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.