/* * FreeModbus Libary: Linux Demo Application * Copyright (C) 2006 Christian Walter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * File: $Id: demo.c,v 1.2 2006/10/12 08:12:06 wolti Exp $ */ /* ----------------------- Standard includes --------------------------------*/ #include #include #include #include #include #include #include #include "demo.h" /* ----------------------- Defines ------------------------------------------*/ #define PROG "freemodbus" #define REG_INPUT_START 1000 #define REG_INPUT_NREGS 10 #define REG_HOLDING_START 2000 #define REG_HOLDING_NREGS 130 /* ----------------------- Static variables ---------------------------------*/ static USHORT usRegInputStart = REG_INPUT_START; USHORT* usRegInputBuf; static USHORT usRegHoldingStart = REG_HOLDING_START; USHORT* usRegHoldingBuf; static pthread_mutex_t xLock = PTHREAD_MUTEX_INITIALIZER; static BOOL bDoExit; /* ----------------------- Static functions ---------------------------------*/ static BOOL bCreatePollingThread( void ); //static enum ThreadState eGetPollingThreadState( void ); //static void vSetPollingThreadState( enum ThreadState eNewState ); static void *pvPollingThread( void *pvParameter ); /* ----------------------- Start implementation -----------------------------*/ BOOL bSetSignal( int iSignalNr, void ( *pSigHandler ) ( int ) ) { BOOL bResult; struct sigaction xNewSig, xOldSig; xNewSig.sa_handler = pSigHandler; sigemptyset( &xNewSig.sa_mask ); xNewSig.sa_flags = 0; if( sigaction( iSignalNr, &xNewSig, &xOldSig ) != 0 ) { bResult = FALSE; } else { bResult = TRUE; } return bResult; } void vSigShutdown( int xSigNr ) { switch ( xSigNr ) { case SIGQUIT: case SIGINT: case SIGTERM: vSetPollingThreadState( SHUTDOWN ); bDoExit = TRUE; } } BOOL active_modbus( USHORT* mPara, USHORT* mStatus, USHORT port_num) { int iExitCode = EXIT_SUCCESS; // CHAR cCh; const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC }; usRegHoldingBuf = mPara; usRegInputBuf = mStatus; if( !bSetSignal( SIGQUIT, vSigShutdown ) || !bSetSignal( SIGINT, vSigShutdown ) || !bSetSignal( SIGTERM, vSigShutdown ) ) { fprintf( stderr, "%s: can't install signal handlers: %s!\n", PROG, strerror( errno ) ); iExitCode = EXIT_FAILURE; } else if( eMBInit( MB_RTU, 0x0A, port_num, 38400, MB_PAR_EVEN ) != MB_ENOERR ) { fprintf( stderr, "%s: can't initialize modbus stack!\n", PROG ); iExitCode = EXIT_FAILURE; } else if( eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 ) != MB_ENOERR ) { fprintf( stderr, "%s: can't set slave id!\n", PROG ); iExitCode = EXIT_FAILURE; } else { vSetPollingThreadState( STOPPED ); if( bCreatePollingThread( ) != TRUE ) { iExitCode = EXIT_FAILURE; vMBPortLog( MB_LOG_DEBUG, "active_modbus", "Can't start protocol stack! Already running?\n"); } } return iExitCode; } BOOL bCreatePollingThread( void ) { BOOL bResult; pthread_t xThread; if( eGetPollingThreadState( ) == STOPPED ) { if( pthread_create( &xThread, NULL, pvPollingThread, NULL ) != 0 ) { bResult = FALSE; } else { bResult = TRUE; } } else { bResult = FALSE; } return bResult; } void * pvPollingThread( void *pvParameter ) { vSetPollingThreadState( RUNNING ); if( eMBEnable( ) == MB_ENOERR ) { do { // vMBPortLog( MB_LOG_DEBUG, "usRegInputBuf[0]", "%d\n", usRegInputBuf[0]); if( eMBPoll( ) != MB_ENOERR ) break; // usRegInputBuf[0] = ( USHORT ) rand( ); } while( eGetPollingThreadState( ) != SHUTDOWN ); } ( void )eMBDisable( ); vSetPollingThreadState( STOPPED ); return 0; } enum ThreadState eGetPollingThreadState( ) { enum ThreadState eCurState; ( void )pthread_mutex_lock( &xLock ); eCurState = ePollThreadState; ( void )pthread_mutex_unlock( &xLock ); return eCurState; } void vSetPollingThreadState( enum ThreadState eNewState ) { ( void )pthread_mutex_lock( &xLock ); ePollThreadState = eNewState; ( void )pthread_mutex_unlock( &xLock ); } eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) { eMBErrorCode eStatus = MB_ENOERR; int iRegIndex; vMBPortLog( MB_LOG_DEBUG, "eMBRegInputCB", "exe\n"); if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ) { iRegIndex = ( int )( usAddress - usRegInputStart ); while( usNRegs > 0 ) { *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 ); *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF ); iRegIndex++; usNRegs--; } } else { eStatus = MB_ENOREG; } return eStatus; } void CallProcessCommands(int index); eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) { eMBErrorCode eStatus = MB_ENOERR; int iRegIndex; vMBPortLog( MB_LOG_DEBUG, "eMBRegHoldingCB", "exe\n"); if( ( usAddress >= REG_HOLDING_START ) && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) ) { iRegIndex = ( int )( usAddress - usRegHoldingStart ); switch ( eMode ) { /* Pass current register values to the protocol stack. */ case MB_REG_READ: while( usNRegs > 0 ) { *pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 ); *pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF ); iRegIndex++; usNRegs--; } break; /* Update current register values with new values from the * protocol stack. */ case MB_REG_WRITE: while( usNRegs > 0 ) { usRegHoldingBuf[iRegIndex - 1] = *pucRegBuffer++ << 8; usRegHoldingBuf[iRegIndex - 1] |= *pucRegBuffer++; vMBPortLog( MB_LOG_DEBUG, "eMBRegHoldingCB", "usRegHoldingBuf[%d] %d\n",iRegIndex - 1, usRegHoldingBuf[iRegIndex - 1]); CallProcessCommands(iRegIndex); iRegIndex++; usNRegs--; } } } else { eStatus = MB_ENOREG; } return eStatus; } eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode ) { return MB_ENOREG; } eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) { return MB_ENOREG; }