fork frdm kl25z slave
Embed:
(wiki syntax)
Show/hide line numbers
mb.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: mb.c,v 1.27 2007/02/18 23:45:41 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 "mbconfig.h" 00041 #include "mbframe.h" 00042 #include "mbproto.h" 00043 #include "mbfunc.h" 00044 #include "mbport.h" 00045 #if MB_RTU_ENABLED == 1 00046 #include "mbrtu.h" 00047 #endif 00048 #if MB_ASCII_ENABLED == 1 00049 #include "mbascii.h" 00050 #endif 00051 #if MB_TCP_ENABLED == 1 00052 #include "mbtcp.h" 00053 #endif 00054 00055 #ifndef MB_PORT_HAS_CLOSE 00056 #define MB_PORT_HAS_CLOSE 0 00057 #endif 00058 00059 /* ----------------------- Static variables ---------------------------------*/ 00060 00061 #include "mbed.h" 00062 00063 static UCHAR ucMBAddress; 00064 static eMBMode eMBCurrentMode; 00065 00066 static enum { 00067 STATE_ENABLED, 00068 STATE_DISABLED, 00069 STATE_NOT_INITIALIZED 00070 } eMBState = STATE_NOT_INITIALIZED; 00071 00072 /* Functions pointer which are initialized in eMBInit( ). Depending on the 00073 * mode (RTU or ASCII) the are set to the correct implementations. 00074 */ 00075 static peMBFrameSend peMBFrameSendCur; 00076 static pvMBFrameStart pvMBFrameStartCur; 00077 static pvMBFrameStop pvMBFrameStopCur; 00078 static peMBFrameReceive peMBFrameReceiveCur; 00079 static pvMBFrameClose pvMBFrameCloseCur; 00080 00081 /* Callback functions required by the porting layer. They are called when 00082 * an external event has happend which includes a timeout or the reception 00083 * or transmission of a character. 00084 */ 00085 BOOL( *pxMBFrameCBByteReceived ) ( void ); 00086 BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); 00087 BOOL( *pxMBPortCBTimerExpired ) ( void ); 00088 00089 BOOL( *pxMBFrameCBReceiveFSMCur ) ( void ); 00090 BOOL( *pxMBFrameCBTransmitFSMCur ) ( void ); 00091 00092 /* An array of Modbus functions handlers which associates Modbus function 00093 * codes with implementing functions. 00094 */ 00095 static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = { 00096 #if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 00097 {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, 00098 #endif 00099 #if MB_FUNC_READ_INPUT_ENABLED > 0 00100 {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister}, 00101 #endif 00102 #if MB_FUNC_READ_HOLDING_ENABLED > 0 00103 {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister}, 00104 #endif 00105 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 00106 {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister}, 00107 #endif 00108 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0 00109 {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister}, 00110 #endif 00111 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 00112 {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister}, 00113 #endif 00114 #if MB_FUNC_READ_COILS_ENABLED > 0 00115 {MB_FUNC_READ_COILS, eMBFuncReadCoils}, 00116 #endif 00117 #if MB_FUNC_WRITE_COIL_ENABLED > 0 00118 {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil}, 00119 #endif 00120 #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 00121 {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils}, 00122 #endif 00123 #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 00124 {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs}, 00125 #endif 00126 }; 00127 00128 /* ----------------------- Start implementation -----------------------------*/ 00129 eMBErrorCode 00130 eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) { 00131 eMBErrorCode eStatus = MB_ENOERR ; 00132 00133 /* check preconditions */ 00134 if ( ( ucSlaveAddress == MB_ADDRESS_BROADCAST ) || 00135 ( ucSlaveAddress < MB_ADDRESS_MIN ) || ( ucSlaveAddress > MB_ADDRESS_MAX ) ) { 00136 eStatus = MB_EINVAL ; 00137 } else { 00138 ucMBAddress = ucSlaveAddress; 00139 00140 switch ( eMode ) { 00141 #if MB_RTU_ENABLED > 0 00142 case MB_RTU : 00143 pvMBFrameStartCur = eMBRTUStart; 00144 pvMBFrameStopCur = eMBRTUStop; 00145 peMBFrameSendCur = eMBRTUSend; 00146 peMBFrameReceiveCur = eMBRTUReceive; 00147 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; 00148 pxMBFrameCBByteReceived = xMBRTUReceiveFSM; 00149 pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM; 00150 pxMBPortCBTimerExpired = xMBRTUTimerT35Expired; 00151 00152 eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity ); 00153 break; 00154 #endif 00155 #if MB_ASCII_ENABLED > 0 00156 case MB_ASCII : 00157 pvMBFrameStartCur = eMBASCIIStart; 00158 pvMBFrameStopCur = eMBASCIIStop; 00159 peMBFrameSendCur = eMBASCIISend; 00160 peMBFrameReceiveCur = eMBASCIIReceive; 00161 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; 00162 pxMBFrameCBByteReceived = xMBASCIIReceiveFSM; 00163 pxMBFrameCBTransmitterEmpty = xMBASCIITransmitFSM; 00164 pxMBPortCBTimerExpired = xMBASCIITimerT1SExpired; 00165 00166 eStatus = eMBASCIIInit( ucMBAddress, ucPort, ulBaudRate, eParity ); 00167 break; 00168 #endif 00169 default: 00170 eStatus = MB_EINVAL ; 00171 } 00172 00173 if ( eStatus == MB_ENOERR ) { 00174 if ( !xMBPortEventInit( ) ) { 00175 /* port dependent event module initalization failed. */ 00176 eStatus = MB_EPORTERR ; 00177 } else { 00178 eMBCurrentMode = eMode; 00179 eMBState = STATE_DISABLED; 00180 } 00181 } 00182 } 00183 return eStatus; 00184 } 00185 00186 #if MB_TCP_ENABLED > 0 00187 eMBErrorCode 00188 eMBTCPInit( USHORT ucTCPPort ) { 00189 eMBErrorCode eStatus = MB_ENOERR ; 00190 00191 if ( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) { 00192 eMBState = STATE_DISABLED; 00193 } else if ( !xMBPortEventInit( ) ) { 00194 /* Port dependent event module initalization failed. */ 00195 eStatus = MB_EPORTERR ; 00196 } else { 00197 pvMBFrameStartCur = eMBTCPStart; 00198 pvMBFrameStopCur = eMBTCPStop; 00199 peMBFrameReceiveCur = eMBTCPReceive; 00200 peMBFrameSendCur = eMBTCPSend; 00201 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL; 00202 ucMBAddress = MB_TCP_PSEUDO_ADDRESS; 00203 eMBCurrentMode = MB_TCP ; 00204 eMBState = STATE_DISABLED; 00205 } 00206 return eStatus; 00207 } 00208 #endif 00209 00210 00211 eMBErrorCode 00212 eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler ) { 00213 int i; 00214 eMBErrorCode eStatus; 00215 00216 if ( ( 0 < ucFunctionCode ) && ( ucFunctionCode <= 127 ) ) { 00217 ENTER_CRITICAL_SECTION( ); 00218 if ( pxHandler != NULL ) { 00219 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) { 00220 if ( ( xFuncHandlers[i].pxHandler == NULL ) || 00221 ( xFuncHandlers[i].pxHandler == pxHandler ) ) { 00222 xFuncHandlers[i].ucFunctionCode = ucFunctionCode; 00223 xFuncHandlers[i].pxHandler = pxHandler; 00224 break; 00225 } 00226 } 00227 eStatus = ( i != MB_FUNC_HANDLERS_MAX ) ? MB_ENOERR : MB_ENORES ; 00228 } else { 00229 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) { 00230 if ( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) { 00231 xFuncHandlers[i].ucFunctionCode = 0; 00232 xFuncHandlers[i].pxHandler = NULL; 00233 break; 00234 } 00235 } 00236 /* Remove can't fail. */ 00237 eStatus = MB_ENOERR ; 00238 } 00239 EXIT_CRITICAL_SECTION( ); 00240 } else { 00241 eStatus = MB_EINVAL ; 00242 } 00243 return eStatus; 00244 } 00245 00246 00247 eMBErrorCode 00248 eMBClose( void ) { 00249 eMBErrorCode eStatus = MB_ENOERR ; 00250 00251 if ( eMBState == STATE_DISABLED ) { 00252 if ( pvMBFrameCloseCur != NULL ) { 00253 pvMBFrameCloseCur( ); 00254 } 00255 } else { 00256 eStatus = MB_EILLSTATE ; 00257 } 00258 return eStatus; 00259 } 00260 00261 eMBErrorCode 00262 eMBEnable( void ) { 00263 eMBErrorCode eStatus = MB_ENOERR ; 00264 00265 if ( eMBState == STATE_DISABLED ) { 00266 /* Activate the protocol stack. */ 00267 pvMBFrameStartCur( ); 00268 eMBState = STATE_ENABLED; 00269 } else { 00270 eStatus = MB_EILLSTATE ; 00271 } 00272 return eStatus; 00273 } 00274 00275 eMBErrorCode 00276 eMBDisable( void ) { 00277 eMBErrorCode eStatus; 00278 00279 if ( eMBState == STATE_ENABLED ) { 00280 pvMBFrameStopCur( ); 00281 eMBState = STATE_DISABLED; 00282 eStatus = MB_ENOERR ; 00283 } else if ( eMBState == STATE_DISABLED ) { 00284 eStatus = MB_ENOERR ; 00285 } else { 00286 eStatus = MB_EILLSTATE ; 00287 } 00288 return eStatus; 00289 } 00290 00291 eMBErrorCode 00292 eMBPoll( void ) { 00293 static UCHAR *ucMBFrame; 00294 static UCHAR ucRcvAddress; 00295 static UCHAR ucFunctionCode; 00296 static USHORT usLength; 00297 static eMBException eException; 00298 00299 int i; 00300 eMBErrorCode eStatus = MB_ENOERR ; 00301 eMBEventType eEvent; 00302 00303 /* Check if the protocol stack is ready. */ 00304 if ( eMBState != STATE_ENABLED ) { 00305 return MB_EILLSTATE ; 00306 } 00307 00308 /* Check if there is a event available. If not return control to caller. 00309 * Otherwise we will handle the event. */ 00310 if ( xMBPortEventGet( &eEvent ) == TRUE ) { 00311 switch ( eEvent ) { 00312 case EV_READY: 00313 break; 00314 00315 case EV_FRAME_RECEIVED: 00316 eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); 00317 //printf("[EV_FRAME_RECEIVED] usLength=%d \r\n", usLength ); 00318 if ( eStatus == MB_ENOERR ) { 00319 #if 0 00320 if ( ucMBFrame ) 00321 { 00322 printf( "\r\n" ); 00323 printf( "-->" ); 00324 for ( int i=0; i< usLength; i++ ) 00325 printf("%02x ", ucMBFrame[i]); 00326 printf( "\r\n" ); 00327 } 00328 #endif 00329 /* Check if the frame is for us. If not ignore the frame. */ 00330 if ( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) ) { 00331 ( void )xMBPortEventPost( EV_EXECUTE ); 00332 } //else 00333 //printf("Drop\r\n"); 00334 } //else printf("Error\r\n"); 00335 break; 00336 00337 case EV_EXECUTE: 00338 ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; 00339 eException = MB_EX_ILLEGAL_FUNCTION; 00340 00341 00342 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) { 00343 /* No more function handlers registered. Abort. */ 00344 if ( xFuncHandlers[i].ucFunctionCode == 0 ) { 00345 break; 00346 } else if ( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) { 00347 eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); 00348 break; 00349 } 00350 } 00351 00352 /* If the request was not sent to the broadcast address we 00353 * return a reply. */ 00354 if ( ucRcvAddress != MB_ADDRESS_BROADCAST ) { 00355 if ( eException != MB_EX_NONE ) { 00356 /* An exception occured. Build an error frame. */ 00357 usLength = 0; 00358 ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR ); 00359 ucMBFrame[usLength++] = eException; 00360 } 00361 eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength ); 00362 #if 0 00363 if ( ucMBFrame ) 00364 { 00365 printf( "\r\n" ); 00366 printf( "<--" ); 00367 for ( int i=0; i< usLength; i++ ) 00368 printf("%02x ", ucMBFrame[i]); 00369 printf( "\r\n" ); 00370 #endif 00371 } 00372 break; 00373 00374 case EV_FRAME_SENT: 00375 break; 00376 } 00377 } 00378 return MB_ENOERR ; 00379 }
Generated on Fri Jul 15 2022 08:22:19 by 1.7.2