📄 modbus_tcp_c.c
字号:
/************************************************************************
read_input_registers
Read the inputg registers in a slave and put the data into
an array.
*************************************************************************/
int read_input_registers_tcp( int slave, int start_addr, int count,
int *dest, int dest_size, int sfd )
{
int function = 0x04; /* Function: Read Input Reqisters */
int status;
if( count > MAX_INPUT_REGS )
{
count = MAX_INPUT_REGS;
#ifdef DEBUG
fprintf( stderr, "Too many input registers requested.\n" );
#endif
}
status = read_registers( function, slave, start_addr, count,
dest, dest_size, sfd );
return( status );
}
/************************************************************************
read_reg_response
reads the response data from a slave and puts the data into an
array.
************************************************************************/
int read_reg_response( int *dest, int dest_size, unsigned char *query, int fd )
{
unsigned char data[ MAX_RESPONSE_LENGTH ];
int raw_response_length;
int temp,i;
raw_response_length = modbus_response( data, query, fd );
if( raw_response_length > 0 )
raw_response_length -= 2;
if( raw_response_length > 0 )
{
for( i = 0;
i < ( data[8] * 2 ) && i < (raw_response_length / 2);
i++ )
{
/* shift reg hi_byte to temp */
temp = data[ 9 + i *2 ] << 8;
/* OR with lo_byte */
temp = temp | data[ 10 + i * 2 ];
dest[i] = temp;
}
}
return( raw_response_length );
}
/***********************************************************************
preset_response
Gets the raw data from the input stream.
***********************************************************************/
int preset_response( unsigned char *query, int fd )
{
unsigned char data[ MAX_RESPONSE_LENGTH ];
int raw_response_length;
raw_response_length = modbus_response( data, query, fd );
return( raw_response_length );
}
/*************************************************************************
set_single
sends a value to a register in a slave.
**************************************************************************/
int set_single( int function, int slave, int addr, int value, int fd )
{
int status;
int i;
unsigned char packet[ REQUEST_QUERY_SIZE ];
for( i = 0; i < 5; i++ ) packet[ i ] = 0;
packet[ i++ ] = 6;
packet[ i++ ] = slave;
packet[ i++ ] = function;
addr -= 1;
packet[ i++ ] = addr >> 8;
packet[ i++ ] = addr & 0x00FF;
packet[ i++ ] = value >> 8;
packet[ i++ ] = value & 0x00FF;
if( send_query( fd, packet, i ) > -1 )
{
status = preset_response( packet, fd );
}
else
{
status = SOCKET_FAILURE;
}
return( status );
}
/*************************************************************************
force_single_coil
turn on or off a single coil on the slave device
*************************************************************************/
int force_single_coil_tcp( int slave, int coil_addr, int state, int fd )
{
int function = 0x05;
int status;
if( state ) state = 0xFF00;
status = set_single( function, slave, coil_addr, state, fd );
return( status );
}
/*************************************************************************
preset_single_register
sets a value in one holding register in the slave device
*************************************************************************/
int preset_single_register_tcp(int slave, int reg_addr, int value, int fd )
{
int function = 0x06;
int status;
status = set_single( function, slave, reg_addr, value, fd );
return( status );
}
/************************************************************************
set_multiple_coils
Takes an array of ints and sets or resets the coils on a slave
appropriatly.
*************************************************************************/
#define PRESET_QUERY_SIZE 210
int set_multiple_coils_tcp( int slave, int start_addr, int coil_count,
int *data, int fd )
{
int byte_count;
int i, bit, packet_size, data_legth;
int coil_check = 0;
int data_array_pos = 0;
int status;
unsigned char packet[ PRESET_QUERY_SIZE ];
if( coil_count > MAX_WRITE_COILS )
{
coil_count = MAX_WRITE_COILS;
#ifdef DEBUG
fprintf( stderr, "Writing to too many coils.\n" );
#endif
}
for( packet_size = 0; packet_size < 5; packet_size++ )
packet[ packet_size ] = 0;
packet[ packet_size++ ] = 6;
packet[ packet_size++ ] = slave;
packet[ packet_size++ ] = 0x0F;
start_addr -= 1;
packet[ packet_size++ ] = start_addr >> 8;
packet[ packet_size++ ] = start_addr & 0x00FF;
packet[ packet_size++ ] = coil_count >> 8;
packet[ packet_size++ ] = coil_count & 0x00FF;
byte_count = (coil_count / 8) + 1;
packet[ packet_size ] = byte_count;
bit = 0x01;
for( i = 0; i < byte_count; i++)
{
packet[ ++packet_size ] = 0;
while( bit & 0xFF && coil_check++ < coil_count )
{
if( data[ data_array_pos++ ] )
{
packet[ packet_size ] |= bit;
}
else
{
packet[ packet_size ] &=~ bit;
}
bit = bit << 1;
}
bit = 0x01;
}
data_legth = packet_size - 5;
packet[ 4 ] = data_legth >> 8;
packet[ 5 ] = data_legth & 0x00FF;
if( send_query( fd, packet, ++packet_size ) > -1 )
{
status = preset_response( packet, fd );
}
else
{
status = SOCKET_FAILURE;
}
return( status );
}
/*************************************************************************
preset_multiple_registers
copy the values in an array to an array on the slave.
***************************************************************************/
int preset_multiple_registers_tcp( int slave, int start_addr,
int reg_count, int *data, int fd )
{
int byte_count, i, packet_size, data_legth;
int status;
unsigned char packet[ PRESET_QUERY_SIZE ];
if( reg_count > MAX_WRITE_REGS )
{
reg_count = MAX_WRITE_REGS;
#ifdef DEBUG
fprintf( stderr, "Trying to write to too many registers.\n" );
#endif
}
for( packet_size = 0; packet_size < 5; packet_size++ )
packet[ packet_size ] = 0;
packet[ packet_size++ ] = 6;
packet[ packet_size++ ] = slave;
packet[ packet_size++ ] = 0x10;
start_addr -= 1;
packet[ packet_size++ ] = start_addr >> 8;
packet[ packet_size++ ] = start_addr & 0x00FF;
packet[ packet_size++ ] = reg_count >> 8;
packet[ packet_size++ ] = reg_count & 0x00FF;
byte_count = reg_count * 2;
packet[ packet_size ] = byte_count;
for( i = 0; i < reg_count; i++ )
{
packet[ ++packet_size ] = data[ i ] >> 8;
packet[ ++packet_size ] = data[ i ] & 0x00FF;
}
data_legth = packet_size - 5;
packet[ 4 ] = data_legth >> 8;
packet[ 5 ] = data_legth & 0x00FF;
if( send_query( fd, packet, ++packet_size ) > -1 )
{
status = preset_response( packet, fd );
}
else
{
status = SOCKET_FAILURE;
}
return( status );
}
#define MODBUS_TCP_PORT 502
int set_up_tcp( char *ip_address )
{
int sfd;
struct sockaddr_in server;
int connect_stat;
sfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
server.sin_family = AF_INET;
server.sin_port = htons( MODBUS_TCP_PORT );
server.sin_addr.s_addr = inet_addr(ip_address);
if( sfd >= 0 )
{
connect_stat = connect( sfd, (struct sockaddr *)&server,
sizeof(struct sockaddr_in) );
if( connect_stat < 0 )
{
//plc_log_errmsg( 0, "\nConnect - error %d\n",
// connect_stat );
close( sfd );
sfd = -1;
// exit( connect_stat );
}
}
return( sfd );
}
/****************************************************************************
*****************************************************************************
*****************************************************************************
THIS SECTION IS DEDICATED TO MODBUS TCP SLAVE FUNCTIONS.
*****************************************************************************
*****************************************************************************
****************************************************************************/
int get_slave_query( int *slave_addr, int *query, int *start_addr,
int *point_count, int *data, int sfd )
{
unsigned char raw_data[ MAX_RESPONSE_LENGTH ];
int response_length;
int i,temp;
response_length = receive_response( raw_data, sfd );
if( response_length > 0 )
{
*slave_addr = raw_data[ 6 ];
*query = raw_data[ 7 ];
*start_addr = raw_data[ 8 ] << 8;
*start_addr = *start_addr | raw_data[ 9 ];
*point_count = raw_data[ 10 ] << 8;
*point_count = *point_count | raw_data[ 11 ];
for( i = 0;
i < ( data[12] * 2 ) && i < (response_length / 2);
i++ )
{
/* shift reg hi_byte to temp */
temp = data[ 13 + i *2 ] << 8;
/* OR with lo_byte */
temp = temp | data[ 14 + i * 2 ];
data[i] = temp;
}
}
return( response_length );
}
int set_up_tcp_slave( void )
{
int sfd;
struct sockaddr_in client;
int bind_stat;
int accept_stat;
int listen_stat;
client.sin_family = AF_INET;
client.sin_port = htons( MODBUS_TCP_PORT );
client.sin_addr.s_addr = INADDR_ANY;
sfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sfd >= 0 )
{
bind_stat = bind( sfd, &client, sizeof( client ) );
if( bind_stat < 0 )
{
//plc_log_errmsg( 0,"bind failed %s\n",
// strerror( errno) );
close( sfd );
sfd = -1;
//exit( bind_stat );
}
}
if( sfd >= 0 )
{
listen_stat = listen( sfd, 1 );
if( listen_stat != 0 )
{
//plc_log_errmsg( "listen FAILED with %s\n",
// strerror( errno ) );
close( sfd );
sfd = -2;
if( listen_stat > 0 ) sfd = -3;
//exit(listen_stat);
}
if( listen_stat == 0 )
{
accept_stat = accept( sfd, NULL, NULL );
if( accept_stat < 0 )
{
//plc_log_errmsg( 0, "\nConnect - error %d\n",
// connect_stat );
close( sfd );
sfd = -4;
//exit( accept_stat );
}
}
}
return( sfd );
}
</XMP></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -