⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus_tcp_c.c

📁 linux下的modbus协议,很好用,欢迎大家下载,在国外网站上获得的
💻 C
📖 第 1 页 / 共 2 页
字号:




/************************************************************************

	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 + -