Blame | Last modification | View Log | Download
/* name readnode.c *//* Copyright (C) Modicon, Inc. 1989, All Rights Reserved. *//*readnode.cThis test program uses the SA85.SYS device driver to read input oroutput coils, and input or output registers from a specified modbus plusnode. The format for the command line is as follows:READNODE <routing path> <reference> <length> <count>where <routing path> is a modbus plus routing address from 1 to 5 bytes,and <reference> is a 0X, 1X, 3X, or 4X reference, and length is the numberof items of the specified reference to read. The last parameter <count>indicates the number of times to read the data, a value of 0 indicatesread continously until control-c is struck at the keyboard.*//*include*/#define STRICT#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <conio.h>#include <signal.h>#include "netbios.h"#include "netlib.h"/*prototypes*/int main(int argc, char *argv[] );void dump(int qty, unsigned int *buff);void control_c(int sig);void show_values(unsigned int reference, int length, PUSHORT buffer);/*global variables*/char mbuffer[ 256 ]; /* modbus message buffer */char path[ 80 ]; /* modbus plus path */int completed; /* infinite loop variable *//*main()Parse the command line request, and issue the appropriate command tothe proper path. The format of the command line is as follows:READNODE <routing path> <reference> <length> <count>Examples:READNODE 1 40001 10 0 (node 1, register 40001, length 10, infinite)READNODE 1.2 30010 20 1 (node 1.2, register 30010, length 20, once)*/int main( argc, argv )int argc;char *argv[];{NCB *nd; /* netbios control block ptr */int i; /* general purpose */int ret_val; /* general purpose */unsigned int reference; /* reference to read */unsigned int offset; /* offset of reference */int length; /* amount to read */int loopcount; /* iteration counter */int route[ 5 ]; /* routing path */printf( "READNODE Modbus Plus access program. Version 1.0\n" );printf( "Copyright(C) 1989, Modicon, Inc. All Rights Reserved.\n\n" );if( argc < 5 ) { /* display help info. */puts( "Usage is:" );puts( " READNODE <routing path> <reference> <length> <count>" );puts( "Examples:" );puts( " READNODE 34 40001 10 1" );puts( " READNODE 13.34 30001 20 1" );puts( " READNODE 1 10001 128 100" );puts( " READNODE 25.1.34.16 1 5 0" );exit( 1 );}for( i = 0; i < 5; i++ )route[ i ] = 0; /* clear routing path */ret_val = sscanf( argv[ 1 ], "%d.%d.%d.%d.%d",&route[ 0 ],&route[ 1 ],&route[ 2 ],&route[ 3 ],&route[ 4 ] ); /* parse routing path argument */if( ret_val < 1 ) { /* verify routing assigned */puts( "ERROR, Unable to assign routing path." );exit( 1 );}for( i = 0; i < ret_val; i++ ) /* validate routing path */if( route[ i ] < 1 || route[ i ] > 64 ) {puts( "ERROR, Routing value out of range." );exit( 1 );}/* get reference value */if( sscanf( argv[ 2 ], "%u", &reference ) != 1 ) {puts( "ERROR, Invalid reference." );exit( 1 );}/* get length */if( sscanf( argv[ 3 ], "%d", &length ) != 1 ) {puts( "ERROR, Invalid length." );exit( 1 );}if( sscanf( argv[ 4 ], "%d", &loopcount ) != 1 ) {puts( "ERROR, Invalid loop count." );exit( 1 );}sprintf( path, "DM.%d.%d.%d.%d.%d", /* set up path string */route[ 0 ],route[ 1 ],route[ 2 ],route[ 3 ],route[ 4 ] );/* redirect control_c */if( signal( SIGINT, control_c ) == SIG_ERR ) {printf( "Unable to redirect Control-C." );exit( 1 );}/* open "path" on board 0 */if( ( nd = ncb_open( path, 0 ) ) == NULL ) {printf( "Unable to open DATA MASTER path.\n" );exit( 1 );}printf("Path %c%c.%d.%d.%d.%d.%d opened.\n",nd->NCB_CALLNAME[0],nd->NCB_CALLNAME[1],nd->NCB_CALLNAME[2],nd->NCB_CALLNAME[3],nd->NCB_CALLNAME[4],nd->NCB_CALLNAME[5],nd->NCB_CALLNAME[6] );completed = 0;while( !completed ) { /* loop until control-c struck */mbuffer[ 0 ] = 0; /* modbus slave address *//* Note: 5 byte routing code *//* replaces slave address */switch( reference / 10000 ) {case 0: /* discrete output */mbuffer[ 1 ] = 1; /* modbus function code */offset = reference - 1;break;case 1: /* discrete input */mbuffer[ 1 ] = 2; /* modbus function code */offset = reference - 10001;break;case 3: /* input register */mbuffer[ 1 ] = 4; /* modbus function code */offset = reference - 30001;break;case 4: /* output register */mbuffer[ 1 ] = 3; /* modbus function code */offset = reference - (unsigned int) 40001;break;}mbuffer[ 2 ] = (char) ( offset >> 8 ); /* offset high byte */mbuffer[ 3 ] = (char) (offset & 0xff); /* offset low byte */mbuffer[ 4 ] = (char) (length >> 8); /* length high byte */mbuffer[ 5 ] = (char) (length & 0xff); /* length low byte */if( ncb_send( nd, 6, mbuffer, 10) != 0 ) {printf( "Send error: %d occurred.\n", nd->NCB_RETCODE );ret_val = ncb_close( nd );exit( 1 ); /* close path, exit on error */}/* try to receive response */if( ncb_receive_wait( nd, mbuffer, 10 ) != 0 ) {printf( "Receive error: %d occurred.\n", nd->NCB_RETCODE );ret_val = ncb_close( nd );exit( 1 ); /* close path, exit on error */}if( mbuffer[ 1 ] & 0x80 ) { /* check for modbus error */printf( "Modbus error: %d occurred.\n", mbuffer[ 2 ] );ret_val = ncb_close( nd );exit( 1 ); /* close path, exit on error */}show_values( reference, length, (PUSHORT)&mbuffer[ 3 ] );printf( "\n" );if( loopcount != 0 ) { /* count of 0, means continous */loopcount--; /* else decrement to zero */if( loopcount == 0 )completed = 1; /* set complete flag when zero */}}ncb_close( nd ); /* close the path */exit( 0 ); /* good exit */return( 0 );}/*show_values()Display the values read in both decimal and hexadecimal format.*/void show_values( reference, length, buffer )unsigned reference;int length;PUSHORT buffer;{int offset;int count;unsigned value;int bits;offset = 0;switch( reference / 10000 ) {case 0: /* output coil */case 1: /* input coil */bits = 0;for( count = 0; count < length; count++ ) {if( (count % 10 ) == 0 ) {/* display 10 values per line */printf( "\n%05u:", reference + count );}if( buffer[ offset ] & ( 1 << bits ) ) {printf( " ON " ); /* show coil on */}else {printf( " OFF " ); /* show coil off */}if( bits == 15 ) { /* increment to next word */bits = 0;offset++;}else {bits++; /* just increment test value */}}printf( "\n" );break;case 3: /* input register */case 4: /* output register */for( offset = 0; offset < length; offset++ ) {if( (offset % 5 ) == 0 ) { /* display 5 values per line */printf( "\n%05u:", reference + offset );}value = ((buffer[ offset ] << 8) & 0xff00) | /* swap */((buffer[ offset ] >> 8) & 0xff);printf( "%04X (%05u) ", /* show in hex and decimal */value, value );}printf( "\n" );break;}}/*control_c()This routine replaces the control-C handler supplied by DOS. When youtype a control_C, the program will vector to this routine, which willset the completed flag to non-zero. In this test program, this will causethe infinite loop within main to terminate.*/void control_c(int sig){signal( SIGINT, SIG_IGN ); /* disable control-c */completed = 1; /* break infinite loop */signal( SIGINT, control_c ); /* reset control-c handler */}