diff --git a/FreeModbus/modbus/functions/mbfuncholding_m.c b/FreeModbus/modbus/functions/mbfuncholding_m.c new file mode 100644 index 0000000..c4539e8 --- /dev/null +++ b/FreeModbus/modbus/functions/mbfuncholding_m.c @@ -0,0 +1,289 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: $Id: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) + +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 ) + +#define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) +#define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) +#define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) +#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 + +eMBException +eMBMasterFuncWriteHoldingRegister( UCHAR ucSndAddr, USHORT * pusDataBuffer, USHORT usRegAddr) +{ + UCHAR *ucMBFrame; + eMBException eExceStates = MB_EX_NONE; + eMBErrorCode eErrStatus; + + if ( xMBMasterGetIsBusy() ) eErrStatus = MB_ETIMEDOUT; + else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM) eErrStatus = MB_EINVAL; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = ( UCHAR ) MB_FUNC_WRITE_REGISTER; + ucMBFrame[MB_PDU_FUNC_READ_ADDR_OFF] = ( UCHAR ) usRegAddr >> 8; + ucMBFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] = ( UCHAR ) usRegAddr; + ucMBFrame[MB_PDU_FUNC_READ_REGCNT_OFF] = ( UCHAR ) pusDataBuffer[0] >> 8; + ucMBFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] = ( UCHAR ) pusDataBuffer[0] ; + vMBMasterSetRTUSndSndLength( MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + } + /* If an error occured convert it into a Modbus exception. */ + if( eErrStatus != MB_ENOERR ) + { + eExceStates = prveMBError2Exception( eErrStatus ); + } + return eExceStates; +} +#endif + +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 +eMBException +eMBMasterFuncWriteMultipleHoldingRegister( UCHAR ucSndAddr,USHORT * pusDataBuffer, USHORT usRegAddr, USHORT usNRegs) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + eMBException eExceStatus = MB_EX_NONE; + eMBErrorCode eErrStatus; + + if ( xMBMasterGetIsBusy() ) eErrStatus = MB_ETIMEDOUT; + else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM || usNRegs > MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX) eErrStatus = MB_EINVAL; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = ( UCHAR ) MB_FUNC_WRITE_MULTIPLE_REGISTERS; + ucMBFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] = ( UCHAR ) usRegAddr >> 8; + ucMBFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] = ( UCHAR ) usRegAddr; + ucMBFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] = ( UCHAR ) usNRegs >> 8; + ucMBFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] = ( UCHAR ) usNRegs ; + ucMBFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF] = ( UCHAR ) usNRegs * 2; + ucMBFrame += MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF + 1; + while( usNRegs-- > 0) + { + *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; + *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; + } + vMBMasterSetRTUSndSndLength( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + 2*usNRegs ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + } + /* If an error occured convert it into a Modbus exception. */ + if( eErrStatus != MB_ENOERR ) + { + eExceStatus = prveMBError2Exception( eErrStatus ); + } + return eExceStatus; +} +#endif + +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + +eMBException +eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usRegCount; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER; + *usLen += 1; + + /* Second byte in the response contain the number of bytes. */ + *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 ); + *usLen += 1; + + /* Make callback to fill the buffer. */ + eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + *usLen += usRegCount * 2; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + +eMBException +eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegReadAddress; + USHORT usRegReadCount; + USHORT usRegWriteAddress; + USHORT usRegWriteCount; + UCHAR ucRegWriteByteCount; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) ) + { + usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U ); + usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] ); + usRegReadAddress++; + + usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U ); + usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] ); + + usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U ); + usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] ); + usRegWriteAddress++; + + usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U ); + usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] ); + + ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF]; + + if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) && + ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) && + ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) ) + { + /* Make callback to update the register values. */ + eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF], + usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); + + if( eRegStatus == MB_ENOERR ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; + *usLen += 1; + + /* Second byte in the response contain the number of bytes. */ + *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 ); + *usLen += 1; + + /* Make the read callback. */ + eRegStatus = + eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ ); + if( eRegStatus == MB_ENOERR ) + { + *usLen += 2 * usRegReadCount; + } + } + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + return eStatus; +} + +#endif +#endif + diff --git a/FreeModbus/modbus/include/mb.h b/FreeModbus/modbus/include/mb.h index db1a4fb..14b6cb9 100644 --- a/FreeModbus/modbus/include/mb.h +++ b/FreeModbus/modbus/include/mb.h @@ -150,9 +150,6 @@ typedef enum */ eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ); -/* This callback function will be use in Modbus Master mode.*/ -eMBErrorCode eMBMasterInit( eMBMode eMode, UCHAR ucPort, - ULONG ulBaudRate, eMBParity eParity ); /*! \ingroup modbus * \brief Initialize the Modbus protocol stack for Modbus TCP. @@ -185,8 +182,6 @@ eMBErrorCode eMBTCPInit( USHORT usTCPPort ); * eMBErrorCode::MB_EILLSTATE. */ eMBErrorCode eMBClose( void ); -/* This callback function will be use in Modbus Master mode.*/ -eMBErrorCode eMBMasterClose( void ); /*! \ingroup modbus * \brief Enable the Modbus protocol stack. @@ -199,8 +194,6 @@ eMBErrorCode eMBMasterClose( void ); * return eMBErrorCode::MB_EILLSTATE. */ eMBErrorCode eMBEnable( void ); -/* This callback function will be use in Modbus Master mode.*/ -eMBErrorCode eMBMasterEnable( void ); /*! \ingroup modbus * \brief Disable the Modbus protocol stack. @@ -212,8 +205,6 @@ eMBErrorCode eMBMasterEnable( void ); * eMBErrorCode::MB_EILLSTATE. */ eMBErrorCode eMBDisable( void ); -/* This callback function will be use in Modbus Master mode.*/ -eMBErrorCode eMBMasterDisable( void ); /*! \ingroup modbus * \brief The main pooling loop of the Modbus protocol stack. @@ -228,8 +219,6 @@ eMBErrorCode eMBMasterDisable( void ); * eMBErrorCode::MB_ENOERR. */ eMBErrorCode eMBPoll( void ); -/* This callback function will be use in Modbus Master mode.*/ -eMBErrorCode eMBMasterPoll( void ); /*! \ingroup modbus * \brief Configure the slave id of the device. diff --git a/FreeModbus/modbus/include/mb_m.h b/FreeModbus/modbus/include/mb_m.h new file mode 100644 index 0000000..95fc551 --- /dev/null +++ b/FreeModbus/modbus/include/mb_m.h @@ -0,0 +1,187 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: $Id: mb_m.h,v 1.60 2013/09/03 10:20:05 Armink Add Master Functions $ + */ + +#ifndef _MB_M_H +#define _MB_M_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/*! \defgroup modbus Modbus + * \code #include "mb_m.h" \endcode + * + * This module defines the interface for the application. It contains + * the basic functions and types required to use the Modbus Master protocol stack. + * A typical application will want to call eMBMasterInit() first. If the device + * is ready to answer network requests it must then call eMBEnable() to activate + * the protocol stack. In the main loop the function eMBMasterPoll() must be called + * periodically. The time interval between pooling depends on the configured + * Modbus timeout. If an RTOS is available a separate task should be created + * and the task should always call the function eMBMasterPoll(). + * + * \code + * // Initialize protocol stack in RTU mode for a Master + * eMBMasterInit( MB_RTU, 38400, MB_PAR_EVEN ); + * // Enable the Modbus Protocol Stack. + * eMBMasterEnable( ); + * for( ;; ) + * { + * // Call the main polling loop of the Modbus Master protocol stack. + * eMBMasterPoll( ); + * ... + * } + * \endcode + */ + +/* ----------------------- Defines ------------------------------------------*/ + +/*! \ingroup modbus + * \brief Use the default Modbus Master TCP port (502) + */ +#define MB_MASTER_TCP_PORT_USE_DEFAULT 0 + +/* ----------------------- Type definitions ---------------------------------*/ + + +/* ----------------------- Function prototypes ------------------------------*/ +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack. + * + * This functions initializes the ASCII or RTU module and calls the + * init functions of the porting layer to prepare the hardware. Please + * note that the receiver is still disabled and no Modbus frames are + * processed until eMBMasterEnable( ) has been called. + * + * \param eMode If ASCII or RTU mode should be used. + * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value + * is platform dependent and some ports simply choose to ignore it. + * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend + * on the porting layer. + * \param eParity Parity used for serial transmission. + * + * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. + * The protocol is then in the disabled state and ready for activation + * by calling eMBMasterEnable( ). Otherwise one of the following error codes + * is returned: + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterInit( eMBMode eMode, UCHAR ucPort, + ULONG ulBaudRate, eMBParity eParity ); + +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack for Modbus TCP. + * + * This function initializes the Modbus TCP Module. Please note that + * frame processing is still disabled until eMBEnable( ) is called. + * + * \param usTCPPort The TCP port to listen on. + * \return If the protocol stack has been initialized correctly the function + * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error + * codes is returned: + * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid + * slave addresses are in the range 1 - 247. + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterTCPInit( USHORT usTCPPort ); + +/*! \ingroup modbus + * \brief Release resources used by the protocol stack. + * + * This function disables the Modbus Master protocol stack and release all + * hardware resources. It must only be called when the protocol stack + * is disabled. + * + * \note Note all ports implement this function. A port which wants to + * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. + * + * \return If the resources where released it return eMBErrorCode::MB_ENOERR. + * If the protocol stack is not in the disabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterClose( void ); + +/*! \ingroup modbus + * \brief Enable the Modbus Master protocol stack. + * + * This function enables processing of Modbus Master frames. Enabling the protocol + * stack is only possible if it is in the disabled state. + * + * \return If the protocol stack is now in the state enabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it + * return eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterEnable( void ); + +/*! \ingroup modbus + * \brief Disable the Modbus Master protocol stack. + * + * This function disables processing of Modbus frames. + * + * \return If the protocol stack has been disabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterDisable( void ); + +/*! \ingroup modbus + * \brief The main pooling loop of the Modbus Master protocol stack. + * + * This function must be called periodically. The timer interval required + * is given by the application dependent Modbus slave timeout. Internally the + * function calls xMBMasterPortEventGet() and waits for an event from the receiver or + * transmitter state machines. + * + * \return If the protocol stack is not in the enabled state the function + * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns + * eMBErrorCode::MB_ENOERR. + */ +eMBErrorCode eMBMasterPoll( void ); + +/* Get Modbus Master busy flag,It will return TRUE when Master is busy. */ +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 ); +/* Get Modbus Master send PDU's buffer length.*/ +UCHAR ucMBMasterGetPDUSndLength( void ); +/* Set Modbus Master send PDU's buffer length.*/ +void vMBMasterSetRTUSndSndLength( UCHAR SendPDULength ); + +/* ----------------------- Callback -----------------------------------------*/ + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/FreeModbus/modbus/mb_m.c b/FreeModbus/modbus/mb_m.c index 6b69a91..e9c9109 100644 --- a/FreeModbus/modbus/mb_m.c +++ b/FreeModbus/modbus/mb_m.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions , $ + * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions $ */ /* ----------------------- System includes ----------------------------------*/ @@ -38,6 +38,7 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" +#include "mb_m.h" #include "mbconfig.h" #include "mbframe.h" #include "mbproto.h" @@ -62,12 +63,9 @@ /* ----------------------- Static variables ---------------------------------*/ -volatile UCHAR ucMBMasterSndAddress; -volatile BOOL bMBRunInMasterMode = FALSE; -UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX]; -BOOL bMasterIsBusy = FALSE; -static UCHAR * pucMasterPUDSndBuf = ucMasterRTUSndBuf + 1; -static UCHAR ucMasterSendPDULength; +static UCHAR ucMBMasterDestAddress; +static BOOL xMBRunInMasterMode = FALSE; +static BOOL xMasterIsBusy = FALSE; static enum { @@ -280,7 +278,7 @@ eMBMasterPoll( void ) case EV_MASTER_FRAME_RECEIVED: eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); /* Check if the frame is for us. If not ,send an error process event. */ - if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterSndAddress ) ) + if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) { ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); } @@ -302,9 +300,9 @@ eMBMasterPoll( void ) } else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode ) { - bMBRunInMasterMode = TRUE; + vMBMasterSetCBRunInMasterMode(TRUE); eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); - bMBRunInMasterMode = FALSE; + vMBMasterSetCBRunInMasterMode(FALSE); break; } } @@ -315,8 +313,9 @@ eMBMasterPoll( void ) case EV_MASTER_FRAME_SENT: /* Master is busy now. */ - bMasterIsBusy = TRUE; - eStatus = peMBMasterFrameSendCur( ucMBMasterSndAddress, pucMasterPUDSndBuf, ucMasterSendPDULength ); + vMBMasterSetIsBusy( TRUE ); + vMBMasterGetPDUSndBuf( &ucMBFrame ); + eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, ucMBMasterGetPDUSndLength() ); break; case EV_MASTER_ERROR_PROCESS: @@ -326,21 +325,48 @@ eMBMasterPoll( void ) return MB_ENOERR; } -BOOL bMBMasterGetIsBusy( void ) +BOOL xMBMasterGetIsBusy( void ) { - return bMasterIsBusy; + return xMasterIsBusy; +} + +void vMBMasterSetIsBusy( BOOL IsBusy ) +{ + xMasterIsBusy = IsBusy; +} + +BOOL xMBMasterGetCBRunInMasterMode( void ) +{ + return xMBRunInMasterMode; +} + +void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ) +{ + xMBRunInMasterMode = IsMasterMode; +} + +UCHAR ucMBMasterGetDestAddress( void ) +{ + return ucMBMasterDestAddress; +} + +void vMBMasterSetDestAddress( UCHAR Address ) +{ + ucMBMasterDestAddress = Address; } //Test Modbus Master void vMBMasterWriteHoldReg(UCHAR ucSlaveAddress, USHORT usRegAddress, USHORT ucRegValue) { - ucMBMasterSndAddress = ucSlaveAddress; - pucMasterPUDSndBuf[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; - pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 0] = usRegAddress >> 8; - pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 1] = usRegAddress; - pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 2] = ucRegValue >> 8; - pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 3] = ucRegValue ; - ucMasterSendPDULength = 5; + static UCHAR *ucMBFrame; + vMBMasterGetPDUSndBuf( &ucMBFrame ); + vMBMasterSetDestAddress(ucSlaveAddress); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; + ucMBFrame[MB_PDU_DATA_OFF + 0] = usRegAddress >> 8; + ucMBFrame[MB_PDU_DATA_OFF + 1] = usRegAddress; + ucMBFrame[MB_PDU_DATA_OFF + 2] = ucRegValue >> 8; + ucMBFrame[MB_PDU_DATA_OFF + 3] = ucRegValue ; + vMBMasterSetRTUSndSndLength(5); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); } #endif diff --git a/FreeModbus/modbus/rtu/mbrtu_m.c b/FreeModbus/modbus/rtu/mbrtu_m.c index 0e3f793..190aed7 100644 --- a/FreeModbus/modbus/rtu/mbrtu_m.c +++ b/FreeModbus/modbus/rtu/mbrtu_m.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions , $ + * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ */ /* ----------------------- System includes ----------------------------------*/ @@ -71,15 +71,15 @@ typedef enum static volatile eMBMasterSndState eSndState; static volatile eMBMasterRcvState eRcvState; -extern BOOL bMasterIsBusy; -extern UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX]; -volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX]; +static volatile UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX]; +static volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX]; +static volatile UCHAR ucMasterSendPDULength; static volatile UCHAR *pucMasterSndBufferCur; static volatile USHORT usMasterSndBufferCount; static volatile USHORT usMasterRcvBufferPos; -static volatile BOOL bFrameIsBroadcast = FALSE; +static volatile BOOL xFrameIsBroadcast = FALSE; /* ----------------------- Start implementation -----------------------------*/ eMBErrorCode eMBMasterRTUInit(UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) @@ -318,14 +318,14 @@ xMBMasterRTUTransmitFSM( void ) } else { - bFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; + xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; /* Disable transmitter. This prevents another transmit buffer * empty interrupt. */ vMBMasterPortSerialEnable( TRUE, FALSE ); eSndState = STATE_M_TX_XFWR; /* If the frame is broadcast ,master will enable timer of convert delay, * else master will enable timer of respond timeout. */ - if ( bFrameIsBroadcast == TRUE ) vMBMasterPortTimersConvertDelayEnable( ); + if ( xFrameIsBroadcast == TRUE ) vMBMasterPortTimersConvertDelayEnable( ); else vMBMasterPortTimersRespondTimeoutEnable( ); } break; @@ -370,7 +370,7 @@ 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 ( bFrameIsBroadcast == FALSE ) xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + if ( xFrameIsBroadcast == FALSE ) xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); break; /* Function called in an illegal state. */ default: @@ -381,9 +381,33 @@ xMBMasterRTUTimerExpired(void) vMBMasterPortTimersDisable(); /* Master is idel now. */ - bMasterIsBusy = FALSE; + vMBMasterSetIsBusy(FALSE); return xNeedPoll; } + +/* Get Modbus Master send RTU's buffer address pointer.*/ +void vMBMasterGetRTUSndBuf( UCHAR ** pucFrame ) +{ + *pucFrame = ( UCHAR * ) ucMasterRTUSndBuf; +} + +/* Get Modbus Master send PDU's buffer address pointer.*/ +void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ) +{ + *pucFrame = ( UCHAR * ) ucMasterRTUSndBuf[MB_SER_PDU_PDU_OFF]; +} + +/* Set Modbus Master send PDU's buffer length.*/ +void vMBMasterSetRTUSndSndLength( UCHAR SendPDULength ) +{ + ucMasterSendPDULength = SendPDULength; +} + +/* Get Modbus Master send PDU's buffer length.*/ +UCHAR ucMBMasterGetPDUSndLength( void ) +{ + return ucMasterSendPDULength; +} #endif diff --git a/FreeModbus/port/portevent_m.c b/FreeModbus/port/portevent_m.c index a2cbe48..08a4910 100644 --- a/FreeModbus/port/portevent_m.c +++ b/FreeModbus/port/portevent_m.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_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions, $ + * File: $Id: portevent_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ */ /* ----------------------- Modbus includes ----------------------------------*/ diff --git a/FreeModbus/port/user_mb_app.c b/FreeModbus/port/user_mb_app.c index a7c03bb..67cf017 100644 --- a/FreeModbus/port/user_mb_app.c +++ b/FreeModbus/port/user_mb_app.c @@ -20,8 +20,6 @@ USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS]; USHORT usMRegHoldStart = M_REG_HOLDING_START; USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; -extern volatile UCHAR ucMBMasterSndAddress; -extern volatile BOOL bMBRunInMasterMode; #endif //******************************输入寄存器回调函数********************************** //函数定义: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) @@ -43,9 +41,9 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) UCHAR usRegInStart; //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { - pusRegInputBuf = usMRegInBuf[ucMBMasterSndAddress]; + pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()]; REG_INPUT_START = M_REG_INPUT_START; REG_INPUT_NREGS = M_REG_INPUT_NREGS; usRegInStart = usMRegInStart; @@ -65,7 +63,7 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) while( usNRegs > 0 ) { //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; @@ -109,9 +107,9 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi UCHAR usRegHoldStart; //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { - pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterSndAddress]; + pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()]; REG_HOLDING_START = M_REG_HOLDING_START; REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; usRegHoldStart = usMRegHoldStart; @@ -123,7 +121,7 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi pusRegHoldingBuf = usSRegHoldBuf; REG_HOLDING_START = S_REG_INPUT_START; REG_HOLDING_NREGS = S_REG_INPUT_NREGS; - usRegHoldStart = usSRegInStart; + usRegHoldStart = usSRegHoldStart; } if( ( usAddress >= REG_HOLDING_START ) && @@ -187,9 +185,9 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { - pucCoilBuf = ucMCoilBuf[ucMBMasterSndAddress]; + pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress()]; COIL_START = M_COIL_START; COIL_NCOILS = M_COIL_NCOILS; usCoilStart = usMCoilStart; @@ -265,9 +263,9 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) iNReg = usNDiscrete / 8 + 1; //占用寄存器数量 //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { - pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterSndAddress]; + pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()]; DISCRETE_INPUT_START = M_DISCRETE_INPUT_START; DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES; usDiscreteInputStart = usMDiscInStart; @@ -287,7 +285,7 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ; //相对于寄存器内部的位地址 //Determine the master or slave - if (bMBRunInMasterMode) + if (xMBMasterGetCBRunInMasterMode()) { /* Update current coil values with new values from the * protocol stack. */ diff --git a/FreeModbus/port/user_mb_app.h b/FreeModbus/port/user_mb_app.h index 46cc0f1..5c866d6 100644 --- a/FreeModbus/port/user_mb_app.h +++ b/FreeModbus/port/user_mb_app.h @@ -2,8 +2,10 @@ #define USER_APP /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" -#include "mbport.h" +#include "mb_m.h" #include "mbconfig.h" +#include "mbframe.h" +#include "mbutils.h" /* -----------------------Slave Defines -------------------------------------*/ #define S_DISCRETE_INPUT_START 1 @@ -49,10 +51,4 @@ //主机模式:在离散输入中,各个地址对应的功能定义 #define M_DI_RESERVE 1 //保留 - - -/*--------------------------Extern Functions------------------------------------*/ -extern UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits ); -extern void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,UCHAR ucValue ); - #endif