📄 main.c
字号:
/******************************************************************************
*
* (c) 2004 by BECK IPC GmbH
*
*******************************************************************************
*
* Module: main.c
*
* Function: This program provides a serial modbus rtu client example for SC12/DK40 or
* SC13/DK50 or DK60/SC1x3.
*
* It shall be used to communicate via RS232 or RS485 with another IPC@CHIP,
* which runs the modbus server example mb_ser_s.exe.
* A small simple function menue provides testing of the different modbus function types.
*
* The application programmer shall use the implemented basic modbus rtu client
* functions for his own modbus client application.
* For understanding the source code and using it for own application the
* following demands are required:
* 1. Good knowledge about the modbus protocol
* 2. Careful reading and understanding of this example program
*
* Required hardware/software for testing:
* 1. DK60/SC1x3,DK50/SC13 or DK40/SC12 as modbus rtu master(client), running this program
* 2. DK60/SC1x3,DK50/SC13 or DK40/SC12 as modbus rtu slave(server), running the program mb_slv.exe
* 3. All targets must be connected via RS232 nullmodem cable or RS485 connection
*
* The implementation based on the follwing documents from modbus.org
* Please note: The server uses only a subset of the specified modbus features
* 1. Modbus over serial line Specification & Implementation V1.0
* 2. Modbus application protocol specification V1.1
*
* Main files of this project:
* 1. Modbus.h : Contains several modbus specific defines and size
* 2. Main.c : Contains a small menue for sending several different
* modbus requests to a slave for demonstrating the usage
* of the different modbus request types, implemented at
* mb_ser.c .
* 3. mb_mst.c: Contains the modbus client initialzation (serial port settings),
* implementation of different modbus rtu request types.
* Supported functions: 1h,2h,3h,4h,5h,6h,Fh,10h,2Bh(only in parts)
*
* Program parameters:
* Usage : mb_mst port baudrate parity ser_mode
* Port : serial port 0: EXT 1: COM
* Parity : serial parity settings: 0: None 1: Odd 2: Even
* Ser_Mode: serial mode: 0: RS232 with RTS/CTS flow
* 1: RS232 no flowctrl
* 2: RS485
* Example : mb_mst 1 19200 0 0
*
*
* Please note: The recommended modbus timing specifications for
* sending/receiving bytes/frames via the serial line are only
* approximately implemented.
*
********************************************************************************
* Disclaimer: This program is an example and should be used as such.
* If you wish to use this program or parts of it in your application,
* you must validate the code yourself. BECK IPC GmbH can not be held
* responsible for the correct functioning or coding of this example.
*******************************************************************************
*
* $Header: main.c, 3, 01.09.2005 17:13:40, Markus Bartat$
*
******************************************************************************/
/******************************************************************************
* Includes
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#include <conio.h>
#include "clib.h"
#include "modbus.h"
#include "mb_mst.h"
/******************************************************************************
//Constants
******************************************************************************/
#define DKXX_REPLY_TIMEOUT 500 //wait at every request max. 500ms for reply from DKxx slave
#define MAX_OBJ_LENGTH 40
/******************************************************************************
//External vars
******************************************************************************/
extern long baudrate;
extern unsigned char serial_mode;
extern unsigned char parity;
extern int port;
extern unsigned char rs485;
/******************************************************************************/
//test buffers for reading/writing coils and registers
unsigned char coil_buf[MB_SER_MAX_BUF/8];
unsigned char coil_wr_buf[MB_SER_MAX_BUF/8];
unsigned int reg_buf[MB_SER_MAX_BUF/2];
unsigned int reg_wr_buf[MB_SER_MAX_BUF/2];
//test array for storing dev identification objects
unsigned char VendorName[MAX_OBJ_LENGTH];
unsigned char ProductCode[MAX_OBJ_LENGTH];
unsigned char MajorMinorRevision[MAX_OBJ_LENGTH];
unsigned char VendorURL[MAX_OBJ_LENGTH];
unsigned char ProductName[MAX_OBJ_LENGTH];
unsigned char ModelName[MAX_OBJ_LENGTH];
unsigned char ApplName[MAX_OBJ_LENGTH];
unsigned char *dev_id_data[7] = {VendorName,
ProductCode,
MajorMinorRevision,
VendorURL,
ProductName,
ModelName,
ApplName};
/******************************************************************************
//Program parameter usage message
******************************************************************************/
void usage(void)
{
printf("\r\nInvalid or missing parameters!"
"\r\nUsage : mb_mst port baudrate parity ser_mode\r\n"
"\r\nPort : 0: EXT 1: COM"
"\r\nParity : 0: None 1: Odd 2: Even"
"\r\nSer_Mode: 0: RS232 with RTS/CTS flow 1: RS232 no flowctrl 2: RS485\r\n"
"\r\nExample : mb_mst 1 19200 0 0\r\n");
}
/******************************************************************************
//Reading/analyze arguments
******************************************************************************/
int parse_args(int argc, char *argv[])
{
int result=0;
int tmp_value;
if(argc!=5)
{
result=-1;
}
else
{
//parse port
port = atoi(argv[1]);
if(port>1)
{
result=-1;
goto END_PARSE_ARGS;
}
//parse baudrate
baudrate = strtol(argv[2],NULL,10);
if((baudrate==0) || (baudrate > 230400L))
{
result=-1;
goto END_PARSE_ARGS;
}
//parse parity
tmp_value = atoi(argv[3]);
if((tmp_value < 0) || (tmp_value>2))
{
result=-1;
goto END_PARSE_ARGS;
}
parity=(unsigned char)tmp_value;
//parse serial mode
tmp_value = atoi(argv[4]);
if((tmp_value<0) || (tmp_value>2))
{
result=-1;
goto END_PARSE_ARGS;
}
serial_mode = (unsigned char) tmp_value;
}//elseif(argc!=5)
END_PARSE_ARGS:
return result;
}
/******************************************************************************
* getUnsigned
*
* Reads an unsigned value from STDIN
*
* Parameters:
* maximum - The maximum value that the user could enter
* preset - The value that is extended to the user
*
* Result:
* The value entered by the user or the preset value if the user simply pressed
* return
******************************************************************************/
unsigned long getUnsigned(
unsigned long maximum,
unsigned long preset )
{
int key, // Key pressed by user
length; // Length of the current value
// Print preset
printf( "%lu%n", preset, &length );
// Read cyphers until the user presses return
do
{
// Get key
key = getch();
// Check key
if( '0' <= key && key <= '9' &&
preset * 10 + (unsigned int)( key - '0' ) <= maximum ) // It's a cypher and applying it doesn't exceed maximum
{
// Apply cypher
preset *= 10;
preset += (unsigned int)( key - '0' );
printf( "%c", key );
++length;
}
// Backspace
if( key == '\b' && length )
{
preset /= 10;
printf( "\b \b" );
--length;
}
}
while( key != 13 );
return preset;
}
/******************************************************************************
Testing "read bit values" (read coils(02) or read discrete inputs(01)
*******************************************************************************/
void read_coils(unsigned char function_code)
{
unsigned int slave;
unsigned int quantity;
unsigned int address;
unsigned char exception;
int result,i;
printf("\r\n\r\nRead bit values(coils), function code %d ",function_code);
printf("\r\nEnter parameters:");
printf("\r\nSlave : ");
if( ( slave = (unsigned int)getUnsigned( 247, 1 ) ) < 1 )
{
printf( "\r\nInvalid slave address (%u).", slave );
return;
}
printf("\r\nAddress : ");
address = (unsigned int)getUnsigned( 65535L, 0 );
printf("\r\nQuantity: ");
if( ( quantity = (unsigned int)getUnsigned( 2000, 1 ) ) < 1 )
{
printf( "\r\nInvalid quantity (%u).", quantity );
return;
}
printf("\r\nSending request: Slave %02X, Address %04X, Quantity %d",
slave,address,quantity);
result=mb_ser_req_rd_coils( (unsigned char)slave,
function_code,
address,
quantity,
coil_buf,
&exception,
DKXX_REPLY_TIMEOUT);
if(result==MB_ERROR)
{
printf("\r\nCommunication error or timeout");
}
else
{
if(exception==0)
{
printf("\r\nExecution sucessful\r\nCoils read from slave[address:value]:\r\n");
for(i=address;i<quantity+address;i++)
{
printf("[%02d : %s] ",i,coil_buf[i]!=0?"ON":"OFF");
}
}
else
{
printf("\r\nReceived exception code %d",exception);
}
}
}
/******************************************************************************
Testing "read multiple registers" (function 03 and function 04)
*******************************************************************************/
void read_multiple_registers(unsigned char function_code)
{
unsigned int slave;
unsigned int quantity;
unsigned int address;
unsigned char exception;
int result,i;
printf("\r\n\r\nRead multiple registers, function code %d ",function_code);
printf("\r\nEnter parameters:");
printf("\r\nSlave : ");
if( ( slave = (unsigned int)getUnsigned( 247, 1 ) ) < 1 )
{
printf( "\r\nInvalid slave address (%u).", slave );
return;
}
printf("\r\nAddress : ");
address = (unsigned int)getUnsigned( 65535L, 0 );
printf("\r\nQuantity: ");
if( ( quantity = (unsigned int)getUnsigned( 125, 1 ) ) < 1 )
{
printf( "\r\nInvalid quantity (%u).", quantity );
return;
}
printf("\r\nSending request: Slave %02X, Address %04X, Quantity %d",
slave,address,quantity);
result=mb_ser_req_rd_regs( (unsigned char)slave,
function_code,
address,
quantity,
reg_buf,
&exception,
DKXX_REPLY_TIMEOUT);
if(result==MB_ERROR)
{
printf("\r\nCommunication error or timeout");
}
else
{
if(exception==0)
{
printf("\r\nExecution sucessful\r\nRegisters read from slave[address:value]:\r\n");
for(i=0;i<quantity;i++)
{
printf("[%02d : %04X] ",i,reg_buf[i]);
}
}
else
{
printf("\r\nReceived exception code %d",exception);
}
}
}
/******************************************************************************
Testing "write single register" function 06
*******************************************************************************/
void write_single_register(void)
{
unsigned int slave;
unsigned int value;
unsigned int address;
unsigned char exception;
int result;
printf("\r\n\r\nWriting single register, function code 06 ");
printf("\r\nEnter parameters:");
printf("\r\nSlave : ");
if( ( slave = (unsigned int)getUnsigned( 247, 1 ) ) < 1 )
{
printf( "\r\nInvalid slave address (%u).", slave );
return;
}
printf("\r\nAddress : ");
address = (unsigned int)getUnsigned( 65535L, 0 );
printf("\r\nValue : ");
value = (unsigned int)getUnsigned( 65535L, 0 );
printf("\r\nSending request: Slave %02X, Address %04X, Value %04X",
slave,address,value);
result=mb_ser_req_wr_single_reg( (unsigned char)slave,
address,
value,
&exception,
DKXX_REPLY_TIMEOUT);
if(result==MB_ERROR)
{
printf("\r\nCommunication error or timeout");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -