enc28j60.c

来自「本附件为嵌入式Web的相关资料」· C语言 代码 · 共 1,923 行 · 第 1/4 页

C
1,923
字号
		MACGetArray(DataBuffer, ChunkLen);

		len -= ChunkLen;

		// Take care of a last odd numbered data byte
		if(((WORD_VAL*)&ChunkLen)->bits.b0)
		{
			DataBuffer[ChunkLen] = 0x00;
			ChunkLen++;
		}

		// Calculate the checksum over this chunk
		DataPtr = (WORD*)&DataBuffer[0];
		while(ChunkLen)
		{
			Checksum.Val += *DataPtr++;
			ChunkLen -= 2;
		}
	}

	// Restore old read pointer location
	WriteReg(ERDPTL, Start.v[0]);
	WriteReg(ERDPTH, Start.v[1]);
	
	// Do an end-around carry (one's complement arrithmatic)
	Checksum.Val = (DWORD)Checksum.w[0] + (DWORD)Checksum.w[1];

	// Do another end-around carry in case if the prior add 
	// caused a carry out
	Checksum.w[0] += Checksum.w[1];

	// Return the resulting checksum
	return ~Checksum.w[0];
}


/******************************************************************************
 * Function:        void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           destAddr:	Destination address in the Ethernet memory to 
 *								copy to.  If the MSb is set, the current EWRPT 
 *								value will be used instead.
 *					sourceAddr:	Source address to read from.  If the MSb is 
 *								set, the current ERDPT value will be used 
 *								instead.
 *					len:		Number of bytes to copy
 *
 * Output:          Byte read from the ENC28J60's RAM
 *
 * Side Effects:    None
 *
 * Overview:        Bytes are asynchrnously transfered within the buffer.  Call 
 *					MACIsMemCopyDone() to see when the transfer is complete.  
 *
 * Note:            If a prior transfer is already in progress prior to 
 *					calling this function, this function will block until it 
 *					can start this transfer.
 *
 *					If a negative value is used for the sourceAddr or destAddr 
 *					parameters, then that pointer will get updated with the 
 *					next address after the read or write.
 *****************************************************************************/
void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
{
	WORD_VAL ReadSave, WriteSave;
	BOOL UpdateWritePointer = FALSE;
	BOOL UpdateReadPointer = FALSE;

	if(((WORD_VAL*)&destAddr)->bits.b15)
	{
		UpdateWritePointer = TRUE;
		((WORD_VAL*)&destAddr)->v[0] = ReadETHReg(EWRPTL).Val;
		((WORD_VAL*)&destAddr)->v[1] = ReadETHReg(EWRPTH).Val;
	}
	if(((WORD_VAL*)&sourceAddr)->bits.b15)
	{
		UpdateReadPointer = TRUE;
		((WORD_VAL*)&sourceAddr)->v[0] = ReadETHReg(ERDPTL).Val;
		((WORD_VAL*)&sourceAddr)->v[1] = ReadETHReg(ERDPTH).Val;
	}

	// Handle special conditions where len == 0 or len == 1
	// The DMA module is not capable of handling those corner cases
	if(len <= 1u)
	{
		if(!UpdateReadPointer)
		{
			ReadSave.v[0] = ReadETHReg(ERDPTL).Val;
			ReadSave.v[1] = ReadETHReg(ERDPTH).Val;
		}
		if(!UpdateWritePointer)
		{
			WriteSave.v[0] = ReadETHReg(EWRPTL).Val;
			WriteSave.v[1] = ReadETHReg(EWRPTH).Val;
		}
		WriteReg(ERDPTL, ((WORD_VAL*)&sourceAddr)->v[0]);
		WriteReg(ERDPTH, ((WORD_VAL*)&sourceAddr)->v[1]);
		WriteReg(EWRPTL, ((WORD_VAL*)&destAddr)->v[0]);
		WriteReg(EWRPTH, ((WORD_VAL*)&destAddr)->v[1]);
		while(len--)
			MACPut(MACGet());
		if(!UpdateReadPointer)
		{
			WriteReg(ERDPTL, ReadSave.v[0]);
			WriteReg(ERDPTH, ReadSave.v[1]);
		}
		if(!UpdateWritePointer)
		{
			WriteReg(EWRPTL, WriteSave.v[0]);
			WriteReg(EWRPTH, WriteSave.v[1]);
		}
	}
	else
	{
		if(UpdateWritePointer)
		{
			WriteSave.Val = destAddr + len;
			WriteReg(EWRPTL, WriteSave.v[0]);
			WriteReg(EWRPTH, WriteSave.v[1]);
		}
		len += sourceAddr - 1;
		while(ReadETHReg(ECON1).ECON1bits.DMAST);
		WriteReg(EDMASTL, ((WORD_VAL*)&sourceAddr)->v[0]);
		WriteReg(EDMASTH, ((WORD_VAL*)&sourceAddr)->v[1]);
		WriteReg(EDMADSTL, ((WORD_VAL*)&destAddr)->v[0]);
		WriteReg(EDMADSTH, ((WORD_VAL*)&destAddr)->v[1]);
		if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
			len -= RXSIZE;
		WriteReg(EDMANDL, ((WORD_VAL*)&len)->v[0]);
		WriteReg(EDMANDH, ((WORD_VAL*)&len)->v[1]);
		BFCReg(ECON1, ECON1_CSUMEN);
		BFSReg(ECON1, ECON1_DMAST);
		if(UpdateReadPointer)
		{
			len++;
			if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
				len -= RXSIZE;
			WriteReg(ERDPTL, ((WORD_VAL*)&len)->v[0]);
			WriteReg(ERDPTH, ((WORD_VAL*)&len)->v[1]);
		}
	}
}

BOOL MACIsMemCopyDone(void)
{
	return !ReadETHReg(ECON1).ECON1bits.DMAST;
}


/******************************************************************************
 * Function:        BYTE MACGet()
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					ERDPT must point to the place to read from.
 *
 * Input:           None
 *
 * Output:          Byte read from the ENC28J60's RAM
 *
 * Side Effects:    None
 *
 * Overview:        MACGet returns the byte pointed to by ERDPT and 
 *					increments ERDPT so MACGet() can be called again.  The 
 *					increment will follow the receive buffer wrapping boundary.
 *
 * Note:            None
 *****************************************************************************/
BYTE MACGet()
{
    BYTE data;

    ENC_CS_IO = 0;
	data = ByteTransfer(RBM);
    data = ByteTransfer(0);
	ENC_CS_IO = 1;
    return data;
}//end MACGet


/******************************************************************************
 * Function:        WORD MACGetArray(BYTE *val, WORD len)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					ERDPT must point to the place to read from.
 *
 * Input:           *val: Pointer to storage location
 *					len:  Number of bytes to read from the data buffer.
 *
 * Output:          Byte(s) of data read from the data buffer.
 *
 * Side Effects:    None
 *
 * Overview:        Burst reads several sequential bytes from the data buffer 
 *					and places them into local memory.  With SPI burst support, 
 *					it performs much faster than multiple MACGet() calls.
 *					ERDPT is incremented after each byte, following the same 
 *					rules as MACGet().
 *
 * Note:            None
 *****************************************************************************/
WORD MACGetArray(BYTE *val, WORD len)
{
// Debug
#if defined(__18F8722) || \
	defined(__18F8627) || \
	defined(__18F8622) || \
	defined(__18F8572) || \
	defined(__18F6722) || \
	defined(__18F6627) || \
	defined(__18F6622) || \
	defined(__18F6527)
	WORD i;
	BYTE Dummy;

	i = len;
	Dummy = 0xFF;
	while(i--)
	{
		if(((BYTE_VAL*)&Dummy)->bits.b0)
		{
			// End bust operation
			ENC_CS_IO = 1;
			((BYTE_VAL*)&Dummy)->bits.b0 = 0;

			// Start the burst operation
			ENC_CS_IO = 0;
			ByteTransfer(RBM);
		}
		else
			Dummy = 0xFF;

		*val++ = ByteTransfer(0);
	}

	ENC_CS_IO = 1;
	
	return len;
#else
	WORD i;

	// Start the burst operation
	ENC_CS_IO = 0;
	ByteTransfer(RBM);
	i = 0;		

	// Read the data
	while(i<len)
	{
		*val++ = ByteTransfer(0);		
		i++;
	};

	// Terminate the burst operation
	ENC_CS_IO = 1;

	return i;
#endif
}//end MACGetArray


/******************************************************************************
 * Function:        void MACPut(BYTE val)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					EWRPT must point to the location to begin writing.
 *
 * Input:           Byte to write into the ENC28J60 buffer memory
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPut outputs the Write Buffer Memory opcode/constant 
 *					(8 bits) and data to write (8 bits) over the SPI.  
 *					EWRPT is incremented after the write.
 *
 * Note:            None
 *****************************************************************************/
void MACPut(BYTE val)
{

	ENC_CS_IO = 0;
	ByteTransfer(WBM);
	ByteTransfer(val);
	ENC_CS_IO = 1;
}//end MACPut


/******************************************************************************
 * Function:        void MACPutArray(BYTE *val, WORD len)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					EWRPT must point to the location to begin writing.
 *
 * Input:           *val: Pointer to source of bytes to copy.
 *					len:  Number of bytes to write to the data buffer.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPutArray writes several sequential bytes to the 
 *					ENC28J60 RAM.  It performs faster than multiple MACPut()
 *					calls.  EWRPT is incremented by len.
 *
 * Note:            None
 *****************************************************************************/
void MACPutArray(BYTE *val, WORD len)
{
// Debug
#if defined(__18F8722) || \
	defined(__18F8627) || \
	defined(__18F8622) || \
	defined(__18F8572) || \
	defined(__18F6722) || \
	defined(__18F6627) || \
	defined(__18F6622) || \
	defined(__18F6527)
	WORD i;
	BYTE Dummy;

	i = len;
	Dummy = 0xFF;
	while(i--)
	{
		if(((BYTE_VAL*)&Dummy)->bits.b0)
		{
			// End bust operation
			ENC_CS_IO = 1;
			((BYTE_VAL*)&Dummy)->bits.b0 = 0;

			// Start the burst operation
			ENC_CS_IO = 0;
			ByteTransfer(WBM);
		}
		else
			Dummy = 0xFF;

		ByteTransfer(*val++);
	}

	ENC_SPI_IF = 0;
	ENC_CS_IO = 1;
	
	return;
#else

	// Select the chip and send the proper opcode
	ENC_CS_IO = 0;
	ByteTransfer(WBM);

	// Send the data
	while(len)
	{
		ByteTransfer(*val++);
		len--;				// Decrement after writing to ENC_SSPBUF to increase speed
	};

	// Terminate the burst operation
	ENC_CS_IO = 1;
#endif
}//end MACPutArray


/******************************************************************************
 * Function:        static void SendSystemReset(void)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        SendSystemReset sends the System Reset SPI command to 
 *					the Ethernet controller.  It resets all register contents 
 *					(except for ECOCON) and returns the device to the power 
 *					on default state.
 *
 * Note:            None
 *****************************************************************************/
static void SendSystemReset(void)
{
	ENC_CS_IO = 0;
	ByteTransfer(SR);
	ENC_CS_IO = 1;
}//end SendSystemReset


/******************************************************************************
 * Function:        REG ReadETHReg(BYTE Address)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					Bank select bits must be set corresponding to the register 
 * 					to read from.
 *
 * Input:           5 bit address of the ETH control register to read from.
 *					  The top 3 bits must be 0.
 *
 * Output:          Byte read from the Ethernet controller's ETH register.
 *
 * Side Effects:    None
 *
 * Overview:        ReadETHReg sends the 8 bit RCR opcode/Address byte over 
 *					the SPI and then retrives the register contents in the 
 *					next 8 SPI clocks.
 *
 * Note:            This routine cannot be used to access MAC/MII or PHY 
 *					registers.  Use ReadMACReg() or ReadPHYReg() for that 
 *					purpose.  
 *****************************************************************************/
static REG ReadETHReg(BYTE Address)
{
	REG r;

	// Select the chip and send the Read Control Register opcode/address
	ENC_CS_IO = 0;

	ByteTransfer(RCR | Address);
	r.Val = ByteTransfer(0);	
	
	ENC_CS_IO = 1;

	return r;
}//end ReadETHReg


/******************************************************************************
 * Function:        REG ReadMACReg(BYTE Address)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					Bank select bits must be set corresponding to the register 
 * 					to read from.
 *
 * Input:           5 bit address of the MAC or MII register to read from.
 *					  The top 3 bits must be 0.
 *
 * Output:          Byte read from the Ethernet controller's MAC/MII register.
 *
 * Side Effects:    None
 *
 * Overview:        ReadMACReg sends the 8 bit RCR opcode/Address byte as well 
 *					as a dummy byte over the SPI and then retrives the 
 *					register contents in the last 8 SPI clocks.
 *
 * Note:            This routine cannot be used to access ETH or PHY 
 *					registers.  Use ReadETHReg() or ReadPHYReg() for that 
 *					purpose.  
 *****************************************************************************/
static REG ReadMACReg(BYTE Address)
{
	REG r;

	ENC_CS_IO = 0;
	ByteTransfer(RCR |  Address);
	ByteTransfer(0);	
	r.Val = ByteTransfer(0);
	
	ENC_CS_IO = 1;
	
	return r;
}//end ReadMACReg


/******************************************************************************
 * Function:        ReadPHYReg
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           Address of the PHY register to read from.
 *
 * Output:          16 bits of data read from the PHY register.
 *
 * Side Effects:    None
 *
 * Overview:        ReadPHYReg performs an MII read operation.  While in 
 *					progress, it simply polls the MII BUSY bit wasting time 
 *					(10.24us).

⌨️ 快捷键说明

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