此函数在mb.c文件中
eMBEnable用于使能协议栈,在初始化函数之后调用
Modbus初始化后,协议栈状态由eMBState由未初始化变成了STATE_DISABLED
eMBErrorCode
eMBEnable( void )
{eMBErrorCode eStatus = MB_ENOERR;if( eMBState == STATE_DISABLED ){/* Activate the protocol stack. */pvMBFrameStartCur( );eMBState = STATE_ENABLED;}else{eStatus = MB_EILLSTATE;}return eStatus;
}
先进行协议栈状态判断,若eMBState == STATE_DISABLED即初始化完成了,就激活协议栈。
调用pvMBFrameStartCur( );函数
然后另协议栈状态为STATE_ENABLED使能状态。
(注意eStatus是本函数返回值,为错误码,不要跟协议栈状态混淆)
这个函数是初始化时被赋值的函数pvMBFrameStartCur( );也就是说实际上调用的是eMBRTUStart
看一下eMBRTUStart这个函数
void
eMBRTUStart( void )
{ENTER_CRITICAL_SECTION( );/* Initially the receiver is in the state STATE_RX_INIT. we start* the timer and if no character is received within t3.5 we change* to STATE_RX_IDLE. This makes sure that we delay startup of the* modbus protocol stack until the bus is free.*/eRcvState = STATE_RX_INIT;vMBPortSerialEnable( TRUE, FALSE );vMBPortTimersEnable( );EXIT_CRITICAL_SECTION( );
}
这里要先引入两个状态机,接受状态机eMBRcvState和发送状态机eMBSndState。
eMBRcvState有四个状态:初始化,空闲态,接收中,帧无效(错误)
eMBSndState只有两个状态:空闲态,发送态
typedef enum
{STATE_RX_INIT, /*!< Receiver is in initial state. */STATE_RX_IDLE, /*!< Receiver is in idle state. */STATE_RX_RCV, /*!< Frame is beeing received. */STATE_RX_ERROR /*!< If the frame is invalid. */
} eMBRcvState;typedef enum
{STATE_TX_IDLE, /*!< Transmitter is in idle state. */STATE_TX_XMIT /*!< Transmitter is in transfer state. */
} eMBSndState;
所以RTU开始这个函数eMBRTUStart。
先将接收状态机赋值为初始化状态 eRcvState = STATE_RX_INIT;
然后vMBPortSerialEnable( TRUE, FALSE ); 串口接收使能,发送禁止。
vMBPortSerialEnable这个函数是在portserial.c文件中定义的,要由用户自己实现它。
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/if (xRxEnable) {/*还要设置485为接收模式*/__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);//使能接收中断} else {__HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);}if (xTxEnable) {/*还要设置485为发送模式*/__HAL_UART_ENABLE_IT(&huart2, UART_IT_TXE);//使能发送中断} else {__HAL_UART_DISABLE_IT(&huart2, UART_IT_TXE);}
}
然后调用vMBPortTimersEnable( );进行定时器使能。此函数要将计数清零,并开启定时器
vMBPortTimersEnable在文件porttimer.c文件中,由用户自己定义
inline void
vMBPortTimersEnable( )
{__HAL_TIM_CLEAR_IT(&htim7,TIM_IT_UPDATE);__HAL_TIM_SET_COUNTER(&htim7,0);HAL_TIM_Base_Start_IT(&htim7);/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
}
在定时器第一次溢出后会将接收状态机的状态由STATE_RX_INIT变为STATE_RX_IDLE。
使能流程:
eMBEnable→
pvMBFrameStartCur→
eMBRTUStart→
接收状态机eRcvState = STATE_RX_INIT→
串口使能vMBPortSerialEnable→
定时器使能vMBPortTimersEnable→
协议栈状态eMBState = STATE_ENABLED;