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

📄 modbus_rtu.c

📁 linux下的modbus协议,很好用,欢迎大家下载,在国外网站上获得的
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	status = read_registers( function, slave, start_addr, count,						dest, dest_size, ttyfd );	return( status);}/************************************************************************	read_input_registers	Read the inputg registers in a slave and put the data into	an array. *************************************************************************/int read_input_registers( int slave, int start_addr, int count,				int *dest, int dest_size, int ttyfd ){	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, ttyfd );	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[2] * 2 ) && i < (raw_response_length / 2); 									i++ )		{			/* shift reg hi_byte to temp */			temp = data[ 3 + i *2 ] << 8;    			/* OR with lo_byte           */			temp = temp | data[ 4 + 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;	unsigned char packet[ REQUEST_QUERY_SIZE ];	packet[ 0 ] = slave;	packet[ 1 ] = function;	addr -= 1;	packet[ 2 ] = addr >> 8;	packet[ 3 ] = addr & 0x00FF;	packet[ 4 ] = value >> 8;	packet[ 5 ] = value & 0x00FF;	if( send_query( fd, packet, 6 ) > -1 )	{		status = preset_response( packet, fd );	}	else	{		status = PORT_FAILURE;	}	return( status );}/*************************************************************************	force_single_coil	turn on or off a single coil on the slave device*************************************************************************/int force_single_coil( 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(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 210int set_multiple_coils( int slave, int start_addr, int coil_count,			    int *data, int fd ){	int byte_count;	int i, bit, packet_size = 6;	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	}	packet[ 0 ] = slave;	packet[ 1 ] = 0x0F;	start_addr -= 1;	packet[ 2 ] = start_addr >> 8;	packet[ 3 ] = start_addr & 0x00FF;	packet[ 4 ] = coil_count >> 8;	packet[ 5 ] = coil_count & 0x00FF;	byte_count = (coil_count / 8) + 1;	packet[ 6 ] = 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;	}	if( send_query( fd, packet, ++packet_size ) > -1 )	{		status = preset_response( packet, fd );	}	else	{		status = PORT_FAILURE;	}	return( status );}/*************************************************************************	preset_multiple_registers	copy the values in an array to an array on the slave.***************************************************************************/int preset_multiple_registers( int slave, int start_addr, 				int reg_count, int *data, int fd ){	int byte_count, i, packet_size = 6;	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	}	packet[ 0 ] = slave;	packet[ 1 ] = 0x10;	start_addr -= 1;	packet[ 2 ] = start_addr >> 8;	packet[ 3 ] = start_addr & 0x00FF;	packet[ 4 ] = reg_count >> 8;	packet[ 5 ] = reg_count & 0x00FF;	byte_count = reg_count * 2;	packet[ 6 ] = byte_count;	for( i = 0; i < reg_count; i++ )	{		packet[ ++packet_size ] = data[ i ] >> 8;		packet[ ++packet_size ] = data[ i ] & 0x00FF;	}	if( send_query( fd, packet, ++packet_size ) > -1 )	{		status = preset_response( packet, fd );	}	else	{		status = PORT_FAILURE;	}	return( status );}/********************************************************************************************************* [  BEGIN:  crc ] ***********************************************************************************************************INPUTS:	buf   ->  Array containing message to be sent to controller.            	start ->  Start of loop in crc counter, usually 0.	cnt   ->  Amount of bytes in message being sent to controller/OUTPUTS:	temp  ->  Returns crc byte for message.COMMENTS:	This routine calculates the crc high and low byte of a message.	Note that this crc is only used for Modbus, not Modbus+ etc. ****************************************************************************/unsigned int crc(unsigned char *buf,int start,int cnt) {	int		i,j;	unsigned	temp,temp2,flag;	temp=0xFFFF;	for (i=start; i<cnt; i++)	{		temp=temp ^ buf[i];		for (j=1; j<=8; j++)		{			flag=temp & 0x0001;			temp=temp >> 1;			if (flag) temp=temp ^ 0xA001;		}	}	/* Reverse byte order. */	temp2=temp >> 8;	temp=(temp << 8) | temp2;	temp &= 0xFFFF;	return(temp);}/************************************************************************	set_up_comms	This function sets up a serial port for RTU communications to	modbus.**************************************************************************/int set_up_comms( char *device, int baud_i, char *parity ){	int ttyfd;	struct termios settings;	speed_t baud_rate;#ifdef DEBUG	fprintf( stderr, "opening %s\n", device );#endif	switch( baud_i )	{		case 110:			baud_rate = B110;			char_interval_timeout = TO_B110;			break;		case 300:			baud_rate = B300;			char_interval_timeout = TO_B300;			break;		case 600:			baud_rate = B600;			char_interval_timeout = TO_B600;			break;		case 1200:			baud_rate = B1200;			char_interval_timeout = TO_B1200;			break;		case 2400:			baud_rate = B2400;			char_interval_timeout = TO_B2400;			break;		case 4800:			baud_rate = B4800;			char_interval_timeout = TO_B4800;			break;		case 9600: case 0:			baud_rate = B9600;			char_interval_timeout = TO_B9600;			break;		case 19200:			baud_rate = B19200;			char_interval_timeout = TO_B19200;			break;		case 38400:			baud_rate = B38400;			char_interval_timeout = TO_B38400;			break;		case 57600:			baud_rate = B57600;			char_interval_timeout = TO_B57600;			break;		case 115200:			baud_rate = B115200;			char_interval_timeout = TO_B115200;			break;		default:			baud_rate = B9600;			char_interval_timeout = TO_B9600;			fprintf(stderr, "Unknown baud rate %d for %s.", baud_i, device);	}	if(( ttyfd = open( device,O_RDWR) ) < 0 )	{		fprintf( stderr, "Error opening device %s.   ", device );					fprintf( stderr, "Error no. %d \n",errno );		exit( 1 );	/* stop the program. This maybe should */				/* be a bit kinder but will do for now.*/	}#ifdef DEBUG	fprintf( stderr, "%s open\n", device );#endif	/* read your man page for the meaning of all this. # man termios */	/* Its a bit to involved to comment here                         */	cfsetispeed( &settings, baud_rate );/* Set the baud rate */	cfsetospeed( &settings, baud_rate );	settings.c_line = 0; 	settings.c_iflag |= IGNBRK;	settings.c_iflag |= IGNPAR;	settings.c_iflag &=~ PARMRK;	settings.c_iflag &=~ INPCK;	settings.c_iflag &=~ ISTRIP;	settings.c_iflag &=~ INLCR;	settings.c_iflag &=~ IGNCR;	settings.c_iflag &=~ ICRNL;	settings.c_iflag &=~ IUCLC;	settings.c_iflag &=~ IXON;	settings.c_iflag |= IXANY;	settings.c_iflag &=~ IXOFF;	settings.c_iflag &=~ IMAXBEL;	settings.c_oflag |= OPOST;	settings.c_oflag &=~ OLCUC;	settings.c_oflag &=~ ONLCR;	settings.c_oflag &=~ OCRNL;	settings.c_oflag |= ONOCR;	settings.c_oflag &=~ ONLRET;	settings.c_oflag &=~ OFILL;	settings.c_oflag &=~ OFDEL;	settings.c_cflag &=~ CSIZE;	settings.c_cflag |= CS8;	settings.c_cflag &=~ CSTOPB;	settings.c_cflag |= CREAD;	if( strncmp( parity, "none", 4 ) == 0 )	{		settings.c_cflag &=~ PARENB;		settings.c_cflag &=~ PARODD;	}	else	if( strncmp( parity, "even", 4 ) == 0 )	{		settings.c_cflag |= PARENB;		settings.c_cflag &=~ PARODD;	}	else	{		settings.c_cflag |= PARENB;		settings.c_cflag |= PARODD;	}	settings.c_cflag &=~ HUPCL;	settings.c_cflag |= CLOCAL;	settings.c_cflag &=~ CRTSCTS;	settings.c_lflag &=~ ISIG;	settings.c_lflag &=~ ICANON;	settings.c_lflag &=~ ECHO;	settings.c_lflag |= IEXTEN;	settings.c_cc[VMIN] = 0;	settings.c_cc[VTIME] = 0;	if( tcsetattr( ttyfd, TCSANOW, &settings ) < 0 )	{		fprintf( stderr, "tcsetattr failed\n");		exit( 1 );	}	return( ttyfd );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -