Modbus RTU/ASCII/TCP with lwip TCP working partial, but with errors (retransmitions)
Dependencies: EthernetNetIf mbed
Diff: ModBus/mbfuncdisc.cpp
- Revision:
- 0:f54e9507171b
diff -r 000000000000 -r f54e9507171b ModBus/mbfuncdisc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ModBus/mbfuncdisc.cpp Mon Dec 05 22:49:02 2011 +0000 @@ -0,0 +1,125 @@ + /* + * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS + * Copyright (C) 2006 Christian Walter <wolti@sil.at> + * + * 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 + */ + + + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ + +#if MB_FUNC_READ_COILS_ENABLED > 0 + +eMBException +eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usDiscreteCnt; + UCHAR ucNBytes; + 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++; + + usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 ); + usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usDiscreteCnt >= 1 ) && + ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_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_DISCRETE_INPUTS; + *usLen += 1; + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usDiscreteCnt & 0x0007 ) != 0 ) + { + ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 ); + } + else + { + ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 ); + } + *pucFrameCur++ = ucNBytes; + *usLen += 1; + + eRegStatus = + eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + /* The response contains the function code, the starting address + * and the quantity of registers. We reuse the old values in the + * buffer because they are still valid. */ + *usLen += ucNBytes;; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif