Trying to make Modbus code into a lib

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbfunccoils.cpp Source File

mbfunccoils.cpp

00001 /* 
00002  * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
00003  * Copyright (c) 2006 Christian Walter <wolti@sil.at>
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  *
00028  * File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $
00029  */
00030 
00031 /* ----------------------- System includes ----------------------------------*/
00032 #include "stdlib.h"
00033 #include "string.h"
00034 
00035 /* ----------------------- Platform includes --------------------------------*/
00036 #include "port.h"
00037 
00038 /* ----------------------- Modbus includes ----------------------------------*/
00039 #include "mb.h"
00040 #include "mbframe.h"
00041 #include "mbproto.h"
00042 #include "mbconfig.h"
00043 
00044 /* ----------------------- Defines ------------------------------------------*/
00045 #define MB_PDU_FUNC_READ_ADDR_OFF           ( MB_PDU_DATA_OFF )
00046 #define MB_PDU_FUNC_READ_COILCNT_OFF        ( MB_PDU_DATA_OFF + 2 )
00047 #define MB_PDU_FUNC_READ_SIZE               ( 4 )
00048 #define MB_PDU_FUNC_READ_COILCNT_MAX        ( 0x07D0 )
00049 
00050 #define MB_PDU_FUNC_WRITE_ADDR_OFF          ( MB_PDU_DATA_OFF )
00051 #define MB_PDU_FUNC_WRITE_VALUE_OFF         ( MB_PDU_DATA_OFF + 2 )
00052 #define MB_PDU_FUNC_WRITE_SIZE              ( 4 )
00053 
00054 #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF      ( MB_PDU_DATA_OFF )
00055 #define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF   ( MB_PDU_DATA_OFF + 2 )
00056 #define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF   ( MB_PDU_DATA_OFF + 4 )
00057 #define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF    ( MB_PDU_DATA_OFF + 5 )
00058 #define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN      ( 5 )
00059 #define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX   ( 0x07B0 )
00060 
00061 /* ----------------------- Static functions ---------------------------------*/
00062 eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
00063 
00064 /* ----------------------- Start implementation -----------------------------*/
00065 
00066 #if MB_FUNC_READ_COILS_ENABLED > 0
00067 
00068 eMBException
00069 eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
00070 {
00071     USHORT          usRegAddress;
00072     USHORT          usCoilCount;
00073     UCHAR           ucNBytes;
00074     UCHAR          *pucFrameCur;
00075 
00076     eMBException    eStatus = MB_EX_NONE;
00077     eMBErrorCode    eRegStatus;
00078 
00079     if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
00080     {
00081         usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
00082         usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
00083         usRegAddress++;
00084 
00085         usCoilCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8 );
00086         usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] );
00087 
00088         /* Check if the number of registers to read is valid. If not
00089          * return Modbus illegal data value exception. 
00090          */
00091         if( ( usCoilCount >= 1 ) &&
00092             ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) )
00093         {
00094             /* Set the current PDU data pointer to the beginning. */
00095             pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
00096             *usLen = MB_PDU_FUNC_OFF;
00097 
00098             /* First byte contains the function code. */
00099             *pucFrameCur++ = MB_FUNC_READ_COILS;
00100             *usLen += 1;
00101 
00102             /* Test if the quantity of coils is a multiple of 8. If not last
00103              * byte is only partially field with unused coils set to zero. */
00104             if( ( usCoilCount & 0x0007 ) != 0 )
00105             {
00106                 ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 );
00107             }
00108             else
00109             {
00110                 ucNBytes = ( UCHAR )( usCoilCount / 8 );
00111             }
00112             *pucFrameCur++ = ucNBytes;
00113             *usLen += 1;
00114 
00115             eRegStatus =
00116                 eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount,
00117                                MB_REG_READ  );
00118 
00119             /* If an error occured convert it into a Modbus exception. */
00120             if( eRegStatus != MB_ENOERR  )
00121             {
00122                 eStatus = prveMBError2Exception( eRegStatus );
00123             }
00124             else
00125             {
00126                 /* The response contains the function code, the starting address
00127                  * and the quantity of registers. We reuse the old values in the 
00128                  * buffer because they are still valid. */
00129                 *usLen += ucNBytes;;
00130             }
00131         }
00132         else
00133         {
00134             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00135         }
00136     }
00137     else
00138     {
00139         /* Can't be a valid read coil register request because the length
00140          * is incorrect. */
00141         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00142     }
00143     return eStatus;
00144 }
00145 
00146 #if MB_FUNC_WRITE_COIL_ENABLED > 0
00147 eMBException
00148 eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
00149 {
00150     USHORT          usRegAddress;
00151     UCHAR           ucBuf[2];
00152 
00153     eMBException    eStatus = MB_EX_NONE;
00154     eMBErrorCode    eRegStatus;
00155 
00156     if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
00157     {
00158         usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
00159         usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
00160         usRegAddress++;
00161 
00162         if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) &&
00163             ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) ||
00164               ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) )
00165         {
00166             ucBuf[1] = 0;
00167             if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF )
00168             {
00169                 ucBuf[0] = 1;
00170             }
00171             else
00172             {
00173                 ucBuf[0] = 0;
00174             }
00175             eRegStatus =
00176                 eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE  );
00177 
00178             /* If an error occured convert it into a Modbus exception. */
00179             if( eRegStatus != MB_ENOERR  )
00180             {
00181                 eStatus = prveMBError2Exception( eRegStatus );
00182             }
00183         }
00184         else
00185         {
00186             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00187         }
00188     }
00189     else
00190     {
00191         /* Can't be a valid write coil register request because the length
00192          * is incorrect. */
00193         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00194     }
00195     return eStatus;
00196 }
00197 
00198 #endif
00199 
00200 #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
00201 eMBException
00202 eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
00203 {
00204     USHORT          usRegAddress;
00205     USHORT          usCoilCnt;
00206     UCHAR           ucByteCount;
00207     UCHAR           ucByteCountVerify;
00208 
00209     eMBException    eStatus = MB_EX_NONE;
00210     eMBErrorCode    eRegStatus;
00211 
00212     if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
00213     {
00214         usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
00215         usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
00216         usRegAddress++;
00217 
00218         usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 );
00219         usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] );
00220 
00221         ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
00222 
00223         /* Compute the number of expected bytes in the request. */
00224         if( ( usCoilCnt & 0x0007 ) != 0 )
00225         {
00226             ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 );
00227         }
00228         else
00229         {
00230             ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 );
00231         }
00232 
00233         if( ( usCoilCnt >= 1 ) &&
00234             ( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) &&
00235             ( ucByteCountVerify == ucByteCount ) )
00236         {
00237             eRegStatus =
00238                 eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
00239                                usRegAddress, usCoilCnt, MB_REG_WRITE  );
00240 
00241             /* If an error occured convert it into a Modbus exception. */
00242             if( eRegStatus != MB_ENOERR  )
00243             {
00244                 eStatus = prveMBError2Exception( eRegStatus );
00245             }
00246             else
00247             {
00248                 /* The response contains the function code, the starting address
00249                  * and the quantity of registers. We reuse the old values in the 
00250                  * buffer because they are still valid. */
00251                 *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
00252             }
00253         }
00254         else
00255         {
00256             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00257         }
00258     }
00259     else
00260     {
00261         /* Can't be a valid write coil register request because the length
00262          * is incorrect. */
00263         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
00264     }
00265     return eStatus;
00266 }
00267 
00268 #endif
00269 
00270 #endif