提交 d8bbb5f1 编写于 作者: armink_ztl's avatar armink_ztl

[modbus]update modbus master and slave source code to lastest.

上级 204298c1
......@@ -74,14 +74,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_COILS_ENABLED > 0
/**
* This function will request read coil.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usNCoils coil total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -93,6 +103,8 @@ eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -108,7 +120,12 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
......@@ -136,7 +153,7 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
......@@ -161,15 +178,27 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_COIL_ENABLED > 0
/**
* This function will request write one coil.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usCoilData data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*
* @see eMBMasterReqWriteMultipleCoils
*/
eMBMasterReqErrCode
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -181,6 +210,7 @@ eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -214,7 +244,7 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
ucBuf[0] = 0;
}
eRegStatus =
eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
......@@ -240,18 +270,31 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
/**
* This function will request write multiple coils.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usNCoils coil total number
* @param usCoilData data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*
* @see eMBMasterReqWriteCoil
*/
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer )
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut)
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
UCHAR ucByteCount;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -277,6 +320,7 @@ eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -293,7 +337,8 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE )
/* If this request is broadcast, the *usLen is not need check. */
if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
......@@ -318,7 +363,7 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) )
{
eRegStatus =
eMBRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usCoilCnt, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
......
......@@ -57,16 +57,26 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_COILS_ENABLED > 0
#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
/**
* This function will request read discrete inputs.
*
* @param ucSndAddr salve address
* @param usDiscreteAddr discrete start address
* @param usNDiscreteIn discrete total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn )
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -78,6 +88,7 @@ eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT u
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -93,7 +104,12 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
......@@ -120,7 +136,7 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
{
/* Make callback to fill the buffer. */
eRegStatus = eMBRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
......
......@@ -86,14 +86,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_WRITE_HOLDING_ENABLED > 0
/**
* This function will request write holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usRegData register data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData )
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -105,6 +115,7 @@ eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRe
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -123,7 +134,7 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
/* Make callback to update the value. */
eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
......@@ -143,16 +154,27 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
/**
* This function will request write multiple holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param pusDataBuffer data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer )
USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -171,6 +193,7 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -186,7 +209,8 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE )
/* If this request is broadcast, the *usLen is not need check. */
if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
......@@ -202,7 +226,7 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
/* Make callback to update the register values. */
eRegStatus =
eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usRegCount, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
......@@ -227,14 +251,24 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_READ_HOLDING_ENABLED > 0
/**
* This function will request read holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -246,6 +280,7 @@ eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRe
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -260,7 +295,12 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
......@@ -268,7 +308,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
......@@ -276,7 +316,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
......@@ -300,17 +340,30 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
/**
* This function will request read and write holding register.
*
* @param ucSndAddr salve address
* @param usReadRegAddr read register start address
* @param usNReadRegs read register total number
* @param pusDataBuffer data to be written
* @param usWriteRegAddr write register start address
* @param usNWriteRegs write register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
USHORT usWriteRegAddr, USHORT usNWriteRegs )
USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -333,6 +386,7 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -349,7 +403,12 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN)
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
......@@ -369,13 +428,13 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] )
{
/* Make callback to update the register values. */
eRegStatus = eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
if( eRegStatus == MB_ENOERR )
{
/* Make the read callback. */
eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
usRegReadAddress, usRegReadCount, MB_REG_READ);
}
if( eRegStatus != MB_ENOERR )
......
......@@ -59,14 +59,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_INPUT_ENABLED > 0
/**
* This function will request read input register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
......@@ -78,6 +88,7 @@ eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
......@@ -92,7 +103,12 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN)
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
......@@ -100,7 +116,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
......@@ -108,7 +124,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
......
......@@ -77,13 +77,10 @@ typedef enum
MB_MRE_NO_ERR, /*!< no error. */
MB_MRE_NO_REG, /*!< illegal register address. */
MB_MRE_ILL_ARG, /*!< illegal argument. */
MB_MRE_PORT_ERR, /*!< porting layer error. */
MB_MRE_NO_RES, /*!< insufficient resources. */
MB_MRE_IO, /*!< I/O error. */
MB_MRE_ILL_STATE, /*!< protocol stack in illegal state. */
MB_MRE_REV_DATA, /*!< receive data error. */
MB_MRE_TIMEDOUT, /*!< timeout error occurred. */
MB_MRE_MASTER_BUSY, /*!< master is busy now. */
MB_MRE_SLAVE_EXCE /*!< slave has exception. */
MB_MRE_EXE_FUN /*!< execute function error. */
} eMBMasterReqErrCode;
/*! \ingroup modbus
* \brief TimerMode is Master 3 kind of Timer modes.
......@@ -189,31 +186,176 @@ eMBErrorCode eMBMasterDisable( void );
*/
eMBErrorCode eMBMasterPoll( void );
/*! \ingroup modbus
* \brief Registers a callback handler for a given function code.
*
* This function registers a new callback handler for a given function code.
* The callback handler supplied is responsible for interpreting the Modbus PDU and
* the creation of an appropriate response. In case of an error it should return
* one of the possible Modbus exceptions which results in a Modbus exception frame
* sent by the protocol stack.
*
* \param ucFunctionCode The Modbus function code for which this handler should
* be registers. Valid function codes are in the range 1 to 127.
* \param pxHandler The function handler which should be called in case
* such a frame is received. If \c NULL a previously registered function handler
* for this function code is removed.
*
* \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
* more resources are available it returns eMBErrorCode::MB_ENORES. In this
* case the values in mbconfig.h should be adjusted. If the argument was not
* valid it returns eMBErrorCode::MB_EINVAL.
*/
eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
pxMBFunctionHandler pxHandler );
/* ----------------------- Callback -----------------------------------------*/
/*! \defgroup modbus_master registers Modbus Registers
* \code #include "mb_m.h" \endcode
* The protocol stack does not internally allocate any memory for the
* registers. This makes the protocol stack very small and also usable on
* low end targets. In addition the values don't have to be in the memory
* and could for example be stored in a flash.<br>
* Whenever the protocol stack requires a value it calls one of the callback
* function with the register address and the number of registers to read
* as an argument. The application should then read the actual register values
* (for example the ADC voltage) and should store the result in the supplied
* buffer.<br>
* If the protocol stack wants to update a register value because a write
* register function was received a buffer with the new register values is
* passed to the callback function. The function should then use these values
* to update the application register values.
*/
/*! \ingroup modbus_registers
* \brief Callback function used if the value of a <em>Input Register</em>
* is required by the protocol stack. The starting register address is given
* by \c usAddress and the last register is given by <tt>usAddress +
* usNRegs - 1</tt>.
*
* \param pucRegBuffer A buffer where the callback function should write
* the current value of the modbus registers to.
* \param usAddress The starting address of the register. Input registers
* are in the range 1 - 65535.
* \param usNRegs Number of registers the callback function must supply.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Holding Register</em> value is
* read or written by the protocol stack. The starting register address
* is given by \c usAddress and the last register is given by
* <tt>usAddress + usNRegs - 1</tt>.
*
* \param pucRegBuffer If the application registers values should be updated the
* buffer points to the new registers values. If the protocol stack needs
* to now the current values the callback function should write them into
* this buffer.
* \param usAddress The starting address of the register.
* \param usNRegs Number of registers to read or write.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application register
* values should be updated from the values in the buffer. For example
* this would be the case when the Modbus master has issued an
* <b>WRITE SINGLE REGISTER</b> command.
* If the value eMBRegisterMode::MB_REG_READ the application should copy
* the current values into the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Coil Register</em> value is
* read or written by the protocol stack. If you are going to use
* this function you might use the functions xMBUtilSetBits( ) and
* xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The bits are packed in bytes where the first coil
* starting at address \c usAddress is stored in the LSB of the
* first byte in the buffer <code>pucRegBuffer</code>.
* If the buffer should be written by the callback function unused
* coil values (I.e. if not a multiple of eight coils is used) should be set
* to zero.
* \param usAddress The first coil number.
* \param usNCoils Number of coil values requested.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
* be updated from the values supplied in the buffer \c pucRegBuffer.
* If eMBRegisterMode::MB_REG_READ the application should store the current
* values in the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNCoils, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Input Discrete Register</em> value is
* read by the protocol stack.
*
* If you are going to use his function you might use the functions
* xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The buffer should be updated with the current
* coil values. The first discrete input starting at \c usAddress must be
* stored at the LSB of the first byte in the buffer. If the requested number
* is not a multiple of eight the remaining bits should be set to zero.
* \param usAddress The starting address of the first discrete input.
* \param usNDiscrete Number of discrete input values.
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNDiscrete );
/*! \ingroup modbus
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
*/
eMBMasterReqErrCode
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData );
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer );
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr,
USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
USHORT usWriteRegAddr, USHORT usNWriteRegs );
USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils );
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData );
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer );
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn );
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut );
eMBException
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
......@@ -239,16 +381,18 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
/*£¡ \ingroup modbus
*\brief These functions are interface for Modbus Master
*/
BOOL xMBMasterGetIsBusy( void );
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame );
UCHAR ucMBMasterGetDestAddress( void );
void vMBMasterSetDestAddress( UCHAR Address );
void vMBMasterSetIsBusy( BOOL IsBusy );
BOOL xMBMasterGetCBRunInMasterMode( void );
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode );
UCHAR ucMBMasterGetPDUSndLength( void );
void vMBMasterSetPDUSndLength( UCHAR SendPDULength );
USHORT usMBMasterGetPDUSndLength( void );
void vMBMasterSetPDUSndLength( USHORT SendPDULength );
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode );
BOOL xMBMasterRequestIsBroadcast( void );
eMBMasterErrorEventType eMBMasterGetErrorType( void );
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
/* ----------------------- Callback -----------------------------------------*/
......
......@@ -115,9 +115,9 @@ PR_BEGIN_EXTERN_C
/*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave.
* And if slave is not respond in this time,the master will process this timeout error.
* Then master can send other frame */
#define MB_MASTER_TIMEOUT_MS_RESPOND (2000)
/*! \brief The total slaves in Modbus Master system.Default 16.
* Note : The slave ID must be continuous from 0.*/
#define MB_MASTER_TIMEOUT_MS_RESPOND (100 )
/*! \brief The total slaves in Modbus Master system. Default 16.
* \note : The slave ID must be continuous from 1.*/
#define MB_MASTER_TOTAL_SLAVE_NUM ( 16 )
#endif
......
......@@ -36,25 +36,38 @@
PR_BEGIN_EXTERN_C
#endif
/* ----------------------- Defines ------------------------------------------*/
/* ----------------------- Type definitions ---------------------------------*/
typedef enum
{
EV_READY, /*!< Startup finished. */
EV_FRAME_RECEIVED, /*!< Frame received. */
EV_EXECUTE, /*!< Execute function. */
EV_FRAME_SENT /*!< Frame sent. */
EV_READY = 1<<0, /*!< Startup finished. */
EV_FRAME_RECEIVED = 1<<1, /*!< Frame received. */
EV_EXECUTE = 1<<2, /*!< Execute function. */
EV_FRAME_SENT = 1<<3 /*!< Frame sent. */
} eMBEventType;
typedef enum
{
EV_MASTER_READY, /*!< Startup finished. */
EV_MASTER_FRAME_RECEIVED, /*!< Frame received. */
EV_MASTER_EXECUTE, /*!< Execute function. */
EV_MASTER_FRAME_SENT, /*!< Frame sent. */
EV_MASTER_ERROR_PROCESS /*!< Frame error process*/
EV_MASTER_READY = 1<<0, /*!< Startup finished. */
EV_MASTER_FRAME_RECEIVED = 1<<1, /*!< Frame received. */
EV_MASTER_EXECUTE = 1<<2, /*!< Execute function. */
EV_MASTER_FRAME_SENT = 1<<3, /*!< Frame sent. */
EV_MASTER_ERROR_PROCESS = 1<<4, /*!< Frame error process. */
EV_MASTER_PROCESS_SUCESS = 1<<5, /*!< Request process success. */
EV_MASTER_ERROR_RESPOND_TIMEOUT = 1<<6, /*!< Request respond timeout. */
EV_MASTER_ERROR_RECEIVE_DATA = 1<<7, /*!< Request receive data error. */
EV_MASTER_ERROR_EXECUTE_FUNCTION = 1<<8, /*!< Request execute function error. */
} eMBMasterEventType;
typedef enum
{
EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */
EV_ERROR_RECEIVE_DATA, /*!< Receive frame data erroe. */
EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
} eMBMasterErrorEventType;
/*! \ingroup modbus
* \brief Parity used for characters in serial mode.
*
......@@ -82,6 +95,12 @@ BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent );
BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent );
void vMBMasterOsResInit( void );
BOOL xMBMasterRunResTake( int32_t time );
void vMBMasterRunResRelease( void );
/* ----------------------- Serial port functions ----------------------------*/
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
......@@ -97,7 +116,6 @@ INLINE BOOL xMBPortSerialGetByte( CHAR * pucByte );
INLINE BOOL xMBPortSerialPutByte( CHAR ucByte );
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
UCHAR ucDataBits, eMBParity eParity );
......@@ -132,6 +150,18 @@ INLINE void vMBMasterPortTimersRespondTimeoutEnable( void );
INLINE void vMBMasterPortTimersDisable( void );
/* ----------------- Callback for the master error process ------------------*/
void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData,
USHORT ucPDULength );
void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData,
USHORT ucPDULength );
void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData,
USHORT ucPDULength );
void vMBMasterCBRequestScuuess( void );
/* ----------------------- Callback for the protocol stack ------------------*/
/*!
......
......@@ -65,7 +65,7 @@
static UCHAR ucMBMasterDestAddress;
static BOOL xMBRunInMasterMode = FALSE;
static BOOL xMasterIsBusy = FALSE;
static eMBMasterErrorEventType eMBMasterCurErrorType;
static enum
{
......@@ -185,6 +185,8 @@ eMBMasterInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity
{
eMBState = STATE_DISABLED;
}
/* initialize the OS resource for modbus master. */
vMBMasterOsResInit();
}
return eStatus;
}
......@@ -257,9 +259,10 @@ eMBMasterPoll( void )
static USHORT usLength;
static eMBException eException;
int i;
int i , j;
eMBErrorCode eStatus = MB_ENOERR;
eMBMasterEventType eEvent;
eMBMasterErrorEventType errorType;
/* Check if the protocol stack is ready. */
if( eMBState != STATE_ENABLED )
......@@ -285,6 +288,7 @@ eMBMasterPoll( void )
}
else
{
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
}
break;
......@@ -292,52 +296,80 @@ eMBMasterPoll( void )
case EV_MASTER_EXECUTE:
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
eException = MB_EX_ILLEGAL_FUNCTION;
for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
{
/* No more function handlers registered. Abort. */
if( xMasterFuncHandlers[i].ucFunctionCode == 0 )
{
break;
}
else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode )
{
vMBMasterSetCBRunInMasterMode(TRUE);
eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
vMBMasterSetCBRunInMasterMode(FALSE);
break;
}
}
/* If receive frame has exception .The receive function code highest bit is 1.*/
if(ucFunctionCode >> 7) eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
if(ucFunctionCode >> 7) {
eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
}
else
{
for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++)
{
/* No more function handlers registered. Abort. */
if (xMasterFuncHandlers[i].ucFunctionCode == 0) {
break;
}
else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) {
vMBMasterSetCBRunInMasterMode(TRUE);
/* If master request is broadcast,
* the master need execute function for all slave.
*/
if ( xMBMasterRequestIsBroadcast() ) {
usLength = usMBMasterGetPDUSndLength();
for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){
vMBMasterSetDestAddress(j);
eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
}
}
else {
eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
}
vMBMasterSetCBRunInMasterMode(FALSE);
break;
}
}
}
/* If master has exception ,Master will send error process.Otherwise the Master is idle.*/
if (eException != MB_EX_NONE) ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
else vMBMasterSetIsBusy( FALSE );
if (eException != MB_EX_NONE) {
vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
}
else {
vMBMasterCBRequestScuuess( );
vMBMasterRunResRelease( );
}
break;
case EV_MASTER_FRAME_SENT:
/* Master is busy now. */
vMBMasterSetIsBusy( TRUE );
vMBMasterGetPDUSndBuf( &ucMBFrame );
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, ucMBMasterGetPDUSndLength() );
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
break;
case EV_MASTER_ERROR_PROCESS:
vMBMasterSetIsBusy( FALSE );
/* Execute specified error process callback function. */
errorType = eMBMasterGetErrorType();
vMBMasterGetPDUSndBuf( &ucMBFrame );
switch (errorType) {
case EV_ERROR_RESPOND_TIMEOUT:
vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(),
ucMBFrame, usMBMasterGetPDUSndLength());
break;
case EV_ERROR_RECEIVE_DATA:
vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(),
ucMBFrame, usMBMasterGetPDUSndLength());
break;
case EV_ERROR_EXECUTE_FUNCTION:
vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(),
ucMBFrame, usMBMasterGetPDUSndLength());
break;
}
vMBMasterRunResRelease();
break;
}
}
return MB_ENOERR;
}
/* Get whether the Modbus Master is busy.*/
BOOL xMBMasterGetIsBusy( void )
{
return xMasterIsBusy;
}
/* Set whether the Modbus Master is busy.*/
void vMBMasterSetIsBusy( BOOL IsBusy )
{
xMasterIsBusy = IsBusy;
}
/* Get whether the Modbus Master is run in master mode.*/
BOOL xMBMasterGetCBRunInMasterMode( void )
{
......@@ -348,15 +380,27 @@ void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
{
xMBRunInMasterMode = IsMasterMode;
}
/* Get Modbus Master send destination address*/
/* Get Modbus Master send destination address. */
UCHAR ucMBMasterGetDestAddress( void )
{
return ucMBMasterDestAddress;
}
/* Set Modbus Master send destination address*/
/* Set Modbus Master send destination address. */
void vMBMasterSetDestAddress( UCHAR Address )
{
ucMBMasterDestAddress = Address;
}
/* Get Modbus Master current error event type. */
eMBMasterErrorEventType eMBMasterGetErrorType( void )
{
return eMBMasterCurErrorType;
}
/* Set Modbus Master current error event type. */
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
{
eMBMasterCurErrorType = errorType;
}
#endif
......@@ -74,7 +74,7 @@ static volatile eMBMasterRcvState eRcvState;
static volatile UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
static volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX];
static volatile UCHAR ucMasterSendPDULength;
static volatile USHORT usMasterSendPDULength;
static volatile UCHAR *pucMasterSndBufferCur;
static volatile USHORT usMasterSndBufferCount;
......@@ -235,7 +235,7 @@ xMBMasterRTUReceiveFSM( void )
BOOL xTaskNeedSwitch = FALSE;
UCHAR ucByte;
assert_param( eSndState == STATE_M_TX_IDLE );
assert_param(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR ));
/* Always read the character. */
( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
......@@ -364,12 +364,15 @@ xMBMasterRTUTimerExpired(void)
/* An error occured while receiving the frame. */
case STATE_M_RX_ERROR:
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
break;
/* Function called in an illegal state. */
default:
assert_param(
( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || ( eRcvState == STATE_M_RX_ERROR ));
( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) ||
( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE ));
break;
}
eRcvState = STATE_M_RX_IDLE;
......@@ -380,18 +383,24 @@ xMBMasterRTUTimerExpired(void)
* If the frame is broadcast,The master will idle,and if the frame is not
* broadcast.Notify the listener process error.*/
case STATE_M_TX_XFWR:
if ( xFrameIsBroadcast == FALSE ) xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
if ( xFrameIsBroadcast == FALSE ) {
vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT);
xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
}
break;
/* Function called in an illegal state. */
default:
assert_param( eSndState == STATE_M_TX_XFWR );
assert_param(
( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE ));
break;
}
eSndState = STATE_M_TX_IDLE;
vMBMasterPortTimersDisable( );
/* If timer mode is convert delay ,then Master is idel now. */
if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) vMBMasterSetIsBusy( FALSE );
/* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */
if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) {
xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE );
}
return xNeedPoll;
}
......@@ -409,15 +418,15 @@ void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
}
/* Set Modbus Master send PDU's buffer length.*/
void vMBMasterSetPDUSndLength( UCHAR SendPDULength )
void vMBMasterSetPDUSndLength( USHORT SendPDULength )
{
ucMasterSendPDULength = SendPDULength;
usMasterSendPDULength = SendPDULength;
}
/* Get Modbus Master send PDU's buffer length.*/
UCHAR ucMBMasterGetPDUSndLength( void )
USHORT usMBMasterGetPDUSndLength( void )
{
return ucMasterSendPDULength;
return usMasterSendPDULength;
}
/* Set Modbus Master current timer mode.*/
......@@ -425,5 +434,10 @@ void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
{
eMasterCurTimerMode = eMBTimerMode;
}
/* The master request is broadcast? */
BOOL xMBMasterRequestIsBroadcast( void ){
return xFrameIsBroadcast;
}
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册