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

📄 modbus_tcp.c

📁 linux 平台, modbus tcp 协议的简单实现.
💻 C
字号:
/******************************************************************************
 *
 * Copyright (c) 2008 Shanghai IS Software
 *
 * All rights reserved
 *
 * $Revision$
 *
 * $LastChangedBy$
 *1. lcj
 *
 * $LastChangedData$
 * 2008/09/25
 *
 * Description: modbus tcp server
 *
 * Revision History:
 * 2008/09/18 14:33 by lcj
 * #1.created
 *
 *****************************************************************************/
#include "md/md_manager.h"
#include "md/md_info.h"
#include "md/md_reg.h"

//#define DEBUG
#define MODBUS_TCP_LEN		12
#define MODBUS_TCP_HEAD	6
#define PORT					0x00
#define ADDR 				0x01

#include "modbus_tcp/modbus_tcp.h"

#ifdef DEBUG
#define pr_debug(fmt,arg...) \
		printf(fmt,##arg)
#else
#define pr_debug(fmt,arg...) \
		NULL
#endif

/**
*	read modbus register value .
*
**/
int  get_value(unsigned char *temp,unsigned char *buff_data)
{
	int result,i,j;
	MD_info* info;
	MD_reg_info *reg_info;
	int port = PORT;
	int addr = buff_data[MODBUS_TCP_LEN - 6];
	unsigned short start_addr;
	unsigned short num;
	unsigned short data[32];
	unsigned char *p = temp;

	memset(data,0,sizeof(data));
	
	start_addr = (unsigned short)(MAKEWORD(buff_data[MODBUS_TCP_LEN - 4],buff_data[MODBUS_TCP_LEN - 3]));
	num	= (unsigned short)(MAKEWORD(buff_data[MODBUS_TCP_LEN - 2],buff_data[MODBUS_TCP_LEN - 1]));

	
	pr_debug("\naddr = %d,num = %d\n",start_addr,num);

	result = init_MD_manager(2, 5, 500);
	if(result)
	{
		info = get_MD_info(port,addr);
		if(info)
		{
			if ( num > 0x01 )
				get_MD_regs_value(info,start_addr+1,num,(short *)data);
			else 
				get_MD_reg_value(info,start_addr+1,(short *)&data[0]);
		
		}
	}

	
	for ( j = 0, i = 0; i < num; i++,j+=2)
	{
		p[j] = (data[i] & 0xff00) >> 8;
		p[j+1] = data[i] & 0x00ff;
	}
	
	return 0;
	
}


/**
*	send tcp data
* 
**/
void sendframe(int fd,unsigned char *buf,int size)
{
	int i,n,len;
	unsigned char *p = buf;
	unsigned char buff[32];

	pr_debug("Send Date:");
	for ( i = 0; i < size; i++ )
		pr_debug("[%d]",buf[i]);

	
	n = send(fd,buf,size,0);
	if ( n < 0 || n > size )	
	{
		
		pr_debug("writen error!\n");
		
		exit(0);
	}
	return;
}

/**
*	parse the recv tcp data;
*
**/
int parseframe(int fd,unsigned char *buf_data )
{
	int ret,flag = 0;
	int i,j;
	unsigned char ch[16];
	unsigned char  tmp[MAX_RX] ,rx_buf[MAX_RX];
	unsigned char *p = rx_buf;
	int size;

	
	for ( i = 0; i < MODBUS_TCP_HEAD-1; i++ ) 
	{
		rx_buf[i] = buf_data[i];
		
	}
	
	rx_buf[6] = buf_data[MODBUS_TCP_LEN - 6]; // dev_addr
	rx_buf[7] = buf_data[MODBUS_TCP_LEN - 5]; // command
	rx_buf[8] = ((unsigned short)MAKEWORD(buf_data[MODBUS_TCP_LEN - 2],buf_data[MODBUS_TCP_LEN - 1]))*2; // num
	rx_buf[5] = 3 + rx_buf[8]; // len

	for ( i = 0; i < 9; i++ )
		p++;

	switch(buf_data[MODBUS_TCP_LEN - 5])
	{
		case 0x03:
			ret = get_value(tmp,buf_data);
			if ( ret < 0 )
			{
				
				pr_debug("Get Value error!\n");
				
				exit(-1);
			}
			flag = 1;
			break;
		case 0x06:
			
			pr_debug("command is write!\n");
		
			break;
		default:
			
			pr_debug("command error!\n");
			
			break;
	}

	if ( flag == 0 )
	{	
		
		pr_debug("commmand is not supply!\n");
	
		exit(0);
	}
	
	for ( i = 0,j = 9; i < rx_buf[8];i++,j++ )
	{
		rx_buf[j] = tmp[i];
	
	}
	
	size =  rx_buf[8] + 9;

	sendframe(fd,rx_buf,size);
	
	return 0;
}

 /**
 *	 recv the tcp client data.
 *
 **/
 int do_it(int connfd)
 {
 	int i,temp;
	int fd = connfd;
	ssize_t n;
	unsigned char buf_top[MODBUS_TCP_HEAD];
	unsigned char buf_data[MAXLINE];

	while(1)
	{
		n = recv(fd,buf_data,MODBUS_TCP_LEN,0);
		if ( n < 0 || n > MODBUS_TCP_LEN )
		{
			#ifdef DEBUG
			fprintf(stderr,"read error!\n");
			#endif
			return -1;
		}

		
		pr_debug("Recv TCP Data:");
		for ( i = 0; i < MODBUS_TCP_LEN; i++ )
			pr_debug("[%d]",buf_data[i]);
		pr_debug("\n");
	
		
		if ((MAKEWORD(buf_data[2],buf_data[3]) != 0) || (MAKEWORD(buf_data[4],buf_data[5])) > 0xff )
		{
		
			pr_debug("modbus tcp data error!\n");
	
			return -1;
		}
		
		parseframe(fd,buf_data);

	}
	return ;
}


void sig_chld(int signo)
{
	pid_t 	pid;
	int 	stat;

	while ((pid = waitpid(-1,&stat,WNOHANG)) > 0)
	{
		pr_debug("child %d terminated\n",pid);
	}
	return;
}

int main(int argc, char **argv)
{
	int listenfd,connfd;
	pid_t childpid;
	socklen_t	clilen;
	struct sockaddr_in	cliaddr,servaddr;
	
	listenfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if ( listenfd < 0 )
	{
		
		pr_debug("socket error!\n");
		
		exit(0);
	}

	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(MODBUS_TCP_PORT);
	
	bind(listenfd,(SA *)&servaddr,sizeof(servaddr));

	listen(listenfd,LISTENQ);

	signal(SIGCHLD,sig_chld);

	while(1)
	{
			clilen = sizeof(cliaddr);
			if ((connfd = accept(listenfd,(SA *)&cliaddr,&clilen)) < 0 )
			{					
				if ( errno == EINTR )
				{
					continue;
				}
				else
				{
					pr_debug(" accept error!\n");
				}
			}
			
			if ( 0 == (childpid = fork())) // child process
			{
				close(listenfd);
							
				do_it(connfd);

			}
				
			close(connfd);
		}
		return 0;
}

 

⌨️ 快捷键说明

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