enc28j60.c

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

C
1,923
字号
 *
 * Note:            None
 *****************************************************************************/
PHYREG ReadPHYReg(BYTE Register)
{
	PHYREG Result;

	// Set the right address and start the register read operation
	BankSel(MIREGADR);
	WriteReg((BYTE)MIREGADR, Register);
	WriteReg((BYTE)MICMD, MICMD_MIIRD);	

	// Loop to wait until the PHY register has been read through the MII
	// This requires 10.24us
	BankSel(MISTAT);
	while(ReadMACReg((BYTE)MISTAT).MISTATbits.BUSY);

	// Stop reading
	BankSel(MIREGADR);
	WriteReg((BYTE)MICMD, 0x00);	
	
	// Obtain results and return
	Result.VAL.v[0] = ReadMACReg((BYTE)MIRDL).Val;
	Result.VAL.v[1] = ReadMACReg((BYTE)MIRDH).Val;

	BankSel(ERDPTL);	// Return to Bank 0
	return Result;
}//end ReadPHYReg


/******************************************************************************
 * Function:        void WriteReg(BYTE Address, BYTE Data)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					Bank select bits must be set corresponding to the register 
 *					to modify.
 *
 * Input:           5 bit address of the ETH, MAC, or MII register to modify.  
 *					  The top 3 bits must be 0.  
 *					Byte to be written into the register.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        WriteReg sends the 8 bit WCR opcode/Address byte over the 
 *					SPI and then sends the data to write in the next 8 SPI 
 *					clocks.
 *
 * Note:            This routine is almost identical to the BFCReg() and 
 *					BFSReg() functions.  It is seperate to maximize speed.  
 *					Unlike the ReadETHReg/ReadMACReg functions, WriteReg() 
 *					can write to any ETH or MAC register.  Writing to PHY 
 *					registers must be accomplished with WritePHYReg().
 *****************************************************************************/
static void WriteReg(BYTE Address, BYTE Data)
{		
	BYTE Dummy;

	ENC_CS_IO = 0;
	ByteTransfer(WCR | Address);
	ByteTransfer(Data);
	ENC_CS_IO = 1;
}//end WriteReg


/******************************************************************************
 * Function:        void BFCReg(BYTE Address, BYTE Data)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					Bank select bits must be set corresponding to the register 
 *					  to modify.
 *
 * Input:           5 bit address of the register to modify.  The top 3 bits 
 *					  must be 0.  
 *					Byte to be used with the Bit Field Clear operation.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        BFCReg sends the 8 bit BFC opcode/Address byte over the 
 *					SPI and then sends the data in the next 8 SPI clocks.
 *
 * Note:            This routine is almost identical to the WriteReg() and 
 *					BFSReg() functions.  It is separate to maximize speed.  
 *					BFCReg() must only be used on ETH registers.
 *****************************************************************************/
static void BFCReg(BYTE Address, BYTE Data)
{
	BYTE Dummy;

	ENC_CS_IO = 0;
	ByteTransfer(BFC | Address);
	ByteTransfer(Data);
	ENC_CS_IO = 1;
}//end BFCReg


/******************************************************************************
 * Function:        void BFSReg(BYTE Address, BYTE Data)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * 					Bank select bits must be set corresponding to the register 
 *					to modify.
 *
 * Input:           5 bit address of the register to modify.  The top 3 bits 
 *					  must be 0.  
 *					Byte to be used with the Bit Field Set operation.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        BFSReg sends the 8 bit BFC opcode/Address byte over the 
 *					SPI and then sends the data in the next 8 SPI clocks.
 *
 * Note:            This routine is almost identical to the WriteReg() and 
 *					BFCReg() functions.  It is separate to maximize speed.
 *					BFSReg() must only be used on ETH registers.
 *****************************************************************************/
static void BFSReg(BYTE Address, BYTE Data)
{
	BYTE Dummy;

	ENC_CS_IO = 0;
	ByteTransfer(BFS | Address);
	ByteTransfer(Data);
	ENC_CS_IO = 1;
}//end BFSReg


/******************************************************************************
 * Function:        WritePHYReg
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           Address of the PHY register to write to.
 *					16 bits of data to write to PHY register.
 *
 * Output:          None
 *
 * Side Effects:    Alters bank bits to point to Bank 3
 *
 * Overview:        WritePHYReg performs an MII write operation.  While in 
 *					progress, it simply polls the MII BUSY bit wasting time.
 *
 * Note:            None
 *****************************************************************************/
void WritePHYReg(BYTE Register, WORD Data)
{
	// Write the register address
	BankSel(MIREGADR);
	WriteReg((BYTE)MIREGADR, Register);
	
	// Write the data
	// Order is important: write low byte first, high byte last
	WriteReg((BYTE)MIWRL, ((WORD_VAL*)&Data)->v[0]);	
	WriteReg((BYTE)MIWRH, ((WORD_VAL*)&Data)->v[1]);

	// Wait until the PHY register has been written
	BankSel(MISTAT);
	while(ReadMACReg((BYTE)MISTAT).MISTATbits.BUSY);

	BankSel(ERDPTL);	// Return to Bank 0
}//end WritePHYReg


/******************************************************************************
 * Function:        BankSel
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           Register address with the high byte containing the 2 bank 
 *					  select 2 bits.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        BankSel takes the high byte of a register address and 
 *					changes the bank select bits in ETHCON1 to match.
 *
 * Note:            None
 *****************************************************************************/
static void BankSel(WORD Register) 
{
	BFCReg(ECON1, ECON1_BSEL1 | ECON1_BSEL0);
	BFSReg(ECON1, ((WORD_VAL*)&Register)->v[1]);
}//end BankSel


/******************************************************************************
 * Function:        void MACPowerDown(void)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPowerDown puts the ENC28J60 in low power sleep mode. In
 *					sleep mode, no packets can be transmitted or received.  
 *					All MAC and PHY registers should not be accessed.
 *
 * Note:            If a packet is being transmitted while this function is 
 * 					called, this function will block until it is it complete.
 *					If anything is being received, it will be completed.
 *****************************************************************************/
void MACPowerDown(void)
{
	// Disable packet reception
	BFCReg(ECON1, ECON1_RXEN);

	// Make sure any last packet which was in-progress when RXEN was cleared 
	// is completed
	while(ReadETHReg(ESTAT).ESTATbits.RXBUSY);

	// If a packet is being transmitted, wait for it to finish
	while(ReadETHReg(ECON1).ECON1bits.TXRTS);
	
	// Enter sleep mode
	BFSReg(ECON2, ECON2_PWRSV);
}//end MACPowerDown


/******************************************************************************
 * Function:        void MACPowerUp(void)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPowerUp returns the ENC28J60 back to normal operation
 *					after a previous call to MACPowerDown().  Calling this 
 *					function when already powered up will have no effect.
 *
 * Note:            If a link partner is present, it will take 10s of 
 *					milliseconds before a new link will be established after
 *					waking up.  While not linked, packets which are 
 *					transmitted will most likely be lost.  MACIsLinked() can 
 *					be called to determine if a link is established.
 *****************************************************************************/
void MACPowerUp(void)
{	
	// Leave power down mode
	BFCReg(ECON2, ECON2_PWRSV);

	// Wait for the 300us Oscillator Startup Timer (OST) to time out.  This 
	// delay is required for the PHY module to return to an operational state.
	while(!ReadETHReg(ESTAT).ESTATbits.CLKRDY);
	
	// Enable packet reception
	BFSReg(ECON1, ECON1_RXEN);
}//end MACPowerUp


/******************************************************************************
 * Function:        void SetCLKOUT(BYTE NewConfig)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           NewConfig - 0x00: CLKOUT disabled (pin driven low)
 *								0x01: Divide by 1 (25 MHz)
 *								0x02: Divide by 2 (12.5 MHz)
 *								0x03: Divide by 3 (8.333333 MHz)
 *								0x04: Divide by 4 (6.25 MHz, POR default)
 *								0x05: Divide by 8 (3.125 MHz)
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Writes the value of NewConfig into the ECOCON register.  
 *					The CLKOUT pin will beginning outputting the new frequency
 *					immediately.
 *
 * Note:            
 *****************************************************************************/
void SetCLKOUT(BYTE NewConfig)
{	
	BankSel(ECOCON);
	WriteReg((BYTE)ECOCON, NewConfig);
	BankSel(ERDPTL);
}//end SetCLKOUT


/******************************************************************************
 * Function:        BYTE GetCLKOUT(void)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           None
 *
 * Output:          BYTE - 0x00: CLKOUT disabled (pin driven low)
 *						   0x01: Divide by 1 (25 MHz)
 *						   0x02: Divide by 2 (12.5 MHz)
 *						   0x03: Divide by 3 (8.333333 MHz)
 *						   0x04: Divide by 4 (6.25 MHz, POR default)
 *						   0x05: Divide by 8 (3.125 MHz)
 *						   0x06: Reserved
 *						   0x07: Reserved
 *
 * Side Effects:    None
 *
 * Overview:        Returns the current value of the ECOCON register.
 *
 * Note:            None
 *****************************************************************************/
BYTE GetCLKOUT(void)
{	
	BankSel(ECOCON);
	return ReadETHReg((BYTE)ECOCON).Val;
	BankSel(ERDPTL);
}//end GetCLKOUT


/******************************************************************************
 * Function:        void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           DestMACAddr: 6 byte group destination MAC address to allow 
 *								 through the Hash Table Filter
 *
 * Output:          Sets the appropriate bit in the EHT* registers to allow 
 *					packets sent to DestMACAddr to be received if the Hash 
 *					Table receive filter is enabled
 *
 * Side Effects:    None
 *
 * Overview:        Calculates a CRC-32 using polynomial 0x4C11DB7 and then, 
 *					using bits 28:23 of the CRC, sets the appropriate bit in 
 *					the EHT* registers
 *
 * Note:            This code is commented out to save code space on systems 
 *					that do not need this function.  Change the "#if 0" line 
 *					to "#if 1" to uncomment it.
 *****************************************************************************/
#if 0
void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
{
	DWORD_VAL CRC = {0xFFFFFFFF};
	BYTE HTRegister;
	BYTE i, j;

	// Calculate a CRC-32 over the 6 byte MAC address 
	// using polynomial 0x4C11DB7
	for(i = 0; i < sizeof(MAC_ADDR); i++)
	{
		BYTE  crcnext;
	
		// shift in 8 bits
		for(j = 0; j < 8; j++)
		{
			crcnext = 0;
			if(((BYTE_VAL*)&(CRC.v[3]))->bits.b7)
				crcnext = 1;
			crcnext ^= (((BYTE_VAL*)&DestMACAddr.v[i])->bits.b0);
	
			CRC.Val <<= 1;
			if(crcnext)
				CRC.Val ^= 0x4C11DB7;
			// next bit
			DestMACAddr.v[i] >>= 1;
		}
	}
	
	// CRC-32 calculated, now extract bits 28:23
	// Bits 25:23 define where within the Hash Table byte the bit needs to be set
	// Bits 28:26 define which of the 8 Hash Table bytes that bits 25:23 apply to
	i = CRC.v[3] & 0x1F;
	HTRegister = (i >> 2) + (BYTE)EHT0;
	i = (i << 1) & 0x06;
	((BYTE_VAL*)&i)->bits.b0 = ((BYTE_VAL*)&CRC.v[2])->bits.b7;
	
	// Set the proper bit in the Hash Table
	BankSel(EHT0);
	BFSReg(HTRegister, 1<<i);

	BankSel(ERDPTL);			// Return to Bank 0
}
#endif

//// GetRegs is a function for debugging purposes only.  It will read all 
//// registers and store them in the PIC's RAM so they can be viewed with 
//// the ICD2.
//REG Regs[4][32];
//void GetRegs(void)
//{
//	BYTE i;
//	
//	BankSel(0x000);
//	for(i=0; i<0x1A; i++)
//		Regs[0][i] = ReadETHReg(i);
//	for(i=0x1B; i<32; i++)
//		Regs[0][i] = ReadETHReg(i);
//
//	BankSel(0x100);
//	for(i=0; i<0x1A; i++)
//		Regs[1][i] = ReadETHReg(i);
//	for(i=0x1B; i<32; i++)
//		Regs[1][i] = ReadETHReg(i);
//
//	BankSel(0x200);
//	for(i=0; i<5; i++)
//		Regs[2][i] = ReadMACReg(i);
//	Regs[2][5] = ReadETHReg(i);
//	for(i=6; i<0x0F; i++)
//		Regs[2][i] = ReadMACReg(i);
//	Regs[2][0x0F] = ReadETHReg(i);
//	for(i=0x10; i<0x13; i++)
//		Regs[2][i] = ReadMACReg(i);
//	Regs[2][0x13] = ReadETHReg(i);
//	for(i=0x14; i<0x1A; i++)
//		Regs[2][i] = ReadMACReg(i);
//	for(i=0x1B; i<32; i++)
//		Regs[2][i] = ReadETHReg(i);
//
//	BankSel(0x300);
//	for(i=0; i<0x06; i++)
//		Regs[3][i] = ReadMACReg(i);
//	for(i=6; i<0x0A; i++)
//		Regs[3][i] = ReadETHReg(i);
//	Regs[3][0x0A] = ReadMACReg(i);
//	for(i=0x0B; i<0x1A; i++)
//		Regs[3][i] = ReadETHReg(i);
//	for(i=0x1B; i<32; i++)
//		Regs[3][i] = ReadETHReg(i);
//
//	Regs[0][0x1A].Val = 0;
//	Regs[1][0x1A].Val = 0;
//	Regs[2][0x1A].Val = 0;
//	Regs[3][0x1A].Val = 0;
//
//	BankSel(ERDPTL);
//
//	return;
//}

//// Get8KBMem is a function intended for debugging purposes.  It will read all 
//// Ethernet RAM and output it in hex out the UART
//void Get8KBMem(void)
//{
//	WORD_VAL i;
//	BYTE v;
//	WORD_VAL RDSave;
//
//	RDSave.v[0] = ReadETHReg(ERDPTL).Val;
//	RDSave.v[1] = ReadETHReg(ERDPTH).Val;
//
//	for(i.Val = 0; i.Val < 8192; i.Val++)
//	{	
//		WriteReg(ERDPTL, i.v[0]);
//		WriteReg(ERDPTH, i.v[1]);
//		v = MACGet();
//
//		putcUART('0');
//		while(BusyUART());
//		putcUART('x');
//		while(BusyUART());
//		putcUART(btohexa_high(v));
//		while(BusyUART());
//		putcUART(btohexa_low(v));
//		while(BusyUART());
//	}
//
//	WriteReg(ERDPTL, RDSave.v[0]);
//	WriteReg(ERDPTH, RDSave.v[1]);
//
//}

#endif //#if defined(ENC_CS_TRIS) && !defined(STACK_USE_SLIP)

⌨️ 快捷键说明

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