Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 20:43:25 by
1.7.2