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.
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 20:43:25 by
1.7.2