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

📄 j1939_16.c

📁 CAN控制器2515的J1939库源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	#ifdef SPI_USE_ONLY_INLINE_DEFINITIONS
		WRITESPI( MCP_Send );
	#else
		WriteSPI( MCP_Send );
	#endif
	UNSELECT_MCP;

	#ifndef J1939_POLL_MCP
		// Clear the transmit interrupt flag
		SELECT_MCP;
		#ifdef SPI_USE_ONLY_INLINE_DEFINITIONS
			WRITESPI( MCP_BITMOD );
			WRITESPI( MCP_CANINTF );
			WRITESPI( MCP_Send<<2 );
			WRITESPI( 0 );
		#else
			WriteSPI( MCP_BITMOD );
			WriteSPI( MCP_CANINTF );
			WriteSPI( MCP_Send<<2 );
			WriteSPI( 0 );
		#endif
		UNSELECT_MCP;
	#endif

	// Put back PDUFormat the way it was in case somebody reuses the message.
//	MsgPtr->Msg.PDUFormat = oldSIDL;
}

/*********************************************************************
J1939_AddressClaimHandling

This routine is called either when the CA must claim its address on
the bus or another CA is trying to claim the same address on the bus and
we must either defend ourself or relinquish the address.  If the CA has
an address in the proprietary range of 0-127 or 248-253, it can take
the address immediately.

Parameters:	unsigned char	ADDRESS_CLAIM_RX indicates an Address
							Claim message has been received and this
							CA must either defend or give up its
							address.
							ADDRESS_CLAIM_TX indicates that the CA is
							initiating a claim to its address.
Return:		None
*********************************************************************/
#ifndef J1939_POLL_MCP
#pragma interrupt_level 0
#endif
void J1939_AddressClaimHandling( unsigned char Mode )
{
	// Get most of the message ready here, since it'll be very similar
	// for both messages to be sent.  Note that J1939_PF_ADDRESS_CLAIMED
	// is the same value as J1939_PF_CANNOT_CLAIM_ADDRESS.  We can't copy
	// the data yet because we might need to look at the old data.

	OneMessage.Msg.Priority = J1939_CONTROL_PRIORITY;
	OneMessage.Msg.PDUFormat = J1939_PF_ADDRESS_CLAIMED;
	OneMessage.Msg.DestinationAddress = J1939_GLOBAL_ADDRESS;
	OneMessage.Msg.DataLength = J1939_DATA_LENGTH;

	if (Mode == ADDRESS_CLAIM_TX)
		goto SendAddressClaim;

	if (OneMessage.Msg.SourceAddress != J1939_Address)
		return;

	if (CompareName( OneMessage.Msg.Data ) != -1) // Our CA_Name is not less
	{
		// Send Cannot Claim Address message
		CopyName();
		OneMessage.Msg.SourceAddress = J1939_NULL_ADDRESS;
		SendOneMessage( (J1939_TX_QUEUE_BANK J1939_MESSAGE *) &OneMessage );

		// Set up MCP filter 2 to receive messages sent to the global address
		SetAddressFilter( J1939_GLOBAL_ADDRESS );

		J1939_Flags.Flags.CannotClaimAddress = 1;
		J1939_Flags.Flags.WaitingForAddressClaimContention = 0;
		return;
	}

SendAddressClaim:
	// Send Address Claim message for CommandedAddress
	CopyName();
	OneMessage.Msg.SourceAddress = CommandedAddress;
	SendOneMessage( (J1939_TX_QUEUE_BANK J1939_MESSAGE *) &OneMessage );

	if (((CommandedAddress & 0x80) == 0) ||			// Addresses 0-127
		((CommandedAddress & 0xF8) == 0xF8))		// Addresses 248-253 (254,255 illegal)
	{
		J1939_Flags.Flags.CannotClaimAddress = 0;
		J1939_Address = CommandedAddress;

		// Set up MCP filter 2 to receive messages sent to this address
		SetAddressFilter( J1939_Address );
	}
	else
	{
		// We don't have a proprietary address, so we need to wait.
 		J1939_Flags.Flags.WaitingForAddressClaimContention = 1;
		ContentionWaitTime = 0;
	}
}

/*********************************************************************
J1939_DequeueMessage

This routine takes a message from the receive queue and places it in
the caller's buffer.  If there is no message to return, an appropriate
return code is returned.

Parameters:	J1939_MESSAGE *		Pointer to the caller's message buffer
Return:		RC_SUCCESS			Message dequeued successfully
			RC_QUEUEEMPTY		No messages to return
			RC_CANNOTRECEIVE	System cannot currently receive
								messages.  This will be returned only
								after the receive queue is empty.
*********************************************************************/
unsigned char J1939_DequeueMessage( J1939_USER_MSG_BANK J1939_MESSAGE *MsgPtr )
{
	unsigned char	rc = RC_SUCCESS;

	#ifndef J1939_POLL_MCP
		INTE = 0;
	#endif

	if (RXQueueCount == 0)
	{
		if (J1939_Flags.Flags.CannotClaimAddress)
			rc = RC_CANNOTRECEIVE;
		else
			rc = RC_QUEUEEMPTY;
	}
	else
	{
		*MsgPtr = RXQueue[RXHead];
		RXHead ++;
		if (RXHead >= J1939_RX_QUEUE_SIZE)
			RXHead = 0;
		RXQueueCount --;
	}

	#ifndef J1939_POLL_MCP
		INTE = 1;
	#endif

	return rc;
}

/*********************************************************************
J1939_EnqueueMessage

This routine takes a message from the caller's buffer and places it in
the transmit queue.  If the message cannot be queued or sent, an appropriate
return code is returned.  If interrupts are being used, then the
transmit interrupt is enabled after the message is queued.

Parameters:	J1939_MESSAGE *		Pointer to the caller's message buffer
Return:		RC_SUCCESS			Message dequeued successfully
			RC_QUEUEFULL		Transmit queue full; message not queued
			RC_CANNOTTRANSMIT	System cannot currently transmit
								messages.
*********************************************************************/
unsigned char J1939_EnqueueMessage( J1939_USER_MSG_BANK J1939_MESSAGE *MsgPtr )
{
	unsigned char	rc = RC_SUCCESS;

	#ifndef J1939_POLL_MCP
		INTE = 0;
	#endif

	if (J1939_Flags.Flags.CannotClaimAddress)
		rc = RC_CANNOTTRANSMIT;
	else
	{
		if ((TXQueueCount < J1939_TX_QUEUE_SIZE) ||
			 (J1939_OVERWRITE_TX_QUEUE == J1939_TRUE))
		{
			if (TXQueueCount < J1939_TX_QUEUE_SIZE)
			{
				TXQueueCount ++;
				TXTail ++;
				if (TXTail >= J1939_TX_QUEUE_SIZE)
					TXTail = 0;
			}
			TXQueue[TXTail] = *MsgPtr;

			#ifndef J1939_POLL_MCP
				// Enable the transmit interrupts on TXB0 and TXB1
				SELECT_MCP;
				#ifdef SPI_USE_ONLY_INLINE_DEFINITIONS
					WRITESPI( MCP_BITMOD );
					WRITESPI( MCP_CANINTE );
					WRITESPI( MCP_TX_INT );
					WRITESPI( MCP_TX01_INT );
				#else
					WriteSPI( MCP_BITMOD );
					WriteSPI( MCP_CANINTE );
					WriteSPI( MCP_TX_INT );
					WriteSPI( MCP_TX01_INT );
				#endif
				UNSELECT_MCP;
			#endif
		}
		else
			rc = RC_QUEUEFULL;

	}

	#ifndef J1939_POLL_MCP
		INTE = 1;
	#endif

	return rc;
}

/*********************************************************************
J1939_Initialization

This routine is called on system initialization.  It initializes
global variables, microcontroller peripherals and interrupts, and the
MCP2515.  It then starts the process of claiming the CA's address.

NOTE: This routine will NOT enable global interrupts.  The CA needs
to do that when it's ready.

Parameters:		None
Return:			None
*********************************************************************/
#pragma inline J1939_Initialization
void J1939_Initialization( void )
{
	unsigned char	i;
//	unsigned char	j;

	// Initialize global variables;
	J1939_Flags.FlagVal = 1;	// Cannot Claim Address, all other flags cleared.
	ContentionWaitTime = 0;
	CommandedAddress = J1939_Address = J1939_STARTING_ADDRESS;
	TXHead = 0;
	TXTail = 0xFF;
	TXQueueCount = 0;
	RXHead = 0;
	RXTail = 0xFF;
	RXQueueCount = 0;
	CA_Name[7] = J1939_CA_NAME7;
	CA_Name[6] = J1939_CA_NAME6;
	CA_Name[5] = J1939_CA_NAME5;
	CA_Name[4] = J1939_CA_NAME4;
	CA_Name[3] = J1939_CA_NAME3;
	CA_Name[2] = J1939_CA_NAME2;
	CA_Name[1] = J1939_CA_NAME1;
	CA_Name[0] = J1939_CA_NAME0;

	// Initialize the SPI peripheral.
	CloseSPI();
	OpenSPI( J1939_SPI_SPEED, J1939_SPI_MODE, J1939_SAMPLE );

	// Initialize the chip select pin
	J1939_CS_TRIS = 0;
	J1939_CS_PIN = 1;

	// Initialize the MCP2515 and put it into configuration mode automatically.
	SELECT_MCP;
	#ifdef SPI_USE_ONLY_INLINE_DEFINITIONS
		WRITESPI( MCP_RESET );
	#else
		WriteSPI( MCP_RESET );
	#endif
	UNSELECT_MCP;

	// Wait for the MCP to start up
	for (i=0; i<128; i++ );

	// Set up the MCP receive buffer 0 mask to receive broadcast messages.
	// Set up receive buffer 1 mask to receive messages sent to the
	// global address (or eventually us).  Set up bit timing as defined by
	// the CA, and set up interrupts on either receive buffer full.
	MCP_Write( MCP_RXM0SIDH, 0x07 );		// RXM0SIDH
	MCP_Write( MCP_RXM0SIDL, 0x80 );		// RXM0SIDL
	MCP_Write( MCP_RXM1EID8, 0xFF );		// RXM1EID8
	MCP_Write( MCP_CNF3, J1939_CNF3 );		// CNF3
	MCP_Write( MCP_CNF2, J1939_CNF2 );		// CNF2
	MCP_Write( MCP_CNF1, J1939_CNF1 );		// CNF1

	// Set all the RXB0 filters to accept only broadcast messages
	// (PF = 240-255).  Set all the RXB1 filters to accept only the
	// global address.  Once we get an address for the CA, we'll change
	// filter 2 to accept that address.
	MCP_Write( MCP_RXF0SIDH, 0x07 );					// RXF0SIDH
	MCP_Write( MCP_RXF0SIDL, 0x88 );					// RXF0SIDL
	MCP_Write( MCP_RXF1SIDH, 0x07 );					// RXF1SIDH
	MCP_Write( MCP_RXF1SIDL, 0x88 );					// RXF1SIDL
	MCP_Write( MCP_RXF2SIDL, 0x08 );					// RXF2SIDL
	MCP_Write( MCP_RXF2EID8, J1939_GLOBAL_ADDRESS );	// RXF2EID8
	MCP_Write( MCP_RXF3SIDL, 0x08 );					// RXF3SIDL
	MCP_Write( MCP_RXF3EID8, J1939_GLOBAL_ADDRESS );	// RXF3EID8
	MCP_Write( MCP_RXF4SIDL, 0x08 );					// RXF4SIDL
	MCP_Write( MCP_RXF4EID8, J1939_GLOBAL_ADDRESS );	// RXF4EID8
	MCP_Write( MCP_RXF5SIDL, 0x08 );					// RXF5SIDL
	MCP_Write( MCP_RXF5EID8, J1939_GLOBAL_ADDRESS );	// RXF5EID8

	// Put the MCP2515 into Normal Mode
	MCP_Write( MCP_CANCTRL, MODE_NORMAL + J1939_CLKOUT + J1939_CLKOUT_PS );

	// Clear out and deactivate the transmit and receive buffers.
	/*
    for (i = 0; i < 3; i++)
	{
		SELECT_MCP;
		#ifdef SPI_USE_ONLY_INLINE_DEFINITIONS
			WRITESPI( MCP_WRITE );
			WRITESPI( MCP_TXB0CTRL + i*16 );
    		for (j = 0; j < 14; j++)
        	    WRITESPI( 0x00 );
		#else
			WriteSPI( MCP_WRITE );
			WriteSPI( MCP_TXB0CTRL + i*16 );
    		for (j = 0; j < 14; j++)
        	    WriteSPI( 0x00 );
		#endif
		UNSELECT_MCP;
    }
	*/

	// Enable the MCP interrupt.  The caller must enable global
	// interrupts when ready.
	#ifndef J1939_POLL_MCP
		TRISB0 = 1;		// Set RB0 as an input.
		INTEDG = 0;  	// Interrupt on falling edge of RB0/INT pin
		INTE = 1;		// Enable the RB0/INT interrupt.
		MCP_Write( MCP_CANINTE, MCP_RX_INT );
	#endif

	// Start the process of claiming our address
	J1939_AddressClaimHandling( ADDRESS_CLAIM_TX );
}

/*********************************************************************
J1939_ISR

This function is called by the CA if it gets an interrupt and the INTF
flag is set.  First we'll clear the interrupt flag.  Then we'll call
the receive and transmit functions to process any received messages and
to transmit any messages in the transmit queue.

Parameters:	None

⌨️ 快捷键说明

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