From d8bbb5f1264c58c600d7f1fb1f1e95fbbfb94115 Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 17:36:11 +0800 Subject: [PATCH 1/5] [modbus]update modbus master and slave source code to lastest. --- .../modbus/functions/mbfunccoils_m.c | 73 +++++-- .../modbus/functions/mbfuncdisc_m.c | 28 ++- .../modbus/functions/mbfuncholding_m.c | 101 ++++++++-- .../modbus/functions/mbfuncinput_m.c | 28 ++- .../freemodbus-v1.6.0/modbus/include/mb_m.h | 180 ++++++++++++++++-- .../modbus/include/mbconfig.h | 6 +- .../freemodbus-v1.6.0/modbus/include/mbport.h | 50 ++++- .../net/freemodbus-v1.6.0/modbus/mb_m.c | 114 +++++++---- .../freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c | 36 ++-- 9 files changed, 492 insertions(+), 124 deletions(-) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c index 553f57b1b7..f6bb51cdf6 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c @@ -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. */ diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c index 187872c2a6..6c8d6c4741 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c @@ -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 ) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c index faefbbbb40..e1fe69e383 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c @@ -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 ) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c index e5f362bbec..2127efef67 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c @@ -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 ) { diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h b/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h index 9c4fa43e60..f6b25e2cf3 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h +++ b/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h @@ -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.
+ * 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.
+ * 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 Input Register + * is required by the protocol stack. The starting register address is given + * by \c usAddress and the last register is given by usAddress + + * usNRegs - 1. + * + * \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 + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Holding Register 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 + * usAddress + usNRegs - 1. + * + * \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 + * WRITE SINGLE REGISTER 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 + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Coil Register 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 pucRegBuffer. + * 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 + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Input Discrete Register 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 + * ILLEGAL DATA ADDRESS 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 -----------------------------------------*/ diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h b/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h index c5434de47e..89030b7abd 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h +++ b/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h @@ -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 diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h b/components/net/freemodbus-v1.6.0/modbus/include/mbport.h index a4c0a24dd4..11794a2929 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h +++ b/components/net/freemodbus-v1.6.0/modbus/include/mbport.h @@ -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 ------------------*/ /*! diff --git a/components/net/freemodbus-v1.6.0/modbus/mb_m.c b/components/net/freemodbus-v1.6.0/modbus/mb_m.c index 8f86f54182..4e7c4b2b74 100644 --- a/components/net/freemodbus-v1.6.0/modbus/mb_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/mb_m.c @@ -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 diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c b/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c index fffbb23f9f..987c9a3156 100644 --- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c +++ b/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c @@ -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 From 2a14e4071c6aaba74a345197623ea7ebec9e7806 Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 19:27:24 +0800 Subject: [PATCH 2/5] [modbus]port modbus master and slave by rtt device framework. --- components/net/freemodbus-v1.6.0/port/port.c | 15 +- components/net/freemodbus-v1.6.0/port/port.h | 14 +- .../net/freemodbus-v1.6.0/port/portevent.c | 38 +- .../net/freemodbus-v1.6.0/port/portevent_m.c | 208 ++++++++- .../net/freemodbus-v1.6.0/port/portserial.c | 277 +++++++----- .../net/freemodbus-v1.6.0/port/portserial_m.c | 275 +++++++----- .../net/freemodbus-v1.6.0/port/porttimer.c | 72 +-- .../net/freemodbus-v1.6.0/port/porttimer_m.c | 118 ++--- .../net/freemodbus-v1.6.0/port/user_mb_app.c | 425 ++++++++---------- .../net/freemodbus-v1.6.0/port/user_mb_app.h | 60 ++- .../freemodbus-v1.6.0/port/user_mb_app_m.c | 294 ++++++++++++ 11 files changed, 1087 insertions(+), 709 deletions(-) create mode 100644 components/net/freemodbus-v1.6.0/port/user_mb_app_m.c diff --git a/components/net/freemodbus-v1.6.0/port/port.c b/components/net/freemodbus-v1.6.0/port/port.c index 459481cc1d..527af909ac 100644 --- a/components/net/freemodbus-v1.6.0/port/port.c +++ b/components/net/freemodbus-v1.6.0/port/port.c @@ -1,6 +1,6 @@ /* - * FreeModbus Libary: LPC214X Port - * Copyright (C) 2007 Tiago Prado Lone + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * File: $Id: port.c,v 1.1 2007/04/24 23:15:18 wolti Exp $ + * File: $Id: portevent.c,v 1.60 2015/02/01 9:18:05 Armink $ */ /* ----------------------- System includes --------------------------------*/ @@ -24,16 +24,15 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "port.h" /* ----------------------- Variables ----------------------------------------*/ - +static rt_base_t level; /* ----------------------- Start implementation -----------------------------*/ void EnterCriticalSection(void) { - //关闭全局中断 - __disable_irq(); + level = rt_hw_interrupt_disable(); } void ExitCriticalSection(void) { - //开启全局中断 - __enable_irq(); + rt_hw_interrupt_enable(level); } + diff --git a/components/net/freemodbus-v1.6.0/port/port.h b/components/net/freemodbus-v1.6.0/port/port.h index c79df3d887..92056116b8 100644 --- a/components/net/freemodbus-v1.6.0/port/port.h +++ b/components/net/freemodbus-v1.6.0/port/port.h @@ -1,6 +1,6 @@ /* * FreeModbus Libary: BARE Port - * Copyright (C) 2006 Christian Walter + * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,18 +34,9 @@ #define PR_BEGIN_EXTERN_C extern "C" { #define PR_END_EXTERN_C } -//TODO 暂时先写B13引脚,等组网测试时再确认 -#define SLAVE_RS485_SEND_MODE GPIO_SetBits(GPIOB,GPIO_Pin_13) -#define SLAVE_RS485_RECEIVE_MODE GPIO_ResetBits(GPIOB,GPIO_Pin_13) -#define MASTER_RS485_SEND_MODE GPIO_SetBits(GPIOB,GPIO_Pin_13) -#define MASTER_RS485_RECEIVE_MODE GPIO_ResetBits(GPIOB,GPIO_Pin_13) - #define ENTER_CRITICAL_SECTION() EnterCriticalSection() #define EXIT_CRITICAL_SECTION() ExitCriticalSection() -void EnterCriticalSection(void); -void ExitCriticalSection(void); - typedef uint8_t BOOL; typedef unsigned char UCHAR; @@ -65,4 +56,7 @@ typedef int32_t LONG; #define FALSE 0 #endif +void EnterCriticalSection(void); +void ExitCriticalSection(void); + #endif diff --git a/components/net/freemodbus-v1.6.0/port/portevent.c b/components/net/freemodbus-v1.6.0/port/portevent.c index 86c7b5e7a5..1a881166be 100644 --- a/components/net/freemodbus-v1.6.0/port/portevent.c +++ b/components/net/freemodbus-v1.6.0/port/portevent.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -24,35 +24,45 @@ #include "mbport.h" /* ----------------------- Variables ----------------------------------------*/ -static eMBEventType eQueuedEvent; -static BOOL xEventInQueue; - +static struct rt_event xSlaveOsEvent; /* ----------------------- Start implementation -----------------------------*/ BOOL xMBPortEventInit( void ) { - xEventInQueue = FALSE; + rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO); return TRUE; } BOOL xMBPortEventPost( eMBEventType eEvent ) { - xEventInQueue = TRUE; - eQueuedEvent = eEvent; + rt_event_send(&xSlaveOsEvent, eEvent); return TRUE; } BOOL xMBPortEventGet( eMBEventType * eEvent ) { - BOOL xEventHappened = FALSE; - - if( xEventInQueue ) + rt_uint32_t recvedEvent; + /* waiting forever OS event */ + rt_event_recv(&xSlaveOsEvent, + EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + switch (recvedEvent) { - *eEvent = eQueuedEvent; - xEventInQueue = FALSE; - xEventHappened = TRUE; + case EV_READY: + *eEvent = EV_READY; + break; + case EV_FRAME_RECEIVED: + *eEvent = EV_FRAME_RECEIVED; + break; + case EV_EXECUTE: + *eEvent = EV_EXECUTE; + break; + case EV_FRAME_SENT: + *eEvent = EV_FRAME_SENT; + break; } - return xEventHappened; + return TRUE; } diff --git a/components/net/freemodbus-v1.6.0/port/portevent_m.c b/components/net/freemodbus-v1.6.0/port/portevent_m.c index c78b6cbcb2..031a3b84ef 100644 --- a/components/net/freemodbus-v1.6.0/port/portevent_m.c +++ b/components/net/freemodbus-v1.6.0/port/portevent_m.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -21,41 +21,219 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" +#include "mb_m.h" #include "mbport.h" +#include "port.h" -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +/* ----------------------- Defines ------------------------------------------*/ /* ----------------------- Variables ----------------------------------------*/ -static eMBMasterEventType eMasterQueuedEvent; -static BOOL xMasterEventInQueue; - +static struct rt_semaphore xMasterRunRes; +static struct rt_event xMasterOsEvent; /* ----------------------- Start implementation -----------------------------*/ BOOL xMBMasterPortEventInit( void ) { - xMasterEventInQueue = FALSE; + rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO); return TRUE; } BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent ) { - xMasterEventInQueue = TRUE; - eMasterQueuedEvent = eEvent; + rt_event_send(&xMasterOsEvent, eEvent); return TRUE; } BOOL xMBMasterPortEventGet( eMBMasterEventType * eEvent ) { - BOOL xEventHappened = FALSE; - - if( xMasterEventInQueue ) + rt_uint32_t recvedEvent; + /* waiting forever OS event */ + rt_event_recv(&xMasterOsEvent, + EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE | + EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + /* the enum type couldn't convert to int type */ + switch (recvedEvent) { - *eEvent = eMasterQueuedEvent; - xMasterEventInQueue = FALSE; - xEventHappened = TRUE; + case EV_MASTER_READY: + *eEvent = EV_MASTER_READY; + break; + case EV_MASTER_FRAME_RECEIVED: + *eEvent = EV_MASTER_FRAME_RECEIVED; + break; + case EV_MASTER_EXECUTE: + *eEvent = EV_MASTER_EXECUTE; + break; + case EV_MASTER_FRAME_SENT: + *eEvent = EV_MASTER_FRAME_SENT; + break; + case EV_MASTER_ERROR_PROCESS: + *eEvent = EV_MASTER_ERROR_PROCESS; + break; } - return xEventHappened; + return TRUE; +} +/** + * This function is initialize the OS resource for modbus master. + * Note:The resource is define by OS.If you not use OS this function can be empty. + * + */ +void vMBMasterOsResInit( void ) +{ + rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO); +} + +/** + * This function is take Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE. + * + * @param lTimeOut the waiting time. + * + * @return resource taked result + */ +BOOL xMBMasterRunResTake( LONG lTimeOut ) +{ + /*If waiting time is -1 .It will wait forever */ + return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ; +} + +/** + * This function is release Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be empty. + * + */ +void vMBMasterRunResRelease( void ) +{ + /* release resource */ + rt_sem_release(&xMasterRunRes); +} + +/** + * This is modbus master respond timeout error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master receive data error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master execute function error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master request process success callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + */ +void vMBMasterCBRequestScuuess( void ) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS); + + /* You can add your code under here. */ + +} + +/** + * This function is wait for modbus master request finish and return result. + * Waiting result include request process success, request respond timeout, + * receive data error and execute function error.You can use the above callback function. + * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run + * much user custom delay for waiting. + * + * @return request error code + */ +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + rt_uint32_t recvedEvent; + /* waiting for OS event */ + rt_event_recv(&xMasterOsEvent, + EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT + | EV_MASTER_ERROR_RECEIVE_DATA + | EV_MASTER_ERROR_EXECUTE_FUNCTION, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + switch (recvedEvent) + { + case EV_MASTER_PROCESS_SUCESS: + break; + case EV_MASTER_ERROR_RESPOND_TIMEOUT: + { + eErrStatus = MB_MRE_TIMEDOUT; + break; + } + case EV_MASTER_ERROR_RECEIVE_DATA: + { + eErrStatus = MB_MRE_REV_DATA; + break; + } + case EV_MASTER_ERROR_EXECUTE_FUNCTION: + { + eErrStatus = MB_MRE_EXE_FUN; + break; + } + } + return eErrStatus; } #endif diff --git a/components/net/freemodbus-v1.6.0/port/portserial.c b/components/net/freemodbus-v1.6.0/port/portserial.c index 3768702087..0ba8dfbaec 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial.c +++ b/components/net/freemodbus-v1.6.0/port/portserial.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -24,122 +24,148 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" +#include "rtdevice.h" +#include "bsp.h" + +/* ----------------------- Static variables ---------------------------------*/ +ALIGN(RT_ALIGN_SIZE) +/* software simulation serial transmit IRQ handler thread stack */ +static rt_uint8_t serial_soft_trans_irq_stack[512]; +/* software simulation serial transmit IRQ handler thread */ +static struct rt_thread thread_serial_soft_trans_irq; +/* serial event */ +static struct rt_event event_serial; +/* modbus slave serial device */ +static rt_serial_t *serial; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) + /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); +static void serial_soft_trans_irq(void* parameter); + /* ----------------------- Start implementation -----------------------------*/ +BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + /** + * set 485 mode receive and transmit control IO + * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user + */ + rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); + + /* set serial name */ + if (ucPORT == 1) { +#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1) + extern struct rt_serial_device serial1; + serial = &serial1; +#endif + } else if (ucPORT == 2) { +#if defined(RT_USING_UART2) + extern struct rt_serial_device serial2; + serial = &serial2; +#endif + } else if (ucPORT == 3) { +#if defined(RT_USING_UART3) + extern struct rt_serial_device serial3; + serial = &serial3; +#endif + } + /* set serial configure parameter */ + serial->config.baud_rate = ulBaudRate; + serial->config.stop_bits = STOP_BITS_1; + switch(eParity){ + case MB_PAR_NONE: { + serial->config.data_bits = DATA_BITS_8; + serial->config.parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_EVEN; + break; + } + } + /* set serial configure */ + serial->ops->configure(serial, &(serial->config)); + + /* open serial device */ + if (!serial->parent.open(&serial->parent, + RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) { + serial->parent.rx_indicate = serial_rx_ind; + } else { + return FALSE; + } + + /* software initialize */ + rt_thread_init(&thread_serial_soft_trans_irq, + "slave trans", + serial_soft_trans_irq, + RT_NULL, + serial_soft_trans_irq_stack, + sizeof(serial_soft_trans_irq_stack), + 10, 5); + rt_thread_startup(&thread_serial_soft_trans_irq); + rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); + + return TRUE; +} void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { - if (xRxEnable) - { - SLAVE_RS485_RECEIVE_MODE; - USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); - } - else - { - SLAVE_RS485_SEND_MODE; - USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); - } - if (xTxEnable) - { - USART_ITConfig(USART1, USART_IT_TXE, ENABLE); - } - else - { - USART_ITConfig(USART1, USART_IT_TXE, DISABLE); - } + rt_uint32_t recved_event; + if (xRxEnable) + { + /* enable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + /* switch 485 to receive mode */ + rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW); + } + else + { + /* switch 485 to transmit mode */ + rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH); + /* disable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); + } + if (xTxEnable) + { + /* start serial transmit */ + rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); + } + else + { + /* stop serial transmit */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, + &recved_event); + } } void vMBPortClose(void) { - USART_ITConfig(USART1, USART_IT_TXE | USART_IT_RXNE, DISABLE); - USART_Cmd(USART1, DISABLE); -} -//默认一个从机 串口1 波特率可设置 奇偶检验可设置 -BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, - eMBParity eParity) -{ - GPIO_InitTypeDef GPIO_InitStructure; - USART_InitTypeDef USART_InitStructure; - NVIC_InitTypeDef NVIC_InitStructure; - //======================时钟初始化======================================= - RCC_APB2PeriphClockCmd( - RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1, - ENABLE); - //======================IO初始化======================================= - //USART1_TX - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //USART1_RX - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //配置485发送和接收模式 -// TODO 暂时先写B13 等之后组网测试时再修改 - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; - GPIO_Init(GPIOB, &GPIO_InitStructure); - //======================串口初始化======================================= - USART_InitStructure.USART_BaudRate = ulBaudRate; - //设置校验模式 - switch (eParity) - { - case MB_PAR_NONE: //无校验 - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - break; - case MB_PAR_ODD: //奇校验 - USART_InitStructure.USART_Parity = USART_Parity_Odd; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - case MB_PAR_EVEN: //偶校验 - USART_InitStructure.USART_Parity = USART_Parity_Even; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - default: - return FALSE; - } - - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_HardwareFlowControl = - USART_HardwareFlowControl_None; - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - if (ucPORT != 1) - return FALSE; - - ENTER_CRITICAL_SECTION(); //关全局中断 - - USART_Init(USART1, &USART_InitStructure); - USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); - USART_Cmd(USART1, ENABLE); - - //=====================中断初始化====================================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - - EXIT_CRITICAL_SECTION(); //开全局中断 - - return TRUE; + serial->parent.close(&(serial->parent)); } BOOL xMBPortSerialPutByte(CHAR ucByte) { - USART_SendData(USART1, ucByte); - return TRUE; + serial->parent.write(&(serial->parent), 0, &ucByte, 1); + return TRUE; } BOOL xMBPortSerialGetByte(CHAR * pucByte) { - *pucByte = USART_ReceiveData(USART1); - return TRUE; + serial->parent.read(&(serial->parent), 0, pucByte, 1); + return TRUE; } /* @@ -151,7 +177,7 @@ BOOL xMBPortSerialGetByte(CHAR * pucByte) */ void prvvUARTTxReadyISR(void) { - pxMBFrameCBTransmitterEmpty(); + pxMBFrameCBTransmitterEmpty(); } /* @@ -162,28 +188,35 @@ void prvvUARTTxReadyISR(void) */ void prvvUARTRxISR(void) { - pxMBFrameCBByteReceived(); + pxMBFrameCBByteReceived(); } -/******************************************************************************* - * Function Name : USART1_IRQHandler - * Description : This function handles USART1 global interrupt request. - * Input : None - * Output : None - * Return : None - *******************************************************************************/ -void USART1_IRQHandler(void) -{ - rt_interrupt_enter(); - //接收中断 - if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) - { - USART_ClearITPendingBit(USART1, USART_IT_RXNE); - prvvUARTRxISR(); - } - //发送中断 - if (USART_GetITStatus(USART1, USART_IT_TXE) == SET) - { - prvvUARTTxReadyISR(); - } - rt_interrupt_leave(); + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void serial_soft_trans_irq(void* parameter) { + rt_uint32_t recved_event; + while (1) + { + /* waiting for serial transmit start */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &recved_event); + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } +} + +/** + * This function is serial receive callback function + * + * @param dev the device of serial + * @param size the data size that receive + * + * @return return RT_EOK + */ +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { + prvvUARTRxISR(); + return RT_EOK; } diff --git a/components/net/freemodbus-v1.6.0/port/portserial_m.c b/components/net/freemodbus-v1.6.0/port/portserial_m.c index ca76a81963..4dc02d92bd 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial_m.c +++ b/components/net/freemodbus-v1.6.0/port/portserial_m.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -24,123 +24,149 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" +#include "rtdevice.h" +#include "bsp.h" + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +/* ----------------------- Static variables ---------------------------------*/ +ALIGN(RT_ALIGN_SIZE) +/* software simulation serial transmit IRQ handler thread stack */ +static rt_uint8_t serial_soft_trans_irq_stack[512]; +/* software simulation serial transmit IRQ handler thread */ +static struct rt_thread thread_serial_soft_trans_irq; +/* serial event */ +static struct rt_event event_serial; +/* modbus slave serial device */ +static rt_serial_t *serial; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); +static void serial_soft_trans_irq(void* parameter); + /* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + /** + * set 485 mode receive and transmit control IO + * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user + */ + rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); + + /* set serial name */ + if (ucPORT == 1) { +#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1) + extern struct rt_serial_device serial1; + serial = &serial1; +#endif + } else if (ucPORT == 2) { +#if defined(RT_USING_UART2) + extern struct rt_serial_device serial2; + serial = &serial2; +#endif + } else if (ucPORT == 3) { +#if defined(RT_USING_UART3) + extern struct rt_serial_device serial3; + serial = &serial3; +#endif + } + /* set serial configure parameter */ + serial->config.baud_rate = ulBaudRate; + serial->config.stop_bits = STOP_BITS_1; + switch(eParity){ + case MB_PAR_NONE: { + serial->config.data_bits = DATA_BITS_8; + serial->config.parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_EVEN; + break; + } + } + /* set serial configure */ + serial->ops->configure(serial, &(serial->config)); + + /* open serial device */ + if (!serial->parent.open(&serial->parent, + RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) { + serial->parent.rx_indicate = serial_rx_ind; + } else { + return FALSE; + } + + /* software initialize */ + rt_thread_init(&thread_serial_soft_trans_irq, + "slave trans", + serial_soft_trans_irq, + RT_NULL, + serial_soft_trans_irq_stack, + sizeof(serial_soft_trans_irq_stack), + 10, 5); + rt_thread_startup(&thread_serial_soft_trans_irq); + rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); + + return TRUE; +} void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { - if (xRxEnable) - { - MASTER_RS485_RECEIVE_MODE; - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); - } - else - { - MASTER_RS485_SEND_MODE; - USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); - } - if (xTxEnable) - { - USART_ITConfig(USART2, USART_IT_TXE, ENABLE); - } - else - { - USART_ITConfig(USART2, USART_IT_TXE, DISABLE); - } + rt_uint32_t recved_event; + if (xRxEnable) + { + /* enable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + /* switch 485 to receive mode */ + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); + } + else + { + /* switch 485 to transmit mode */ + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); + /* disable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); + } + if (xTxEnable) + { + /* start serial transmit */ + rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); + } + else + { + /* stop serial transmit */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, + &recved_event); + } } void vMBMasterPortClose(void) { - USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE); - USART_Cmd(USART2, DISABLE); -} -//默认一个主机 串口2 波特率可设置 奇偶检验可设置 -BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, - eMBParity eParity) -{ - GPIO_InitTypeDef GPIO_InitStructure; - USART_InitTypeDef USART_InitStructure; - NVIC_InitTypeDef NVIC_InitStructure; - //======================时钟初始化======================================= - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); - //======================IO初始化======================================= - //USART2_TX - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //USART2_RX - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //配置485发送和接收模式 -// TODO 暂时先写B13 等之后组网测试时再修改 - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; - GPIO_Init(GPIOB, &GPIO_InitStructure); - //======================串口初始化======================================= - USART_InitStructure.USART_BaudRate = ulBaudRate; - //设置校验模式 - switch (eParity) - { - case MB_PAR_NONE: //无校验 - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - break; - case MB_PAR_ODD: //奇校验 - USART_InitStructure.USART_Parity = USART_Parity_Odd; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - case MB_PAR_EVEN: //偶校验 - USART_InitStructure.USART_Parity = USART_Parity_Even; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - default: - return FALSE; - } - - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_HardwareFlowControl = - USART_HardwareFlowControl_None; - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - if (ucPORT != 2) - return FALSE; - - ENTER_CRITICAL_SECTION(); //关全局中断 - - USART_Init(USART2, &USART_InitStructure); - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); - USART_Cmd(USART2, ENABLE); - - //=====================中断初始化====================================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - - EXIT_CRITICAL_SECTION(); //开全局中断 - - return TRUE; + serial->parent.close(&(serial->parent)); } BOOL xMBMasterPortSerialPutByte(CHAR ucByte) { - USART_SendData(USART2, ucByte); + serial->parent.write(&(serial->parent), 0, &ucByte, 1); return TRUE; } BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) { - *pucByte = USART_ReceiveData(USART2); - return TRUE; + serial->parent.read(&(serial->parent), 0, pucByte, 1); + return TRUE; } /* @@ -152,7 +178,7 @@ BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) */ void prvvUARTTxReadyISR(void) { - pxMBMasterFrameCBTransmitterEmpty(); + pxMBMasterFrameCBTransmitterEmpty(); } /* @@ -163,30 +189,37 @@ void prvvUARTTxReadyISR(void) */ void prvvUARTRxISR(void) { - pxMBMasterFrameCBByteReceived(); + pxMBMasterFrameCBByteReceived(); } -/******************************************************************************* - * Function Name : USART2_IRQHandler - * Description : This function handles USART2 global interrupt request. - * Input : None - * Output : None - * Return : None - *******************************************************************************/ -void USART2_IRQHandler(void) -{ - rt_interrupt_enter(); - //接收中断 - if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) - { - USART_ClearITPendingBit(USART2, USART_IT_RXNE); - prvvUARTRxISR(); - } - //发送中断 - if (USART_GetITStatus(USART2, USART_IT_TXE) == SET) - { - prvvUARTTxReadyISR(); - } - rt_interrupt_leave(); + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void serial_soft_trans_irq(void* parameter) { + rt_uint32_t recved_event; + while (1) + { + /* waiting for serial transmit start */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &recved_event); + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } +} + +/** + * This function is serial receive callback function + * + * @param dev the device of serial + * @param size the data size that receive + * + * @return return RT_EOK + */ +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { + prvvUARTRxISR(); + return RT_EOK; } #endif diff --git a/components/net/freemodbus-v1.6.0/port/porttimer.c b/components/net/freemodbus-v1.6.0/port/porttimer.c index b7b74ce078..6f017d8759 100644 --- a/components/net/freemodbus-v1.6.0/port/porttimer.c +++ b/components/net/freemodbus-v1.6.0/port/porttimer.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -27,81 +27,37 @@ #include "mbport.h" /* ----------------------- static functions ---------------------------------*/ +static struct rt_timer timer; static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(void* parameter); /* ----------------------- Start implementation -----------------------------*/ BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) { - - uint16_t PrescalerValue = 0; - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - NVIC_InitTypeDef NVIC_InitStructure; - //====================================时钟初始化=========================== - //使能定时器3时钟 - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); - //====================================定时器初始化=========================== - //定时器时间基配置说明 - //HCLK为72MHz,APB1经过2分频为36MHz - //TIM3的时钟倍频后为72MHz(硬件自动倍频,达到最大) - //TIM3的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us - //TIM最大计数值为usTim1Timerout50u - - PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1; - //定时器1初始化 - TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTim1Timerout50us; - TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); - //预装载使能 - TIM_ARRPreloadConfig(TIM3, ENABLE); - //====================================中断初始化=========================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - //清除溢出中断标志位 - TIM_ClearITPendingBit(TIM3, TIM_IT_Update); - //定时器3溢出中断关闭 - TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE); - //定时器3禁能 - TIM_Cmd(TIM3, DISABLE); - return TRUE; + rt_timer_init(&timer, "slave timer", + timer_timeout_ind, /* bind timeout callback function */ + RT_NULL, + (50*usTim1Timerout50us)/(1000*1000/RT_TICK_PER_SECOND), + RT_TIMER_FLAG_ONE_SHOT); /* one shot */ + return TRUE; } void vMBPortTimersEnable() { - TIM_ClearITPendingBit(TIM3, TIM_IT_Update); - TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM3, 0); - TIM_Cmd(TIM3, ENABLE); + rt_timer_start(&timer); } void vMBPortTimersDisable() { - TIM_ClearITPendingBit(TIM3, TIM_IT_Update); - TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE); - TIM_SetCounter(TIM3, 0); - TIM_Cmd(TIM3, DISABLE); + rt_timer_stop(&timer); } void prvvTIMERExpiredISR(void) { - (void) pxMBPortCBTimerExpired(); + (void) pxMBPortCBTimerExpired(); } -void TIM3_IRQHandler(void) +static void timer_timeout_ind(void* parameter) { - rt_interrupt_enter(); - if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) - { - - TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清中断标记 - TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除定时器T3溢出中断标志位 - prvvTIMERExpiredISR(); - } - rt_interrupt_leave(); + prvvTIMERExpiredISR(); } diff --git a/components/net/freemodbus-v1.6.0/port/porttimer_m.c b/components/net/freemodbus-v1.6.0/port/porttimer_m.c index 1881b47053..69bdc54879 100644 --- a/components/net/freemodbus-v1.6.0/port/porttimer_m.c +++ b/components/net/freemodbus-v1.6.0/port/porttimer_m.c @@ -1,5 +1,5 @@ /* - * FreeModbus Libary: STM32 Port + * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or @@ -27,10 +27,12 @@ #include "mb_m.h" #include "mbport.h" -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Variables ----------------------------------------*/ static USHORT usT35TimeOut50us; -static USHORT usPrescalerValue = 0; +static struct rt_timer timer; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(void* parameter); /* ----------------------- static functions ---------------------------------*/ static void prvvTIMERExpiredISR(void); @@ -38,120 +40,68 @@ static void prvvTIMERExpiredISR(void); /* ----------------------- Start implementation -----------------------------*/ BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) { - NVIC_InitTypeDef NVIC_InitStructure; - //====================================时钟初始化=========================== - //使能定时器2时钟 - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - //====================================定时器初始化=========================== - //定时器时间基配置说明 - //HCLK为72MHz,APB1经过2分频为36MHz - //TIM2的时钟倍频后为72MHz(硬件自动倍频,达到最大) - //TIM2的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us - //TIM最大计数值为usTim1Timerout50u - usPrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1; - //保存T35定时器计数值 - usT35TimeOut50us = usTimeOut50us; + /* backup T35 ticks */ + usT35TimeOut50us = usTimeOut50us; - //预装载使能 - TIM_ARRPreloadConfig(TIM2, ENABLE); - //====================================中断初始化=========================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - //清除溢出中断标志位 - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - //定时器3溢出中断关闭 - TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); - //定时器3禁能 - TIM_Cmd(TIM2, DISABLE); - return TRUE; + rt_timer_init(&timer, "master timer", + timer_timeout_ind, /* bind timeout callback function */ + RT_NULL, + (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND), + RT_TIMER_FLAG_ONE_SHOT); /* one shot */ + + return TRUE; } void vMBMasterPortTimersT35Enable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = (50 * usT35TimeOut50us) + / (1000 * 1000 / RT_TICK_PER_SECOND); - /* Set current timer mode,don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_T35); + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_T35); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us; - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersConvertDelayEnable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; - /* Set current timer mode,don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_DELAY_MS_CONVERT * 1000 / 50); - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersRespondTimeoutEnable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; - /* Set current timer mode,don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / 50); - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersDisable() { - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, DISABLE); + rt_timer_stop(&timer); } void prvvTIMERExpiredISR(void) { - (void) pxMBMasterPortCBTimerExpired(); + (void) pxMBMasterPortCBTimerExpired(); } -void TIM2_IRQHandler(void) +static void timer_timeout_ind(void* parameter) { - rt_interrupt_enter(); - if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) - { - - TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清中断标记 - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除定时器TIM2溢出中断标志位 - prvvTIMERExpiredISR(); - } - rt_interrupt_leave(); + prvvTIMERExpiredISR(); } #endif diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.c b/components/net/freemodbus-v1.6.0/port/user_mb_app.c index a99615c235..e6fdede11f 100644 --- a/components/net/freemodbus-v1.6.0/port/user_mb_app.c +++ b/components/net/freemodbus-v1.6.0/port/user_mb_app.c @@ -1,4 +1,25 @@ +/* + * FreeModbus Libary: user callback functions and buffer define in slave mode + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $ + */ #include "user_mb_app.h" + /*------------------------Slave mode use these variables----------------------*/ //Slave mode:DiscreteInputs variables USHORT usSDiscInStart = S_DISCRETE_INPUT_START; @@ -20,81 +41,41 @@ USHORT usSRegInBuf[S_REG_INPUT_NREGS] ; //Slave mode:HoldingRegister variables USHORT usSRegHoldStart = S_REG_HOLDING_START; USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ; -/*-----------------------Master mode use these variables----------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -//Master mode:DiscreteInputs variables -USHORT usMDiscInStart = M_DISCRETE_INPUT_START; -#if M_DISCRETE_INPUT_NDISCRETES%8 -UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1]; -#else -UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8]; -#endif -//Master mode:Coils variables -USHORT usMCoilStart = M_COIL_START; -#if M_COIL_NCOILS%8 -UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1]; -#else -UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8]; -#endif -//Master mode:InputRegister variables -USHORT usMRegInStart = M_REG_INPUT_START; -USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS]; -//Master mode:HoldingRegister variables -USHORT usMRegHoldStart = M_REG_HOLDING_START; -USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; -#endif -//******************************输入寄存器回调函数********************************** -//函数定义: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) -//描 述:输入寄存器相关的功能(读、连续读) -//入口参数:pucRegBuffer : 回调函数将Modbus寄存器的当前值写入的缓冲区 -// usAddress : 寄存器的起始地址,输入寄存器的地址范围是1-65535。 -// usNRegs : 寄存器数量 -//出口参数:eMBErrorCode : 这个函数将返回的错误码 -//备 注:Editor:Armink 2010-10-31 Company: BXXJS -//********************************************************************************** -eMBErrorCode -eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) + +/** + * Modbus slave input register callback function. + * + * @param pucRegBuffer input register buffer + * @param usAddress input register address + * @param usNRegs input register number + * + * @return result + */ +eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) { eMBErrorCode eStatus = MB_ENOERR; - int iRegIndex; + USHORT iRegIndex; USHORT * pusRegInputBuf; - UCHAR REG_INPUT_START; - UCHAR REG_INPUT_NREGS; - UCHAR usRegInStart; + USHORT REG_INPUT_START; + USHORT REG_INPUT_NREGS; + USHORT usRegInStart; - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()]; - REG_INPUT_START = M_REG_INPUT_START; - REG_INPUT_NREGS = M_REG_INPUT_NREGS; - usRegInStart = usMRegInStart; - } - else - { - pusRegInputBuf = usSRegInBuf; - REG_INPUT_START = S_REG_INPUT_START; - REG_INPUT_NREGS = S_REG_INPUT_NREGS; - usRegInStart = usSRegInStart; - } + pusRegInputBuf = usSRegInBuf; + REG_INPUT_START = S_REG_INPUT_START; + REG_INPUT_NREGS = S_REG_INPUT_NREGS; + usRegInStart = usSRegInStart; - if( ( usAddress >= REG_INPUT_START ) - && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ) + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_INPUT_START) + && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) { - iRegIndex = ( int )( usAddress - usRegInStart ); - while( usNRegs > 0 ) + iRegIndex = usAddress - usRegInStart; + while (usNRegs > 0) { - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; - pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; - } - else - { - *pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] >> 8 ); - *pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF ); - } + *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF); iRegIndex++; usNRegs--; } @@ -106,67 +87,55 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) return eStatus; } -//******************************保持寄存器回调函数********************************** -//函数定义: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) -//描 述:保持寄存器相关的功能(读、连续读、写、连续写) -//入口参数:pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。 -// 如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区 -// usAddress : 寄存器的起始地址。 -// usNRegs : 寄存器数量 -// eMode : 如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。 -// 如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中 -//出口参数:eMBErrorCode : 这个函数将返回的错误码 -//备 注:Editor:Armink 2010-10-31 Company: BXXJS -//********************************************************************************** -eMBErrorCode -eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) + +/** + * Modbus slave holding register callback function. + * + * @param pucRegBuffer holding register buffer + * @param usAddress holding register address + * @param usNRegs holding register number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) { eMBErrorCode eStatus = MB_ENOERR; - int iRegIndex; + USHORT iRegIndex; USHORT * pusRegHoldingBuf; - UCHAR REG_HOLDING_START; - UCHAR REG_HOLDING_NREGS; - UCHAR usRegHoldStart; + USHORT REG_HOLDING_START; + USHORT REG_HOLDING_NREGS; + USHORT usRegHoldStart; - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()]; - REG_HOLDING_START = M_REG_HOLDING_START; - REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; - usRegHoldStart = usMRegHoldStart; - //If mode is read,the master will wirte the received date to bufffer. - eMode = MB_REG_WRITE; - } - else - { - pusRegHoldingBuf = usSRegHoldBuf; - REG_HOLDING_START = S_REG_HOLDING_START; - REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; - usRegHoldStart = usSRegHoldStart; - } + pusRegHoldingBuf = usSRegHoldBuf; + REG_HOLDING_START = S_REG_HOLDING_START; + REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; + usRegHoldStart = usSRegHoldStart; - if( ( usAddress >= REG_HOLDING_START ) && - ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) ) + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_HOLDING_START) + && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) { - iRegIndex = ( int )( usAddress - usRegHoldStart ); - switch ( eMode ) + iRegIndex = usAddress - usRegHoldStart; + switch (eMode) { - /* Pass current register values to the protocol stack. */ + /* read current register values from the protocol stack. */ case MB_REG_READ: - while( usNRegs > 0 ) + while (usNRegs > 0) { - *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 ); - *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF ); + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); iRegIndex++; usNRegs--; } break; - /* Update current register values with new values from the - * protocol stack. */ + /* write current register values with new values from the protocol stack. */ case MB_REG_WRITE: - while( usNRegs > 0 ) + while (usNRegs > 0) { pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; @@ -182,83 +151,76 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi } return eStatus; } -//****************************线圈状态寄存器回调函数******************************** -//函数定义: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode ) -//描 述:线圈状态寄存器相关的功能(读、连续读、写、连续写) -//入口参数:pucRegBuffer : 位组成一个字节,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。 -// 如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置位0。 -// usAddress : 第一个线圈地址。 -// usNCoils : 请求的线圈个数 -// eMode ;如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。 -// 如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中 -//出口参数:eMBErrorCode : 这个函数将返回的错误码 -//备 注:Editor:Armink 2010-10-31 Company: BXXJS -//********************************************************************************** -eMBErrorCode -eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode ) + +/** + * Modbus slave coils callback function. + * + * @param pucRegBuffer coils buffer + * @param usAddress coils address + * @param usNCoils coils number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) { eMBErrorCode eStatus = MB_ENOERR; - int iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucCoilBuf; - UCHAR COIL_START; - UCHAR COIL_NCOILS; - UCHAR usCoilStart; - iNReg = usNCoils / 8 + 1; //占用寄存器数量 + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucCoilBuf; + USHORT COIL_START; + USHORT COIL_NCOILS; + USHORT usCoilStart; + iNReg = usNCoils / 8 + 1; + pucCoilBuf = ucSCoilBuf; + COIL_START = S_COIL_START; + COIL_NCOILS = S_COIL_NCOILS; + usCoilStart = usSCoilStart; - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress()]; - COIL_START = M_COIL_START; - COIL_NCOILS = M_COIL_NCOILS; - usCoilStart = usMCoilStart; - //If mode is read,the master will wirte the received date to bufffer. - eMode = MB_REG_WRITE; - } - else - { - pucCoilBuf = ucSCoilBuf; - COIL_START = S_COIL_START; - COIL_NCOILS = S_COIL_NCOILS; - usCoilStart = usSCoilStart; - } + /* it already plus one in modbus function method. */ + usAddress--; if( ( usAddress >= COIL_START ) && ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) ) { - iRegIndex = ( int )( usAddress - usCoilStart ) / 8 ; //每个寄存器存8个 - iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ; //相对于寄存器内部的位地址 + iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; switch ( eMode ) { - /* Pass current coil values to the protocol stack. */ + /* read current coil values from the protocol stack. */ case MB_REG_READ: - while( iNReg > 0 ) + while (iNReg > 0) { - *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8); - iNReg --; - } - pucRegBuffer --; - usNCoils = usNCoils % 8; //余下的线圈数 - *pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //高位补零 - *pucRegBuffer = *pucRegBuffer >>(8 - usNCoils); - break; - - /* Update current coil values with new values from the - * protocol stack. */ - case MB_REG_WRITE: - while(iNReg > 1) //最后面余下来的数单独算 - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++); + *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], + iRegBitIndex, 8); iNReg--; } - usNCoils = usNCoils % 8; //余下的线圈数 - if (usNCoils != 0) //xMBUtilSetBits方法 在操作位数量为0时存在bug - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, - *pucRegBuffer++); - } - break; + pucRegBuffer--; + /* last coils */ + usNCoils = usNCoils % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); + *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); + break; + + /* write current coil values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (iNReg > 1) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last coils */ + usNCoils = usNCoils % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNCoils != 0) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, + *pucRegBuffer++); + } + break; } } else @@ -267,78 +229,52 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis } return eStatus; } -//****************************离散输入寄存器回调函数******************************** -//函数定义: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) -//描 述:离散输入寄存器相关的功能(读、连续读) -//入口参数:pucRegBuffer : 用当前的线圈数据更新这个寄存器,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。 -// 如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置为0。 -// usAddress : 离散输入的起始地址 -// usNDiscrete : 离散输入点数量 -//出口参数:eMBErrorCode : 这个函数将返回的错误码 -//备 注:Editor:Armink 2010-10-31 Company: BXXJS -//********************************************************************************** -eMBErrorCode -eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) + +/** + * Modbus slave discrete callback function. + * + * @param pucRegBuffer discrete buffer + * @param usAddress discrete address + * @param usNDiscrete discrete number + * + * @return result + */ +eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) { eMBErrorCode eStatus = MB_ENOERR; - int iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucDiscreteInputBuf; - UCHAR DISCRETE_INPUT_START; - UCHAR DISCRETE_INPUT_NDISCRETES; - UCHAR usDiscreteInputStart; - iNReg = usNDiscrete / 8 + 1; //占用寄存器数量 + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucDiscreteInputBuf; + USHORT DISCRETE_INPUT_START; + USHORT DISCRETE_INPUT_NDISCRETES; + USHORT usDiscreteInputStart; + iNReg = usNDiscrete / 8 + 1; - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()]; - DISCRETE_INPUT_START = M_DISCRETE_INPUT_START; - DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES; - usDiscreteInputStart = usMDiscInStart; - } - else - { - pucDiscreteInputBuf = ucSDiscInBuf; - DISCRETE_INPUT_START = S_DISCRETE_INPUT_START; - DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES; - usDiscreteInputStart = usSDiscInStart; - } + pucDiscreteInputBuf = ucSDiscInBuf; + DISCRETE_INPUT_START = S_DISCRETE_INPUT_START; + DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES; + usDiscreteInputStart = usSDiscInStart; - if( ( usAddress >= DISCRETE_INPUT_START ) - && ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) ) - { - iRegIndex = ( int )( usAddress - usDiscreteInputStart ) / 8 ; //每个寄存器存8个 - iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ; //相对于寄存器内部的位地址 + /* it already plus one in modbus function method. */ + usAddress--; - //Determine the master or slave - if (xMBMasterGetCBRunInMasterMode()) - { - /* Update current coil values with new values from the - * protocol stack. */ - while(iNReg > 1) //最后面余下来的数单独算 - { - xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++); - iNReg--; - } - usNDiscrete = usNDiscrete % 8; //余下的线圈数 - if (usNDiscrete != 0) //xMBUtilSetBits方法 在操作位数量为0时存在bug - { - xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, - usNDiscrete, *pucRegBuffer++); - } - } - else - { - while( iNReg > 0 ) - { - *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8); - iNReg --; - } - pucRegBuffer --; - usNDiscrete = usNDiscrete % 8; //余下的线圈数 - *pucRegBuffer = *pucRegBuffer <<(8 - usNDiscrete); //高位补零 - *pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete); - } + if ((usAddress >= DISCRETE_INPUT_START) + && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) + { + iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; //每个寄存器存8个 + iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; //相对于寄存器内部的位地址 + + while (iNReg > 0) + { + *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++], + iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + /* last discrete */ + usNDiscrete = usNDiscrete % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete); + *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete); } else { @@ -347,3 +283,4 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) return eStatus; } + diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.h b/components/net/freemodbus-v1.6.0/port/user_mb_app.h index 440ca82135..846b9a3a48 100644 --- a/components/net/freemodbus-v1.6.0/port/user_mb_app.h +++ b/components/net/freemodbus-v1.6.0/port/user_mb_app.h @@ -1,4 +1,4 @@ -#ifndef USER_APP +#ifndef USER_APP #define USER_APP /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" @@ -8,47 +8,41 @@ #include "mbutils.h" /* -----------------------Slave Defines -------------------------------------*/ -#define S_DISCRETE_INPUT_START 1 +#define S_DISCRETE_INPUT_START 0 #define S_DISCRETE_INPUT_NDISCRETES 16 -#define S_COIL_START 1 +#define S_COIL_START 0 #define S_COIL_NCOILS 64 -#define S_REG_INPUT_START 1 +#define S_REG_INPUT_START 0 #define S_REG_INPUT_NREGS 100 -#define S_REG_HOLDING_START 1 +#define S_REG_HOLDING_START 0 #define S_REG_HOLDING_NREGS 100 -//从机模式:在保持寄存器中,各个地址对应的功能定义 -#define S_HD_RESERVE 0 //保留 -#define S_HD_CPU_USAGE_MAJOR 1 //当前CPU利用率的整数位 -#define S_HD_CPU_USAGE_MINOR 2 //当前CPU利用率的小数位 - -//从机模式:在输入寄存器中,各个地址对应的功能定义 -#define S_IN_RESERVE 0 //保留 - -//从机模式:在线圈中,各个地址对应的功能定义 -#define S_CO_RESERVE 2 //保留 - -//从机模式:在离散输入中,各个地址对应的功能定义 -#define S_DI_RESERVE 1 //保留 +/* salve mode: holding register's all address */ +#define S_HD_RESERVE 0 +#define S_HD_CPU_USAGE_MAJOR 1 +#define S_HD_CPU_USAGE_MINOR 2 +/* salve mode: input register's all address */ +#define S_IN_RESERVE 0 +/* salve mode: coil's all address */ +#define S_CO_RESERVE 0 +/* salve mode: discrete's all address */ +#define S_DI_RESERVE 0 /* -----------------------Master Defines -------------------------------------*/ -#define M_DISCRETE_INPUT_START 1 +#define M_DISCRETE_INPUT_START 0 #define M_DISCRETE_INPUT_NDISCRETES 16 -#define M_COIL_START 1 +#define M_COIL_START 0 #define M_COIL_NCOILS 64 -#define M_REG_INPUT_START 1 +#define M_REG_INPUT_START 0 #define M_REG_INPUT_NREGS 100 -#define M_REG_HOLDING_START 1 +#define M_REG_HOLDING_START 0 #define M_REG_HOLDING_NREGS 100 -//主机模式:在保持寄存器中,各个地址对应的功能定义 -#define M_HD_RESERVE 0 //保留 - -//主机模式:在输入寄存器中,各个地址对应的功能定义 -#define M_IN_RESERVE 0 //保留 - -//主机模式:在线圈中,各个地址对应的功能定义 -#define M_CO_RESERVE 2 //保留 - -//主机模式:在离散输入中,各个地址对应的功能定义 -#define M_DI_RESERVE 1 //保留 +/* master mode: holding register's all address */ +#define M_HD_RESERVE 0 +/* master mode: input register's all address */ +#define M_IN_RESERVE 0 +/* master mode: coil's all address */ +#define M_CO_RESERVE 0 +/* master mode: discrete's all address */ +#define M_DI_RESERVE 0 #endif diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app_m.c b/components/net/freemodbus-v1.6.0/port/user_mb_app_m.c new file mode 100644 index 0000000000..12fabf21ac --- /dev/null +++ b/components/net/freemodbus-v1.6.0/port/user_mb_app_m.c @@ -0,0 +1,294 @@ +/* + * FreeModbus Libary: user callback functions and buffer define in master mode + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $ + */ +#include "user_mb_app.h" + +/*-----------------------Master mode use these variables----------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +//Master mode:DiscreteInputs variables +USHORT usMDiscInStart = M_DISCRETE_INPUT_START; +#if M_DISCRETE_INPUT_NDISCRETES%8 +UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1]; +#else +UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8]; +#endif +//Master mode:Coils variables +USHORT usMCoilStart = M_COIL_START; +#if M_COIL_NCOILS%8 +UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1]; +#else +UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8]; +#endif +//Master mode:InputRegister variables +USHORT usMRegInStart = M_REG_INPUT_START; +USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS]; +//Master mode:HoldingRegister variables +USHORT usMRegHoldStart = M_REG_HOLDING_START; +USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; + +/** + * Modbus master input register callback function. + * + * @param pucRegBuffer input register buffer + * @param usAddress input register address + * @param usNRegs input register number + * + * @return result + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegInputBuf; + USHORT REG_INPUT_START; + USHORT REG_INPUT_NREGS; + USHORT usRegInStart; + + pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1]; + REG_INPUT_START = M_REG_INPUT_START; + REG_INPUT_NREGS = M_REG_INPUT_NREGS; + usRegInStart = usMRegInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_INPUT_START) + && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) + { + iRegIndex = usAddress - usRegInStart; + while (usNRegs > 0) + { + pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; + pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; + iRegIndex++; + usNRegs--; + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} + +/** + * Modbus master holding register callback function. + * + * @param pucRegBuffer holding register buffer + * @param usAddress holding register address + * @param usNRegs holding register number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegHoldingBuf; + USHORT REG_HOLDING_START; + USHORT REG_HOLDING_NREGS; + USHORT usRegHoldStart; + + pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1]; + REG_HOLDING_START = M_REG_HOLDING_START; + REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; + usRegHoldStart = usMRegHoldStart; + /* if mode is read, the master will write the received date to buffer. */ + eMode = MB_REG_WRITE; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_HOLDING_START) + && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) + { + iRegIndex = usAddress - usRegHoldStart; + switch (eMode) + { + /* read current register values from the protocol stack. */ + case MB_REG_READ: + while (usNRegs > 0) + { + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + break; + /* write current register values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (usNRegs > 0) + { + pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; + pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; + iRegIndex++; + usNRegs--; + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master coils callback function. + * + * @param pucRegBuffer coils buffer + * @param usAddress coils address + * @param usNCoils coils number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucCoilBuf; + USHORT COIL_START; + USHORT COIL_NCOILS; + USHORT usCoilStart; + iNReg = usNCoils / 8 + 1; + + pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1]; + COIL_START = M_COIL_START; + COIL_NCOILS = M_COIL_NCOILS; + usCoilStart = usMCoilStart; + + /* if mode is read,the master will write the received date to buffer. */ + eMode = MB_REG_WRITE; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= COIL_START) + && (usAddress + usNCoils <= COIL_START + COIL_NCOILS)) + { + iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; + switch (eMode) + { + /* read current coil values from the protocol stack. */ + case MB_REG_READ: + while (iNReg > 0) + { + *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], + iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + /* last coils */ + usNCoils = usNCoils % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); + *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); + break; + + /* write current coil values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (iNReg > 1) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last coils */ + usNCoils = usNCoils % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNCoils != 0) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, + *pucRegBuffer++); + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master discrete callback function. + * + * @param pucRegBuffer discrete buffer + * @param usAddress discrete address + * @param usNDiscrete discrete number + * + * @return result + */ +eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucDiscreteInputBuf; + USHORT DISCRETE_INPUT_START; + USHORT DISCRETE_INPUT_NDISCRETES; + USHORT usDiscreteInputStart; + iNReg = usNDiscrete / 8 + 1; + + pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1]; + DISCRETE_INPUT_START = M_DISCRETE_INPUT_START; + DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES; + usDiscreteInputStart = usMDiscInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= DISCRETE_INPUT_START) + && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) + { + iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; + + /* write current discrete values with new values from the protocol stack. */ + while (iNReg > 1) + { + xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last discrete */ + usNDiscrete = usNDiscrete % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNDiscrete != 0) + { + xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, + usNDiscrete, *pucRegBuffer++); + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} +#endif From 73558791194272423d173bbaaa9a33019f4df8d5 Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 19:41:00 +0800 Subject: [PATCH 3/5] [modbus]update SConscript --- components/net/freemodbus-v1.6.0/SConscript | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/net/freemodbus-v1.6.0/SConscript b/components/net/freemodbus-v1.6.0/SConscript index 77ab37e086..d613a9f398 100644 --- a/components/net/freemodbus-v1.6.0/SConscript +++ b/components/net/freemodbus-v1.6.0/SConscript @@ -7,7 +7,6 @@ modbus/functions/mbutils.c modbus/functions/mbfuncother.c modbus/rtu/mbcrc.c port/port.c -port/user_mb_app.c """) master_rtu_src = Split(""" @@ -20,6 +19,7 @@ modbus/mb_m.c port/portevent_m.c port/portserial_m.c port/porttimer_m.c +port/user_mb_app_m.c """) slave_rtu_src = Split(""" @@ -32,6 +32,7 @@ modbus/mb.c port/portevent.c port/portserial.c port/porttimer.c +port/user_mb_app.c """) master_slave_rtu_src = Split(""" @@ -53,6 +54,8 @@ port/portserial.c port/portserial_m.c port/porttimer.c port/porttimer_m.c +port/user_mb_app.c +port/user_mb_app_m.c """) # The set of source files associated with this SConscript file. From dec67c3a29a79d1357d75bc518a531795be9950b Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 20:54:32 +0800 Subject: [PATCH 4/5] [modbus]fix port file's head file. --- components/net/freemodbus-v1.6.0/port/portserial.c | 2 +- components/net/freemodbus-v1.6.0/port/portserial_m.c | 2 +- components/net/freemodbus-v1.6.0/port/user_mb_app.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/components/net/freemodbus-v1.6.0/port/portserial.c b/components/net/freemodbus-v1.6.0/port/portserial.c index 0ba8dfbaec..3a5f8eab62 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial.c +++ b/components/net/freemodbus-v1.6.0/port/portserial.c @@ -25,7 +25,7 @@ #include "mb.h" #include "mbport.h" #include "rtdevice.h" -#include "bsp.h" +#include "board.h" /* ----------------------- Static variables ---------------------------------*/ ALIGN(RT_ALIGN_SIZE) diff --git a/components/net/freemodbus-v1.6.0/port/portserial_m.c b/components/net/freemodbus-v1.6.0/port/portserial_m.c index 4dc02d92bd..6c3d4c8299 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial_m.c +++ b/components/net/freemodbus-v1.6.0/port/portserial_m.c @@ -25,7 +25,7 @@ #include "mb.h" #include "mbport.h" #include "rtdevice.h" -#include "bsp.h" +#include "board.h" #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Static variables ---------------------------------*/ diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.h b/components/net/freemodbus-v1.6.0/port/user_mb_app.h index 846b9a3a48..864c3860bf 100644 --- a/components/net/freemodbus-v1.6.0/port/user_mb_app.h +++ b/components/net/freemodbus-v1.6.0/port/user_mb_app.h @@ -18,8 +18,6 @@ #define S_REG_HOLDING_NREGS 100 /* salve mode: holding register's all address */ #define S_HD_RESERVE 0 -#define S_HD_CPU_USAGE_MAJOR 1 -#define S_HD_CPU_USAGE_MINOR 2 /* salve mode: input register's all address */ #define S_IN_RESERVE 0 /* salve mode: coil's all address */ From b3290f6eede6622b395c2a09d729f50917c783ee Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 21:22:18 +0800 Subject: [PATCH 5/5] [modbus]changed tabs to spaces. --- components/net/freemodbus-v1.6.0/port/port.c | 6 +++--- components/net/freemodbus-v1.6.0/port/port.h | 6 +++--- .../net/freemodbus-v1.6.0/port/portserial.c | 2 +- .../net/freemodbus-v1.6.0/port/portserial_m.c | 10 +++++----- .../net/freemodbus-v1.6.0/port/porttimer_m.c | 16 ++++++++-------- .../net/freemodbus-v1.6.0/port/user_mb_app.c | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/components/net/freemodbus-v1.6.0/port/port.c b/components/net/freemodbus-v1.6.0/port/port.c index 527af909ac..d01c5c9d6a 100644 --- a/components/net/freemodbus-v1.6.0/port/port.c +++ b/components/net/freemodbus-v1.6.0/port/port.c @@ -16,7 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * File: $Id: portevent.c,v 1.60 2015/02/01 9:18:05 Armink $ + * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $ */ /* ----------------------- System includes --------------------------------*/ @@ -28,11 +28,11 @@ static rt_base_t level; /* ----------------------- Start implementation -----------------------------*/ void EnterCriticalSection(void) { - level = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); } void ExitCriticalSection(void) { - rt_hw_interrupt_enable(level); + rt_hw_interrupt_enable(level); } diff --git a/components/net/freemodbus-v1.6.0/port/port.h b/components/net/freemodbus-v1.6.0/port/port.h index 92056116b8..73d2177c9a 100644 --- a/components/net/freemodbus-v1.6.0/port/port.h +++ b/components/net/freemodbus-v1.6.0/port/port.h @@ -30,11 +30,11 @@ #include #include -#define INLINE +#define INLINE #define PR_BEGIN_EXTERN_C extern "C" { -#define PR_END_EXTERN_C } +#define PR_END_EXTERN_C } -#define ENTER_CRITICAL_SECTION() EnterCriticalSection() +#define ENTER_CRITICAL_SECTION() EnterCriticalSection() #define EXIT_CRITICAL_SECTION() ExitCriticalSection() typedef uint8_t BOOL; diff --git a/components/net/freemodbus-v1.6.0/port/portserial.c b/components/net/freemodbus-v1.6.0/port/portserial.c index 3a5f8eab62..317c7f4605 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial.c +++ b/components/net/freemodbus-v1.6.0/port/portserial.c @@ -133,7 +133,7 @@ void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) else { /* switch 485 to transmit mode */ - rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH); + rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH); /* disable RX interrupt */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } diff --git a/components/net/freemodbus-v1.6.0/port/portserial_m.c b/components/net/freemodbus-v1.6.0/port/portserial_m.c index 6c3d4c8299..8ec0d081f1 100644 --- a/components/net/freemodbus-v1.6.0/port/portserial_m.c +++ b/components/net/freemodbus-v1.6.0/port/portserial_m.c @@ -57,7 +57,7 @@ BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, * set 485 mode receive and transmit control IO * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user */ - rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); + rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); /* set serial name */ if (ucPORT == 1) { @@ -129,12 +129,12 @@ void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) /* enable RX interrupt */ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); /* switch 485 to receive mode */ - rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); } else { /* switch 485 to transmit mode */ - rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); /* disable RX interrupt */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } @@ -154,13 +154,13 @@ void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) void vMBMasterPortClose(void) { - serial->parent.close(&(serial->parent)); + serial->parent.close(&(serial->parent)); } BOOL xMBMasterPortSerialPutByte(CHAR ucByte) { serial->parent.write(&(serial->parent), 0, &ucByte, 1); - return TRUE; + return TRUE; } BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) diff --git a/components/net/freemodbus-v1.6.0/port/porttimer_m.c b/components/net/freemodbus-v1.6.0/port/porttimer_m.c index 69bdc54879..00441bfd1c 100644 --- a/components/net/freemodbus-v1.6.0/port/porttimer_m.c +++ b/components/net/freemodbus-v1.6.0/port/porttimer_m.c @@ -54,44 +54,44 @@ BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) void vMBMasterPortTimersT35Enable() { - rt_tick_t timer_tick = (50 * usT35TimeOut50us) - / (1000 * 1000 / RT_TICK_PER_SECOND); + rt_tick_t timer_tick = (50 * usT35TimeOut50us) + / (1000 * 1000 / RT_TICK_PER_SECOND); /* Set current timer mode, don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_T35); - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); rt_timer_start(&timer); } void vMBMasterPortTimersConvertDelayEnable() { - rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; + rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; /* Set current timer mode, don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); rt_timer_start(&timer); } void vMBMasterPortTimersRespondTimeoutEnable() { - rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; + rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; /* Set current timer mode, don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); rt_timer_start(&timer); } void vMBMasterPortTimersDisable() { - rt_timer_stop(&timer); + rt_timer_stop(&timer); } void prvvTIMERExpiredISR(void) diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.c b/components/net/freemodbus-v1.6.0/port/user_mb_app.c index e6fdede11f..8da7376336 100644 --- a/components/net/freemodbus-v1.6.0/port/user_mb_app.c +++ b/components/net/freemodbus-v1.6.0/port/user_mb_app.c @@ -260,8 +260,8 @@ eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT us if ((usAddress >= DISCRETE_INPUT_START) && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) { - iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; //每个寄存器存8个 - iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; //相对于寄存器内部的位地址 + iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; while (iNReg > 0) {