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

📄 conn1.c

📁 关于devicenet的源代码。micorchip公司的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *
 * Microchip DeviceNet Stack (Explicit Messaging Connection Object Source)
 *
 *****************************************************************************
 * FileName:        conn1.c
 * Dependencies:    
 * Processor:       PIC18F with CAN
 * Compiler:       	C18 02.20.00 or higher
 * Linker:          MPLINK 03.40.00 or higher
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the "Company") is intended and supplied to you, the Company's
 * customer, for use solely and exclusively with products manufactured
 * by the Company. 
 *
 * The software is owned by the Company and/or its supplier, and is 
 * protected under applicable copyright laws. All rights are reserved. 
 * Any use in violation of the foregoing restrictions may subject the 
 * user to criminal sanctions under applicable laws, as well as to 
 * civil liability for the breach of the terms and conditions of this 
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, 
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * This file contains Explicit messaging support for the Connection Object 
 * described in Section 5-4 and Chapter 7 of Volume 1 of the DeviceNet 
 * specification.
 * 
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Ross Fosler			04/28/03	...	
 * 
 *****************************************************************************/

#include	"dnet.def"			// Global definitions file

#include 	"typedefs.h"

#include	"conn.h"			// Connection prototypes and symbols

#include	"services.h"		// Service codes
#include	"errors.h"			// Error codes
#include	"class.h"			// Class codes

#include	"route.h"			// Global symbols defined by the router
#include	"dnet.h"			// DeviceNet prototypes and symbols
#include	"frag.h"			// Fragmentation control

#include	"CAN.h"				// CAN driver


#define		_FRAG_SUCCESS	0
#define		_FRAG_TOO_MUCH	1





#define		RXFLAG_FIRST_FRAG		b0
#define		TXFLAG_SEND_ACK			b0
#define		TXFLAG_ACK_STAT			b1
#define		TXFLAG_TX_START			b2
#define		TXFLAG_TX_TIMER_EN		b3
#define		TXFLAG_TX_AGAIN			b4
#define		TXFLAG_TX_FIN			b5



#pragma 	udata
/*********************************************************************
 * Connection related variables
 ********************************************************************/
CONN_EXPL 		uConn1;

unsigned char	uConn1RxBuffer[CONN_EXPLICIT_RX_SIZE];
unsigned char	uConn1TxBuffer[CONN_EXPLICIT_TX_SIZE];



/*********************************************************************
 * Function:        unsigned char _Conn1Create(void)
 *
 * PreCondition:    none
 *
 * Input:       	none	
 *                  
 * Output:      	handle to connection
 *
 * Side Effects:    none
 *
 * Overview:        Returns a handle to the connection 
 *
 * Note:            none
 ********************************************************************/
unsigned char _Conn1Create(void)
{
	//Initialize the connection attributes
	uConn1.attrib.state = _STATE_ESTABLISHED;
	uConn1.attrib.produced_cid.bytes.MSB = uDNet.MACID | 0x80;
	uConn1.attrib.produced_cid.bytes.LSB = 0x60;
	uConn1.attrib.consumed_cid.bytes.MSB = uDNet.MACID | 0x80; 
	uConn1.attrib.consumed_cid.bytes.LSB = 0x80;
	uConn1.attrib.expected_packet_rate.word = 2500;
	uConn1.attrib.wdt_action = _WDT_ACTION_DEFERRED;
	
	_establishFlags.bits.expl = 1;
	_existentFlags.bits.expl = 1;
	
	// Setup the pointer and other info for the receiving side
	uConn1.rx.pMsg = uConn1RxBuffer;
	uConn1.rx.lenMax = CONN_EXPLICIT_RX_SIZE;
	uConn1.rx.fragFlags.byte = 0;
	uConn1.rx.oldFrag = 0;
	
	// Setup the pointer and other info for the transmitting side
	uConn1.tx.pMsg = uConn1TxBuffer;
	uConn1.tx.lenMax = CONN_EXPLICIT_TX_SIZE;
	uConn1.tx.fragFlags.byte = 0;
	uConn1.tx.oldFrag = 0;

	// Put 10000 or (rate)x(4), whichever is greater
	uConn1.timer.word = (uConn1.attrib.expected_packet_rate.word << 2);
	if (uConn1.timer.word < 10000) uConn1.timer.word = 10000;
	
	// Set the time
	uConn1.ack_tmr.word = EXPLICIT_ACK_TIMER;		
			
	//Issue a request to start receiving the CID
	CANSetFilter(uConn1.attrib.consumed_cid.word);
	return (1);
}


/*********************************************************************
 * Function:        unsigned char _Conn1Close(void)
 *
 * PreCondition:    
 *
 * Input:       	none		
 *                  
 * Output:      	status of the close
 *
 * Side Effects:    
 *
 * Overview:        Closes the specified connection 
 *
 * Note:            None
 ********************************************************************/
unsigned char _Conn1Close(void)
{	
	// Transition to the non-existent state
	uConn1.attrib.state = _STATE_NON_EXISTENT;
	
	_establishFlags.bits.expl = 0;
	_existentFlags.bits.expl = 0;
	
	// Issue a request to the driver to stop receiving the message
	CANClrFilter(uConn1.attrib.consumed_cid.word);

	return(1);
}





/*********************************************************************
 * Function:        void _Conn1TimerEvent(void)
 *
 * PreCondition:    
 *
 * Input:       	none		
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        Update timer and process any timer events.
 *
 * Note:            None
 ********************************************************************/
void _Conn1TimerEvent(void)
{		
	// Process the watchdog if the packet rate is other than 0
	if (uConn1.attrib.expected_packet_rate.word)
	{
		// Adjust the time
		uConn1.timer.word -= TICK_RESOLUTION;

		// If the wdt expires then change the state of the connection
		if (uConn1.timer.word == 0) 
		{
			// Auto delete the connection
			if (uConn1.attrib.wdt_action == _WDT_ACTION_AUTO_DELETE)
			{ 
				uConn1.attrib.state = _STATE_NON_EXISTENT;
			}
			else 
			
			// Deferred delete (full release is determined outside 
			// of this instance)
			if (uConn1.attrib.wdt_action == _WDT_ACTION_DEFERRED) 
			{
				uConn1.attrib.state = _STATE_DEFERED_DELETE;
			}
		}
	}

#if	FRAGMENTATION_ACK
	// Process fragmentation timer for acknowledged transmission
	if (uConn1.tx.fragFlags.bits.TXFLAG_TX_TIMER_EN == 1)
	{
		// Adjust ack timer
		uConn1.ack_tmr.word -= TICK_RESOLUTION;

		// If the ack timer expires then change the frag state
		if (uConn1.ack_tmr.word == 0)
		{	
			// Disable the timer
			uConn1.tx.fragFlags.bits.TXFLAG_TX_TIMER_EN = 0;
			
			// Reset the time
			uConn1.ack_tmr.word = EXPLICIT_ACK_TIMER;

			// If a resend has been requested
			if (uConn1.tx.fragFlags.bits.TXFLAG_TX_AGAIN == 1)
			{
				// Kill the message
				// Reset the transmit state
				uConn1.tx.fragFlags.bits.TXFLAG_TX_START = 0;
				uConn1.tx.fragFlags.bits.TXFLAG_TX_FIN = 0;
				uConn1.tx.fragFlags.bits.TXFLAG_TX_AGAIN = 0;

				// Set flag indicating completion
				_txFinFlags.bits.expl = 1;
			}
			else
			{
				// Issue a resend
				uConn1.tx.fragFlags.bits.TXFLAG_TX_AGAIN = 1;
				_txFlag.bits.expl = 1;
			}
		}
	}
#endif
}




/*********************************************************************
 * Function:        void _Conn1RxEvent(void)
 *
 * PreCondition:    
 *
 * Input:       	none	
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        Process data for this connection.
 *
 * Note:            This event occures when data has been received
 *					for this connection instance.
 ********************************************************************/
void _Conn1RxEvent(void)
{
	BYTE header, service, frag, count, type, len;
	unsigned char *pRxData;

	// Set the size of classId depending on what has been specified
	#if (CLASS_WIDTH_16BIT)
	UINT classId;
	#else
	BYTE classId;
	#endif
	
	// Get the pointer to the buffer
	pRxData = CANGetRxDataPtr();
	len.byte = CANGetRxCnt();
	
	// Extract the header	
	header.byte = *pRxData; 
		
#if	FRAGMENTATION_ACK				
	// If fragmented
	if (header.bits.b7)
	{
		// Process only if there is sufficient data to process the connection
		if (len.byte > 2)
		{
			// Point to the frag byte and copy it
			pRxData++;
			frag.byte = *pRxData; 
			
			// Point to the service
			pRxData++; 
			
			// Get the fragment type and count
			type.byte = frag.byte & 0xC0;
			count.byte = frag.byte & 0x3F;
		
			// If the header MAC equals the allocated MasterMACID then 
			// process the message fragment	
			if (((header.byte ^ uDNet.AllocInfo.MasterMACID) & 0x3F) == 0)
			{			
				// Remember the header
				uConn1.rx.header = header.byte; 
					
				// Process the fragment
				switch (type.byte)
				{
					// Received first fragment
					case 0x00:
						// The first fragment must always have a frag byte of 0
						if (frag.byte == 0)
						{
							// Copy the fragment to the buffer
							CANGetRxDataTyp2(uConn1.rx.pMsg + 1);
							
							// Store the header
							*uConn1.rx.pMsg = header.byte;
				
							// Adjust the length minus the fragment control byte
							uConn1.rx.len = len.byte - 1;
												
							// Request to issue an ACK with status	
							uConn1.tx.fragFlags.bits.TXFLAG_SEND_ACK = 1;
							uConn1.tx.fragFlags.bits.TXFLAG_ACK_STAT = 0;
							_txFlag.bits.expl = 1;
											
							// Reset the old fragment
							uConn1.rx.oldFrag = 0;
				
							// Indicate the first fragment has been received
							uConn1.rx.fragFlags.bits.RXFLAG_FIRST_FRAG = 1;
						}
						break;
						
					// Received a middle or last fragment
					case 0x40:
					case 0x80:
						// If this frag is the same as the previous then re-ack
						if (uConn1.rx.oldFrag == frag.byte)
						{
							// Set the status & request the hardware to send the ACK
							uConn1.tx.fragFlags.bits.TXFLAG_SEND_ACK = 1;
							uConn1.tx.fragFlags.bits.TXFLAG_ACK_STAT = 0;
							_txFlag.bits.expl = 1;
						}
						else
					
						// Continue if the first fragment has been received
						if (uConn1.rx.fragFlags.bits.RXFLAG_FIRST_FRAG)
						{						
							// Process the current fragment
							if (((uConn1.rx.oldFrag + 1) & 0x3F) == count.byte)
							{
								// if the buffer is large enough
								if ((uConn1.rx.len + (len.byte - 1)) < uConn1.rx.lenMax)
								{
						
									// Copy this fragment to the buffer
									CANGetRxDataTyp2(uConn1.rx.pMsg + uConn1.rx.len);
					
									// Store the length minus the fragment control byte and header
									uConn1.rx.len += (len.byte - 2);
								
									// Save the current fragment information
									uConn1.rx.oldFrag = frag.byte;
									
									// If this the last fragment in the sequence
									if (type.byte == 0x80)
									{
										// Indicate message has been received
										_rxFlag.bits.expl = 1;
									}
								
									// Set the status & request the hardware to send the ACK				
									uConn1.tx.fragFlags.bits.TXFLAG_SEND_ACK = 1;
									uConn1.tx.fragFlags.bits.TXFLAG_ACK_STAT = 0;
									_txFlag.bits.expl = 1;
								}
							
								//else send an error ack indicating too much data		
								else
								{
									// Set the status & request the hardware to send the ACK				
									uConn1.tx.fragFlags.bits.TXFLAG_SEND_ACK = 1;
									uConn1.tx.fragFlags.bits.TXFLAG_ACK_STAT = 1;
									_txFlag.bits.expl = 1;
								
									// Reset to the initial state
									uConn1.rx.fragFlags.bits.RXFLAG_FIRST_FRAG = 0;
								}
							}
						
							// Toss the fragment and reset to the first state
							else
							{
								// Reset to the initial state
								uConn1.rx.fragFlags.bits.RXFLAG_FIRST_FRAG = 0;
							}
						}
					
						// Fragment not expected
						else
						{
							// Reset to the initial state	
							uConn1.rx.fragFlags.bits.RXFLAG_FIRST_FRAG = 0;	
						}
						break;
						
										
					// Received an ACK
					case 0xC0:
						// Process ack if expecting it
						if (uConn1.tx.fragFlags.bits.TXFLAG_TX_START == 1)
						{
							// Stop the acknowledge timer if it was running
							uConn1.tx.fragFlags.bits.TXFLAG_TX_TIMER_EN = 0;

							// Reset the retry flag if it was set
							uConn1.tx.fragFlags.bits.TXFLAG_TX_AGAIN = 0;

							// If the last transmission has been sent
							if (uConn1.tx.fragFlags.bits.TXFLAG_TX_FIN == 1)
							{
								// Reset the transmit state
								uConn1.tx.fragFlags.bits.TXFLAG_TX_START = 0;
								uConn1.tx.fragFlags.bits.TXFLAG_TX_FIN = 0;
							}
							else
							{
								// Start up the next transmission
								_txFlag.bits.expl = 1;
							}
						}
						break;
					}
							
							
							
				
				// Put the connection into the established state
				uConn1.attrib.state = _STATE_ESTABLISHED;
				_establishFlags.bits.expl = 1;
				
				// Reset the connection wdt
				uConn1.timer.word = uConn1.attrib.expected_packet_rate.word << 2;
			}
		}
	}
#else
	// If fragmented
	if (header.bits.b7)
	{
		// Process only if there is sufficient data to process the connection
		if (len.byte > 2)
		{
			// If the header MAC equals the allocated MasterMACID then 
			// process the message fragment	
			if (((header.byte ^ uDNet.AllocInfo.MasterMACID) & 0x3F) == 0)
			{
				// Request to issue an ACK with error status	
				uConn1.tx.fragFlags.bits.TXFLAG_SEND_ACK = 1;
				uConn1.tx.fragFlags.bits.TXFLAG_ACK_STAT = 1;
				_txFlag.bits.expl = 1;
			}
		}
	}
#endif

	// else process a non-fragmented message
	else
	{ 
		// Process only if there is sufficient data to process the connection
		if (len.byte > 1)
		{
			// Extract the service ID  
			service.byte = *(pRxData + 1);
		
			// If the header MAC equals the allocated MasterMACID or if the release
			// connection service is requested then process the message.
			// (refer to section 5-5.4.2)
			#if (CLASS_WIDTH_16BIT)
			classId.bytes.LSB = *(pRxData + 2);
			classId.bytes.MSB = *(pRxData + 3);	
			if (((classId.word == CLASS_DEVICENET) && (service.byte == SRVS_RELEASE_CONN)) ||
				(header.byte ^ uDNet.AllocInfo.MasterMACID & 0x3F) == 0)
			#else
			classId.byte = *(pRxData + 2);
			if (((classId.byte == CLASS_DEVICENET) && (service.byte == SRVS_RELEASE_CONN)) ||
				(header.byte ^ uDNet.AllocInfo.MasterMACID & 0x3F) == 0)
			#endif

⌨️ 快捷键说明

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