4
0
mirror of https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32.git synced 2025-01-31 19:36:13 +08:00

1、【优化】FreeModbus主机框架,使其与应用软件及从机部分耦合度降低;

2、【增加】主机忙查询、目标从机地址、获取当前PDU总长度等实用Get及Set方法;
3、【修改】user_mb_app.c一处书写错误;
4、【增加】主机读单个及多个寄存器方法,位于mbfuncholding_m.c,目前只实现了异步发送命令,下一步准备实现同步方式;

Signed-off-by: armink <armink.ztl@gmail.com>
This commit is contained in:
armink 2013-09-03 19:20:08 +08:00
parent 3947c51e7b
commit a115bbf3e3
8 changed files with 571 additions and 62 deletions

View File

@ -0,0 +1,289 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* 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

View File

@ -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.

View File

@ -0,0 +1,187 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* 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

View File

@ -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

View File

@ -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

View File

@ -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 ----------------------------------*/

View File

@ -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. */

View File

@ -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