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

📄 enc28j60.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
📖 第 1 页 / 共 5 页
字号:
			TXSTATUS TXStatus;
			BYTE i;
			
			// Cancel the previous transmission if it has become stuck set
			BFCReg(ECON1, ECON1_TXRTS);

			// Save the current read pointer (controlled by application)
			BankSel(ERDPTL);
			ReadPtrSave.v[0] = ReadETHReg(ERDPTL).Val;
			ReadPtrSave.v[1] = ReadETHReg(ERDPTH).Val;

			// Get the location of the transmit status vector
			TXEnd.v[0] = ReadETHReg(ETXNDL).Val;
			TXEnd.v[1] = ReadETHReg(ETXNDH).Val;
			TXEnd.Val++;
			
			// Read the transmit status vector
			WriteReg(ERDPTL, TXEnd.v[0]);
			WriteReg(ERDPTH, TXEnd.v[1]);
			MACGetArray((BYTE*)&TXStatus, sizeof(TXStatus));

			// Implement retransmission if a late collision occured (this can 
			// happen on B5 when certain link pulses arrive at the same time 
			// as the transmission)
			for(i = 0; i < 16; i++)
			{
				if(ReadETHReg(EIR).EIRbits.TXERIF && TXStatus.bits.LateCollision)
				{
					// Reset the TX logic
					BFSReg(ECON1, ECON1_TXRST);
					BFCReg(ECON1, ECON1_TXRST);
					BFCReg(EIR, EIR_TXERIF | EIR_TXIF);

					// Transmit the packet again
					BFSReg(ECON1, ECON1_TXRTS);
					while(!(ReadETHReg(EIR).Val & (EIR_TXERIF | EIR_TXIF)));

					// Cancel the previous transmission if it has become stuck set
					BFCReg(ECON1, ECON1_TXRTS);

					// Read transmit status vector
					WriteReg(ERDPTL, TXEnd.v[0]);
					WriteReg(ERDPTH, TXEnd.v[1]);
					MACGetArray((BYTE*)&TXStatus, sizeof(TXStatus));
				}
				else
				{
					break;
				}
			}

			// Restore the current read pointer
			WriteReg(ERDPTL, ReadPtrSave.v[0]);
			WriteReg(ERDPTH, ReadPtrSave.v[1]);
		}
	}
}


/******************************************************************************
 * Function:        void MACSetRxBuffer(WORD offset)
 *
 * PreCondition:    A packet has been obtained by calling MACGetHeader() and 
 *					getting a TRUE result.
 *
 * Input:           offset: WORD specifying how many bytes beyond the Ethernet 
 *							header's type field to relocate the SPI read and 
 *							write pointers.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        SPI read and write pointers are updated.  All calls to 
 *					MACGet(), MACPut(), MACGetArray(), and MACPutArray(), 
 *					and various other functions will use these new values.
 *
 * Note:			RXSTOP must be statically defined as being > RXSTART for 
 *					this function to work correctly.  In other words, do not 
 *					define an RX buffer which spans the 0x1FFF->0x0000 memory
 *					boundary.
 *****************************************************************************/
void MACSetRxBuffer(WORD offset)
{
	WORD_VAL ReadPT;

	// Determine the address of the beginning of the entire packet
	// and adjust the address to the desired location
	ReadPT.Val = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
	
	// Since the receive buffer is circular, adjust if a wraparound is needed
	if ( ReadPT.Val > RXSTOP )
		ReadPT.Val -= RXSIZE;
	
	// Set the SPI read and write pointers to the new calculated value
	BankSel(ERDPTL);
	WriteReg(ERDPTL, ReadPT.v[0]);
	WriteReg(ERDPTH, ReadPT.v[1]);
	WriteReg(EWRPTL, ReadPT.v[0]);
	WriteReg(EWRPTH, ReadPT.v[1]);
}


/******************************************************************************
 * Function:        void MACSetTxBuffer(BUFFER buffer, WORD offset)
 *
 * PreCondition:    None
 *
 * Input:           buffer: BYTE specifying which transmit buffer to seek 
 *							within.  If MAC_TX_BUFFER_COUNT <= 1, this 
 *							parameter is not used.
 *					offset: WORD specifying how many bytes beyond the Ethernet 
 *							header's type field to relocate the SPI read and 
 *							write pointers.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        SPI read and write pointers are updated.  All calls to 
 *					MACGet(), MACPut(), MACGetArray(), and MACPutArray(), 
 *					and various other functions will use these new values.
 *
 * Note:			None
 *****************************************************************************/
void MACSetTxBuffer(BUFFER buffer, WORD offset)
{
    CurrentTxBuffer = buffer;

	// Calculate the proper address.  Since the TX memory area is not circular,
	// no wrapparound checks are necessary. +1 adjustment is needed because of 
	// the per packet control byte which preceeds the packet in the TX memory 
	// area.
#if MAC_TX_BUFFER_COUNT > 1
	offset += TxBuffers[buffer].StartAddress.Val + 1 + sizeof(ETHER_HEADER);
#else
	offset += TXSTART + 1 + sizeof(ETHER_HEADER);
#endif

	// Set the SPI read and write pointers to the new calculated value
	BankSel(EWRPTL);
	WriteReg(ERDPTL, ((WORD_VAL*)&offset)->v[0]);
	WriteReg(ERDPTH, ((WORD_VAL*)&offset)->v[1]);
	WriteReg(EWRPTL, ((WORD_VAL*)&offset)->v[0]);
	WriteReg(EWRPTH, ((WORD_VAL*)&offset)->v[1]);
}


// MACCalcRxChecksum() and MACCalcTxChecksum() use the DMA module to calculate
// checksums.  These two functions have been tested.
/******************************************************************************
 * Function:        WORD MACCalcRxChecksum(WORD offset, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           offset	- Number of bytes beyond the beginning of the 
 *							Ethernet data (first byte after the type field) 
 *							where the checksum should begin
 *					len		- Total number of bytes to include in the checksum
 *
 * Output:          16-bit checksum as defined by rfc 793.
 *
 * Side Effects:    None
 *
 * Overview:        This function performs a checksum calculation in the MAC
 *                  buffer itself using the hardware DMA module
 *
 * Note:            None
 *****************************************************************************/
WORD MACCalcRxChecksum(WORD offset, WORD len)
{
	WORD_VAL temp;

	// Add the offset requested by firmware plus the Ethernet header
	temp.Val = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
	if ( temp.Val > RXSTOP )		// Adjust value if a wrap is needed
	{
		temp.Val -= RXSIZE;
	}
	// Program the start address of the DMA
	BankSel(EDMASTL);
	WriteReg(EDMASTL, temp.v[0]);
	WriteReg(EDMASTH, temp.v[1]);

	// Calculate the end address, given the start address and len
	temp.Val += len-1;
	if ( temp.Val > RXSTOP )		// Adjust value if a wrap is needed
	{
		temp.Val -= RXSIZE;
	}
	// Program the end address of the DMA
	WriteReg(EDMANDL, temp.v[0]);
	WriteReg(EDMANDH, temp.v[1]);
	
	// Calculate the checksum using the DMA device
	BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);

	// Swap endianness and return
	temp.v[1] = ReadETHReg(EDMACSL).Val;
	temp.v[0] = ReadETHReg(EDMACSH).Val;

	return temp.Val;
}


/******************************************************************************
 * Function:        WORD MACCalcTxChecksum(WORD offset, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           offset	- Number of bytes beyond the beginning of the 
 *							Ethernet data (first byte after the type field) 
 *							where the checksum should begin
 *					len		- Total number of bytes to include in the checksum
 *
 * Output:          16-bit checksum as defined by rfc 793.
 *
 * Side Effects:    None
 *
 * Overview:        This function performs a checksum calculation in the MAC
 *                  buffer itself using the hardware DMA module
 *
 * Note:            None
 *****************************************************************************/
WORD MACCalcTxChecksum(WORD offset, WORD len)
{
	WORD_VAL temp;

	// Program the start address of the DMA, after adjusting for the Ethernet 
	// header
#if MAC_TX_BUFFER_COUNT > 1
	temp.Val = TxBuffers[CurrentTxBuffer].StartAddress.Val + sizeof(ETHER_HEADER)
				+ offset + 1;	// +1 needed to account for per packet control byte
#else
	temp.Val = TXSTART + sizeof(ETHER_HEADER)
				+ offset + 1;	// +1 needed to account for per packet control byte
#endif
	BankSel(EDMASTL);
	WriteReg(EDMASTL, temp.v[0]);
	WriteReg(EDMASTH, temp.v[1]);
	
	// Program the end address of the DMA.
	temp.Val += len-1;
	WriteReg(EDMANDL, temp.v[0]);
	WriteReg(EDMANDH, temp.v[1]);
	
    // Calcualte the checksum using the DMA device
	BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);

	// Swap endianness and return
	temp.v[1] = ReadETHReg(EDMACSL).Val;
	temp.v[0] = ReadETHReg(EDMACSH).Val;

	return temp.Val;
}


/******************************************************************************
 * Function:        WORD CalcIPBufferChecksum(WORD len)
 *
 * PreCondition:    Read buffer pointer set to starting of checksum data
 *
 * Input:           len: Total number of bytes to calculate the checksum over. 
 *						 The first byte included in the checksum is the byte 
 *						 pointed to by ERDPT, which is updated by calls to 
 *						 MACGet(), MACSetRxBuffer(), MACSetTxBuffer(), etc.
 *
 * Output:          16-bit checksum as defined by rfc 793.
 *
 * Side Effects:    None
 *
 * Overview:        This function performs a checksum calculation in the MAC
 *                  buffer itself.  The ENC28J60 has a hardware DMA module 
 *					which can calculate the checksum faster than software, so 
 *					this function replaces the CaclIPBufferChecksum() function 
 *					defined in the helpers.c file.  Through the use of 
 *					preprocessor defines, this replacement is automatic.
 *
 * Note:            This function works either in the RX buffer area or the TX
 *					buffer area.  No validation is done on the len parameter.
 *****************************************************************************/
WORD CalcIPBufferChecksum(WORD len)
{
	WORD_VAL temp;

	// Take care of special cases which the DMA cannot be used for
	if(len == 0u)
	{
		return 0xFFFF;
	}
	else if(len == 1u)
	{
		return ~(((WORD)MACGet())<<8);
	}
		

	// Set the DMA starting address to the SPI read pointer value
	BankSel(ERDPTL);
	temp.v[0] = ReadETHReg(ERDPTL).Val;
	temp.v[1] = ReadETHReg(ERDPTH).Val;
	WriteReg(EDMASTL, temp.v[0]);
	WriteReg(EDMASTH, temp.v[1]);
	
	// See if we are calculating a checksum within the RX buffer (where 
	// wrapping rules apply) or TX/unused area (where wrapping rules are 
	// not applied)
#if RXSTART == 0
	if(temp.Val <= RXSTOP)
#else
	if(temp.Val >= RXSTART && temp.Val <= RXSTOP)
#endif
	{
		// Calculate the DMA ending address given the starting address and len 
		// parameter.  The DMA will follow the receive buffer wrapping boundary.
		temp.Val += len-1;
		if(temp.Val > RXSTOP)
		{
			temp.Val -= RXSIZE;
		}
	}
	else
	{
		temp.Val += len-1;
	}	

	// Write the DMA end address
	WriteReg(EDMANDL, temp.v[0]);
	WriteReg(EDMANDH, temp.v[1]);
	
	// Begin the DMA checksum calculation and wait until it is finished
	BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);

	// Return the resulting good stuff
	temp.v[0] = ReadETHReg(EDMACSL).Val;
	temp.v[1] = ReadETHReg(EDMACSH).Val;
	return temp.Val;
}


/******************************************************************************
 * Function:        void MACCopyRxToTx(WORD RxOffset, WORD TxOffset, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           RxOffset: Offset in the RX buffer (0=first byte of 
 * 							  destination MAC address) to copy from.
 *					TxOffset: Offset in the TX buffer (0=first byte of
 *							  destination MAC address) to copy to.
 *					len:	  Number of bytes to copy
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        If the TX logic is transmitting a packet (ECON1.TXRTS is 
 *					set), the hardware will wait until it is finished.  Then, 
 *					the DMA module will copy the data from the receive buffer 
 *					to the transmit buffer.
 *
 * Note:            None
 *****************************************************************************/
// Remove this line if your application needs to use this 
// function.  This code has NOT been tested.
#if 0 
void MACCopyRxToTx(WORD RxOffset, WORD TxOffset, WORD len)
{
	WORD_VAL temp;

	temp.Val = CurrentPacketLocation.Val + RxOffset + sizeof(ENC_PREAMBLE);
	if ( temp.Val > RXSTOP )		// Adjust value if a wrap is needed
		temp.Val -= RXSIZE;

	BankSel(EDMASTL);
	WriteReg(EDMASTL, temp.v[0]);
	WriteReg(EDMASTH, temp.v[1]);

	temp.Val += len-1;
	if ( temp.Val > RXSTOP )		// Adjust value if a wrap is needed
		temp.Val -= RXSIZE;

	WriteReg(EDMANDL, temp.v[0]);
	WriteReg(EDMANDH, temp.v[1]);
	
	TxOffset += TXSTART+1;
	WriteReg(EDMADSTL, ((WORD_VAL*)&TxOffset)->v[0]);
	WriteReg(EDMADSTH, ((WORD_VAL*)&TxOffset)->v[1]);
	
	// Do the DMA Copy.  The DMA module will wait for TXRTS to become clear 
	// before starting the copy.
	BFCReg(ECON1, ECON1_CSUMEN);
	BFSReg(ECON1, ECON1_DMAST);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);
}

⌨️ 快捷键说明

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