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

📄 modbus.c

📁 modbus rtu协议 linux 平台的实现.读取相关配置文件信息.通过串口发送数据.
💻 C
字号:
/******************************************************************************
 *
 * Copyright (c) 2008 Shanghai IS Software
 *
 * All rights reserved
 *
 * $Revision$
 *
 * $LastChangedBy$
 * 1. lcj
 *
 * $LastChangedData$ :
 * 2008/09/27 10:00
 *
 * Description: modbus RTU Protocol
 *
 * Revision History:
 * 2008/08/28 14:33 by lcj
 * #1.created
 *****************************************************************************/
#include "md/md_manager.h"
#include "md/md_info.h"
#include "md/md_reg.h"

#include "modbus_rtu/modbus.h"

//#define DEBUG
#define MAKEWORD(a,b)	((((a) << 8) + (b)) & 0xffff)

unsigned char rx_count,tx_count;

unsigned char caddrcode;
unsigned char command; 
unsigned char port_no;
char file_data[MAX_CONF_DATA][MAX_CONF];
char dev_name[MAX_DEV_NAME];
int speed;
int num;
int timeout;
int frequecy;
int dev_addr;

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



/**
*  open uart device .
*
**/
int OpenDev(char *dev)
{
	
	pr_debug("%s\n",dev);

	int fd = open(dev, O_RDWR | O_NONBLOCK  );

	if ( -1 == fd )
	{	
		
		pr_debug("Can't Open Serial Port!\n");
		
		return -1;
	}
	else 
		return fd;
}	

/**
* Uart initialize
* 
**/
void uart_init(struct modbus mod)
{
	
	set_speed(mod.fd,mod.speed);
	if ( set_parity(mod.fd,8,1,'E') == FALSE ) 
	{	
		
		pr_debug("Set Parity Error\n");
		
		close(mod.fd);
		exit(0);
	}
}

/**
* modbus rtu protocol data CRC
*
**/
unsigned short crc_check(unsigned char *snd,unsigned char num)
{
	unsigned char i,j;
	unsigned short c,crc = 0xFFFF;

	for ( i = 0; i < num; i++ )
	{
		c = snd[i] & 0x00FF;
		crc ^= c;
		
		for ( j = 0; j < 8; j++ )
		{
			if ( crc & 0x0001 )
			{
				crc >>= 1;
				crc ^= 0xA001;
			}
			else 
				crc >>= 1;
		}
	}
	return crc;
}

void delay(int time)
{
	int i,j;
	
	for ( i = 0; i < time; i++ )
		for ( j = 0; j < 0x5000; j++ ); 
}

void set_fl(int fd, int flag)
{
	int val;
	if ( (val = fcntl(fd,F_GETFL,0)) < 0)
	{	
		
		pr_debug("fcntl F_GETFL error!\n");
		
		close(fd);
		exit(0);
	}
	
	val |= flag;

	if (fcntl(fd,F_SETFL,val) < 0 )
	{
		
		pr_debug("fcntl F_SETFL error!\n");
		
		close(fd);
		exit(0);
	}
}

/**
*  send modbus data 
*
**/
void *do_modbus(void *arg)
{
	
	int ret,i,j,k;
	int oldtime,newtime;
	struct timeval tv;
	struct modbus *md = (struct modbus *)arg;

	gettimeofday(&tv,NULL);
	oldtime = tv.tv_usec;	

	for ( i = 0 ; md[i].count != 0; i++ )
		j = md[i].count;

	while ( 1 )
	{
		i = 0;
		gettimeofday(&tv,NULL);
		newtime = tv.tv_usec;
	
		while( i < j )
		{	
			if ( (newtime - oldtime) < 0 )
				newtime = newtime + 1000000;
			if ( (newtime - oldtime) / (md[i].time * 1000) != 0 )
			{
				md[i].send_flag = 1;
			}
			i++;
		}

		for ( i = 0; i < j; i++ )
		{
			if ( 1 == md[i].send_flag  )
			{
				uart_init(md[i]);
		
				set_fl(md[i].fd,O_RDWR);

				
				pr_debug("Send Data");
				for(k = 0; k < 8; k++ )
					pr_debug("[0x%x]",md[i].tx_buf[k]);
				pr_debug("\n");
			
				
				ret = write(md[i].fd,md[i].tx_buf,8);
				if ( ret < 0 )
				{
				
					pr_debug("send data error!\n");
					
					close(md[i].fd);
					exit(0);
				}
				
				md[i].send_flag = 0;

				if(recvframe(&md[i]))
				{
					ms_sleep(200);
					parseframe(md[i]);		
				}
			}	
		}
	}
}

/**
* recv modbus data
*
**/
int recvframe(struct modbus * md)
{
	int i,n,max_fd,len,j;
	fd_set input;
	struct timeval timeout;
	unsigned char buff[MAX_LEN];
	unsigned char *ptr = buff;
	unsigned short wcrc;

	FD_ZERO(&input);
	FD_SET(md->fd,&input);
	max_fd = md->fd + 1;
	rx_count = 0;

	#if 0
	
	len = md->tx_buf[5]*2+5;
	n = read(md->fd,md->rx_buf,len);
	if ( n != len )
	{
		printf("read data error!, errno = %d",errno);
		exit(0);
	}
	
	wcrc = MAKEWORD(md->rx_buf[len-1],md->rx_buf[len-2]);
	if (wcrc != crc_check(md->rx_buf,len -2))
	{
	#ifdef DEBUG
		fprintf(stderr,"Recv Data Err!\n");
	#endif
		close(md->fd);
		exit(0);
	}

		
	#else
	while (1) 
	{
		timeout.tv_sec = 0;
		timeout.tv_usec = 500000; // 100ms

		n = select(max_fd,&input,NULL,NULL,&timeout);
		if ( n < 0 )
		{
			
			pr_debug("select failed");
			
			break;
		}
		else if ( n == 0 )
		{	
			
			pr_debug("\nTIMEOUT");
		
			break;
		}
		else
		{
			ioctl(md->fd,FIONREAD,&len);
			if ( !len )
			{	
				#ifdef DEBUG
				fprintf(stderr,"Communication closed by server!\n");
				#endif
				close(md->fd);
				exit(0);
			}

			len = read(md->fd,ptr,len);
			if ( len < 0 ) 
			{
				
				pr_debug("read fail !\n");
				
				close(md->fd);
				exit(0);
			}
			
			rx_count += len;

			
			pr_debug("Recv Data:");
			
			for ( i = 0; i < len; i++ )
			{
				md->rx_buf[i] = buff[i];
				
				pr_debug("[%.2x] ",md->rx_buf[i]);
				
			}	
		}
	
	}

	
	if(!rx_count)
		return 0;

	wcrc = MAKEWORD(md->rx_buf[len-1],md->rx_buf[len-2]);
	if (wcrc != crc_check(md->rx_buf,len -2))
	{

		pr_debug("Recv Data Err!\n");

		return 0;

	}
	#endif
	return 1;
}


/**
* parse the recv of modbus data, and save to the share memory
*
**/
int parseframe(struct modbus md)
{
	
	unsigned short number;
	MD_reg_addr regs_addr[NUM_OF_REGS];
	MD_reg_value regs_value[NUM_OF_REGS];
	MD_info* info;
	int i,j,len;
	int result;
	int status = MD_STATUS_NORMAL;

	len = md.rx_buf[2] + 5;

	for ( i = 0; i < MAX_FOR_REG_ADDR; i++ )
		regs_addr[i] = (MD_reg_addr)i + 0x16; 

	for ( i = 0; i < MAX_FOR_REG_ADDR; i++ )
		regs_value[i] = 0;


	for (j = 4,i = 0; i < md.tx_buf[5]; i++,j+= 2 )
	{
		regs_value[i] = (MAKEWORD(md.rx_buf[j-1],md.rx_buf[j]))& 0xffff;
	}
	

	result = init_MD_manager(2, 5, 500);
	if ( result ) 
	{
		info = create_MD_info(md.name,md.port_no,md.tx_buf[0], NUM_OF_REGS/2,regs_addr);
		if(info)
		{
			if ( 0x01 == md.tx_buf[5])
				set_MD_reg_value(info,MAKEWORD(md.tx_buf[2],md.tx_buf[3])+ 1, MAKEWORD(md.rx_buf[len -4],md.rx_buf[len - 3]),status);
			else
				set_MD_regs_value(info,MAKEWORD(md.tx_buf[2],md.tx_buf[3])+ 1,md.tx_buf[5],regs_value,status);
		}
	
		#ifdef DEBUG
		print_MD_manager(get_MD_manager());
		#endif
	}	
	

	
}

/**
* trim the config file item
*
**/
char *trim(char *str)
{
	int len,i = 0;
	char *pRet = str;
	
	while ((' ' == (*pRet))||('\t' == (*pRet)))
	{
		pRet++;
	}
	
	len = strlen(pRet);
	while (len > 0)
	{
		if ((' ' == pRet[len-1]) || ('\t' == pRet[len-1]) || ('\n' == pRet[len-1])|| ('\r' == pRet[len-1]))
			len--;
		else 
		{
			break;
		}
	}
	*(pRet + len) = '\0';

	return pRet;
}


/**
* parse the config file item
*
**/
void do_string(char *str)
{
	int len,j,i = 0;
	char *pstr = str;
	char *delim = "[ ]\t ";
	char *p;

	len = strlen(str);
	if ((*pstr) !=  '[' || pstr[len - 1] != ']' )
	{
	
		pr_debug("config file error!\n");
	
		exit(0);
	}

	strcpy(file_data[i++],strtok(pstr,delim));

	while(p = strtok(NULL,delim))
	{
		strcpy(file_data[i++],p);
	}
	
	sscanf(file_data[0],"%x",&port_no);
	sscanf(file_data[1],"%d",&speed);
	strcpy(dev_name,file_data[2]);
	sscanf(file_data[3],"%x",&dev_addr);
	sscanf(file_data[4],"%d",&timeout);
	sscanf(file_data[5],"%x",&command);
	sscanf(file_data[6],"%x",&caddrcode);
	sscanf(file_data[7],"%x",&num);
	sscanf(file_data[8],"%d",&frequecy);
	
	return ;
}


int main(int argc ,char **argv)
{	
	int fd;
	int j, i = 0;
	FILE *pFILE;
	char linebuf[CONFIGMAXLINE];
	char *pLine;
	pthread_t ntid1,ntid2,ntid3;
	int err;
	int count = 0;
	unsigned short crc;
	struct modbus mod[MAX_CONF_ITEM];
	
	pFILE = fopen(CONFIG_FILE,"r");
	if ( NULL == pFILE )
	{
		
		pr_debug("fopen file error!\n");
		
		exit(0);
	}
	
	while ( pLine = fgets(linebuf,CONFIGMAXLINE-1,pFILE) ) // read config file data 
	{
		
		pLine = trim(pLine);
		if ( strlen(pLine) < 3) 
			continue;
		if ('#' == (*pLine))
			continue;	

		do_string(pLine);
		
		mod[count].tx_buf[0] = dev_addr; 
		mod[count].tx_buf[1] = command;
		mod[count].tx_buf[2] = 0;
		mod[count].tx_buf[3] = caddrcode;
		mod[count].tx_buf[4] = 0;
		mod[count].tx_buf[5] = num;
		crc = crc_check(mod[count].tx_buf, 6);
		mod[count].tx_buf[6] = crc & 0xff;
		mod[count].tx_buf[7] = crc/0x100;

		mod[count].time 	 = frequecy;
		mod[count].port_no	 = port_no;
		strcpy(mod[count].name ,dev_name);
		mod[count].fd = OpenDev("/dev/ttyS4");
		mod[count].send_flag = 0;
		mod[count].count = count + 1;
		mod[count].speed = speed;
		
		count++;
			
	}
	
	do_modbus(mod);
	
	return 0;
	
}

⌨️ 快捷键说明

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