www.pudn.com > TCPmodbushy.rar > modbus.c


/****************************************************************************** 
 * Project     : t_box 
 * Module Name : modbus.C 
 * CPU Type    : C8051F340 
 * 
 * Description : 
 * 
 * History        Author     Version       Comment 
 * 2002.12.22       HY       V0.0         Original version 
 * 
 * Copyright (C) 2006 HY. All rights reserved. 
 ******************************************************************************/ 
#include  "o:\sysdef.h" 
#include  "modbus.h" 
 
#define	SndCommuBuf			CommuBuffer 
#define	RcvCommuBuf			CommuBuffer 
 
uchar xdata	CommuBuffer[ SndRcvBufferSize ]; 
uchar data	RcvCommuLen = 0; 
uchar data	SndCommuLen; 
uchar data	TransmittedLen; 
uchar  idata Commbufflen; 
bit data master_com_flag; 
bit data master_sendcommdata_flag; 
bit	data shield_flag = NO; 
/****************************************************************************** 
 *	功能: 通信中断服务程序 
 *	说明:receive data 
 ******************************************************************************/ 
void CommuRcv_INT( void )  
{ 
	master_sendcommdata_flag = NO; 
	//master_com_flag = NO; 
	/*only when wait receive,process receive data*/ 
	if(FrameDataReceived == WAIT_RECEIVE) 
	{ 
		uchar  data tmp; 
		if( RxByte( &tmp ) ) 
		{ 
			if(RcvCommuLen == 0) 
			{ 
				COM_LED = LED_ON; 
				if( (CurWorkState&MASTER_NOT_SLAVE) ) 
				{ 
					/*query station is or not in shield list*/ 
 
					FLASHADDRH = 0x06; 
					FLASHADDRL = tmp; 
					if( FLASHDATA != 0 ) 
//					if( ReadByteFromFlash( MASTER_SHIELD_ADDRESS + (uint)tmp ) != 0 ) 
						shield_flag = YES; 
					else 
						shield_flag = NO; 
				} 
			}				 
			RcvCommuBuf[ RcvCommuLen ] = tmp; 
			RcvCommuLen++; 
			if( RcvCommuLen >= SndRcvBufferSize ) 
				RcvCommuLen = SndRcvBufferSize - 1; 
			Timer5ms = COMM_RECEIVE_OUTTIME; 
		} 
		else 
		{ 
			if( !shield_flag ) 
				FrameDataReceived = END_RECEIVE; 
			else 
			{ 
				RcvCommuLen = 0; 
				Timer5ms = 0; 
			} 
			COM_LED = LED_OFF; 
		} 
	} 
} 
 
/****************************************************************************** 
 *	功能: 通信中断服务程序 
 *	说明:send data 
 ******************************************************************************/ 
void CommuSnd_INT( void ) 
{ 
	if( TransmittedLen < SndCommuLen ) 
	{ 
		TxByte( SndCommuBuf[ TransmittedLen ] );		/* 将 CommuBuf[ TredLen ] 装入发送寄存器 */ 
		TransmittedLen++; 
		COM_LED = LED_ON; 
	} 
	else 
	{ 
		//FrameDataReceived = wait_receive; 
		RstRcvCommu();	 
		COM_LED = LED_OFF;								/*send end,begine receive*/ 
//TransmittedLen = 0; 
	} 
} 
 
/****************************************************************************** 
 *	功能 :start send first  data 
 ******************************************************************************/ 
void StartTrans( void ) 
{ 
	StartTx(); 
	TransmittedLen = 1; 
	FrameDataReceived = WAIT_RECEIVE; 
	TxByte( SndCommuBuf[0]);				/* 将 CommuBuf[ 0 ] 装入发送寄存器 */ 
} 
/******************************************************************** 
 
********************************************************************/ 
void  RSTsend(uchar len,uchar *pd) 
{ 
	/*send data  on 485*/ 
	uint  tmp; 
	tmp = CRC(pd,pd+len); 
	pd +=len; 
	*pd = HIGH_BYTE( tmp ); 
	pd ++; 
	*pd = LOW_BYTE( tmp ); 
	SndCommuLen = len+2; 
/*	&SndCommuBuf[0] = pd;*/ 
	StartTrans(); 
} 
 
/****************************************************************************** 
 *	功能:  
 ******************************************************************************/ 
#pragma		NOAREGS 
void RstRcvCommu( void ) 
{ 
	RcvCommuLen = 0; 
	Timer5ms = 0; 
	FrameDataReceived = WAIT_RECEIVE; 
	StartRx(); 
} 
#pragma		AREGS 
 
/***************************************************************************** 
check receive data(CRC) 
******************************************************************************/ 
bit check_RCVdata() 
{ 
	if( ( RcvCommuLen > 2 )&&( RcvCommuLen <= SndRcvBufferSize ) ) 
	{ 
		if( ! ( ( RcvCommuBuf[ RcvCommuLen-2 ] == 0xA5 )&&( RcvCommuBuf[ RcvCommuLen-1 ] == 0x5A ) ) ) 
		{ 
			if( ! CRC_OK( RcvCommuBuf+RcvCommuLen-2, RcvCommuBuf, RcvCommuBuf+RcvCommuLen-2 ) ) 
			{				 
#ifdef   TESTDEBUG	 
test[11]++; 
#endif 
				RstRcvCommu(); 
				COM_ERROR_LED = LED_ON; 
				return(ERR); 
			} 
		} 
		COM_ERROR_LED = LED_OFF; 
		Commbufflen = RcvCommuLen; 
		return(OK); 
	} 
	else 
	{ 
#ifdef   TESTDEBUG	 
	test[0]++; 
#endif 
		RstRcvCommu(); 
		COM_ERROR_LED = LED_ON; 
		return(ERR); 
	} 
} 
 
/********************************************************************************* 
analyse normal modbus data( master) 
**********************************************************************************/ 
void  MODBUS_analyse() 
{ 
	//uchar tmp; 
	//Commbufflen = RcvCommuLen; 
	check_station_reply(); 
	if(RcvCommuBuf[0] == BROADCAST ) 
	{ 
		master_sendcommdata_flag = YES; 
		switch_message(); 
	} 
	else 
	{ 
		//tmp = RcvCommuBuf[0]; 
		master_sendcommdata_flag = YES; 
		check_ip(); 
	} 
} 
 
/******************************************************************************** 
check ip,if ip in list ,then send data ,if not ,then query ip 
*********************************************************************************/ 
void check_ip(void) 
{ 
	if( station_IP(RcvCommuBuf[0]) != ERR ) 
	{ 
		switch_message();			/*this port's IP have get,send data use tcp*/ 
	} 
	else 
	{ 
		queryIP(RcvCommuBuf[0]);	/*send broadcast to get the port's IP,*/ 
		master_com_flag = YES; 
	} 
} 
 
/******************************************************************************* 
switch normal modbus data to tcp modbus data  
********************************************************************************/ 
void	switch_message( void ) 
{ 
	if( CurWorkState & MASTER_NOT_SLAVE ) 
	{ 
		if(comm_send_protocol == TCP_PROTOCOL) 
		{ 
			if( IsHaveDataSending() != 0 )  //query data if or not finish sending  
			{ 
#ifdef   TESTDEBUG 
	test[10]++; 
#endif 
				return; 
			} 
		} 
		make_request_message((Commbufflen - 2), CommuBuffer);  
		master_com_flag = NO; 
		master_sendcommdata_flag = NO; 
	} 
	else 
	{ 
		make_response_message((RcvCommuLen - 2), CommuBuffer);	 
	} 
}