sw k
/
Modbus
a
Fork of Modbus by
Embed:
(wiki syntax)
Show/hide line numbers
mbfuncholding.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: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 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 + 0) 00046 #define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) 00047 #define MB_PDU_FUNC_READ_SIZE ( 4 ) 00048 #define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) 00049 00050 #define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) 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 + 0 ) 00055 #define MB_PDU_FUNC_WRITE_MUL_REGCNT_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_REGCNT_MAX ( 0x0078 ) 00060 00061 #define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) 00062 #define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) 00063 #define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) 00064 #define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) 00065 #define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) 00066 #define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) 00067 #define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 ) 00068 00069 /* ----------------------- Static functions ---------------------------------*/ 00070 eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); 00071 00072 /* ----------------------- Start implementation -----------------------------*/ 00073 00074 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0 00075 00076 eMBException 00077 eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) 00078 { 00079 USHORT usRegAddress; 00080 eMBException eStatus = MB_EX_NONE; 00081 eMBErrorCode eRegStatus; 00082 00083 if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) 00084 { 00085 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); 00086 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); 00087 usRegAddress++; 00088 00089 /* Make callback to update the value. */ 00090 eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], 00091 usRegAddress, 1, MB_REG_WRITE ); 00092 00093 /* If an error occured convert it into a Modbus exception. */ 00094 if( eRegStatus != MB_ENOERR ) 00095 { 00096 eStatus = prveMBError2Exception( eRegStatus ); 00097 } 00098 } 00099 else 00100 { 00101 /* Can't be a valid request because the length is incorrect. */ 00102 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00103 } 00104 return eStatus; 00105 } 00106 #endif 00107 00108 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 00109 eMBException 00110 eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) 00111 { 00112 USHORT usRegAddress; 00113 USHORT usRegCount; 00114 UCHAR ucRegByteCount; 00115 00116 eMBException eStatus = MB_EX_NONE; 00117 eMBErrorCode eRegStatus; 00118 00119 if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) ) 00120 { 00121 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); 00122 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); 00123 usRegAddress++; 00124 00125 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 ); 00126 usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] ); 00127 00128 ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; 00129 00130 if( ( usRegCount >= 1 ) && 00131 ( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) && 00132 ( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) ) 00133 { 00134 /* Make callback to update the register values. */ 00135 eRegStatus = 00136 eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], 00137 usRegAddress, usRegCount, MB_REG_WRITE ); 00138 00139 /* If an error occured convert it into a Modbus exception. */ 00140 if( eRegStatus != MB_ENOERR ) 00141 { 00142 eStatus = prveMBError2Exception( eRegStatus ); 00143 } 00144 else 00145 { 00146 /* The response contains the function code, the starting 00147 * address and the quantity of registers. We reuse the 00148 * old values in the buffer because they are still valid. 00149 */ 00150 *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; 00151 } 00152 } 00153 else 00154 { 00155 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00156 } 00157 } 00158 else 00159 { 00160 /* Can't be a valid request because the length is incorrect. */ 00161 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00162 } 00163 return eStatus; 00164 } 00165 #endif 00166 00167 #if MB_FUNC_READ_HOLDING_ENABLED > 0 00168 00169 eMBException 00170 eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) 00171 { 00172 USHORT usRegAddress; 00173 USHORT usRegCount; 00174 UCHAR *pucFrameCur; 00175 00176 eMBException eStatus = MB_EX_NONE; 00177 eMBErrorCode eRegStatus; 00178 00179 if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) 00180 { 00181 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); 00182 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); 00183 usRegAddress++; 00184 00185 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); 00186 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); 00187 00188 /* Check if the number of registers to read is valid. If not 00189 * return Modbus illegal data value exception. 00190 */ 00191 if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) ) 00192 { 00193 /* Set the current PDU data pointer to the beginning. */ 00194 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; 00195 *usLen = MB_PDU_FUNC_OFF; 00196 00197 /* First byte contains the function code. */ 00198 *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER; 00199 *usLen += 1; 00200 00201 /* Second byte in the response contain the number of bytes. */ 00202 *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 ); 00203 *usLen += 1; 00204 00205 /* Make callback to fill the buffer. */ 00206 eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ ); 00207 /* If an error occured convert it into a Modbus exception. */ 00208 if( eRegStatus != MB_ENOERR ) 00209 { 00210 eStatus = prveMBError2Exception( eRegStatus ); 00211 } 00212 else 00213 { 00214 *usLen += usRegCount * 2; 00215 } 00216 } 00217 else 00218 { 00219 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00220 } 00221 } 00222 else 00223 { 00224 /* Can't be a valid request because the length is incorrect. */ 00225 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00226 } 00227 return eStatus; 00228 } 00229 00230 #endif 00231 00232 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 00233 00234 eMBException 00235 eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) 00236 { 00237 USHORT usRegReadAddress; 00238 USHORT usRegReadCount; 00239 USHORT usRegWriteAddress; 00240 USHORT usRegWriteCount; 00241 UCHAR ucRegWriteByteCount; 00242 UCHAR *pucFrameCur; 00243 00244 eMBException eStatus = MB_EX_NONE; 00245 eMBErrorCode eRegStatus; 00246 00247 if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) ) 00248 { 00249 usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U ); 00250 usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] ); 00251 usRegReadAddress++; 00252 00253 usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U ); 00254 usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] ); 00255 00256 usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U ); 00257 usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] ); 00258 usRegWriteAddress++; 00259 00260 usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U ); 00261 usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] ); 00262 00263 ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF]; 00264 00265 if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) && 00266 ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) && 00267 ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) ) 00268 { 00269 /* Make callback to update the register values. */ 00270 eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF], 00271 usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); 00272 00273 if( eRegStatus == MB_ENOERR ) 00274 { 00275 /* Set the current PDU data pointer to the beginning. */ 00276 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; 00277 *usLen = MB_PDU_FUNC_OFF; 00278 00279 /* First byte contains the function code. */ 00280 *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; 00281 *usLen += 1; 00282 00283 /* Second byte in the response contain the number of bytes. */ 00284 *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 ); 00285 *usLen += 1; 00286 00287 /* Make the read callback. */ 00288 eRegStatus = 00289 eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ ); 00290 if( eRegStatus == MB_ENOERR ) 00291 { 00292 *usLen += 2 * usRegReadCount; 00293 } 00294 } 00295 if( eRegStatus != MB_ENOERR ) 00296 { 00297 eStatus = prveMBError2Exception( eRegStatus ); 00298 } 00299 } 00300 else 00301 { 00302 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 00303 } 00304 } 00305 return eStatus; 00306 } 00307 00308 #endif
Generated on Tue Jul 12 2022 23:11:12 by 1.7.2