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

📄 enc28j60.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = RCR | Address;	// Send the Read Control Register opcode and 
							//   address.
	while(!ENC_SPI_IF);		// Wait until opcode/address is transmitted.
	r.Val = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = 0;				// Send a dummy byte 
	while(!ENC_SPI_IF);		// Wait for the dummy byte to be transmitted
	r.Val = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = 0;				// Send another dummy byte to receive the register 
							//   contents.
	while(!ENC_SPI_IF);		// Wait until register is received.
	r.Val = ENC_SSPBUF;
	ENC_SPI_IF = 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:    Alters bank bits to point to Bank 2
 *
 * Overview:        ReadPHYReg performs an MII read operation.  While in 
 *					progress, it simply polls the MII BUSY bit wasting time 
 *					(10.24us).
 *
 * 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;

	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;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = WCR | Address;	// Send the opcode and address.
	while(!ENC_SPI_IF);		// Wait until opcode/address is transmitted.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = Data;			// Send the byte to be writen.
	while(!ENC_SPI_IF);		// Wait until register is written.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	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;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = BFC | Address;	// Send the opcode and address.
	while(!ENC_SPI_IF);		// Wait until opcode/address is transmitted.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = Data;			// Send the byte to be writen.
	while(!ENC_SPI_IF);		// Wait until register is written.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	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;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = BFS | Address;	// Send the opcode and address.
	while(!ENC_SPI_IF);		// Wait until opcode/address is transmitted.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	ENC_SSPBUF = Data;			// Send the byte to be writen.
	while(!ENC_SPI_IF);		// Wait until register is written.
	Dummy = ENC_SSPBUF;
	ENC_SPI_IF = 0;
	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);
}//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:        static BOOL TestMemory(void) 
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           None
 *
 * Output:          TRUE if the memory tests have passed 
 *					FALSE if the BIST has detected a hardware fault
 *
 * Side Effects:    Alters the state of numerous control registers and all 
 *					RAM bytes.
 *
 * Overview:        The internal BIST and DMA modules are used to fill the 
 *					entire dual port memory and calculate a checksum of the 
 *					data stored within.  Address and Random fill modes are 
 *					used.
 *
 * Note:            For the Random Fill mode, the random number generator is
 *					seeded by the contents of the TMR0L PIC SFR.  If the timer
 *					is running, additional confidence that the memory is 
 *					working can be obtained by calling TestMemory multiple 
 *					times.
 *****************************************************************************/
#if defined(MAC_POWER_ON_TEST)
static BOOL TestMemory(void) 
{
	#define RANDOM_FILL		0b0000
	#define ADDRESS_FILL	0b0100
	#define PATTERN_SHIFT	0b1000
	
	WORD_VAL DMAChecksum, BISTChecksum;
	
	
	// Select Bank 0 and disable anything that could have been in progress
	WriteReg(ECON1, 0x00);
	
	// Set up necessary pointers for the DMA to calculate over the entire 
	// memory
	WriteReg(EDMASTL, 0x00);
	WriteReg(EDMASTH, 0x00);
	WriteReg(EDMANDL, LOW(RAMSIZE-1u));
	WriteReg(EDMANDH, HIGH(RAMSIZE-1u));
	WriteReg(ERXNDL, LOW(RAMSIZE-1u));
	WriteReg(ERXNDH, HIGH(RAMSIZE-1u));

	// Enable Test Mode and do an Address Fill
	BankSel(EBSTCON);
	WriteReg((BYTE)EBSTCON, EBSTCON_TME | 
						 EBSTCON_BISTST | 
						 ADDRESS_FILL);
	
	
	// Wait for the BIST to complete and disable test mode before 
	// starting any DMA operations.
	while(ReadETHReg((BYTE)EBSTCON).EBSTCONbits.BISTST);
	BFCReg((BYTE)EBSTCON, EBSTCON_TME);


	// Begin reading the memory and calculating a checksum over it
	// Block until the checksum is generated
	BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
	BankSel(EDMACSL);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);

	// Obtain the resulting DMA checksum and the expected BIST checksum
	DMAChecksum.v[0] = ReadETHReg(EDMACSL).Val;
	DMAChecksum.v[1] = ReadETHReg(EDMACSH).Val;
	BankSel(EBSTCSL);
	BISTChecksum.v[0] = ReadETHReg((BYTE)EBSTCSL).Val;
	BISTChecksum.v[1] = ReadETHReg((BYTE)EBSTCSH).Val;
	BFCReg((BYTE)EBSTCON, EBSTCON_TME);
	
	// Compare the results
	// 0xF807 should always be generated in Address fill mode
	if( (DMAChecksum.Val != BISTChecksum.Val) || (DMAChecksum.Val != 0xF807) )
		return FALSE;
	
	// Seed the random number generator and begin another Random Fill test 
	// with the DMA and BIST memory access ports swapped.
#ifdef __C30__
	WriteReg((BYTE)EBSTSD, TMR1);
#else
	WriteReg((BYTE)EBSTSD, TMR0L);
#endif
	WriteReg((BYTE)EBSTCON, EBSTCON_TME | 
					  EBSTCON_PSEL | 
					  EBSTCON_BISTST | 
					  RANDOM_FILL);
						 
						 
	// Wait for the BIST to complete and disable test mode since 
	// we won't be needing it anymore
	while(ReadETHReg((BYTE)EBSTCON).EBSTCONbits.BISTST);
	BFCReg((BYTE)EBSTCON, EBSTCON_TME);
	
	
	// Begin reading the memory and calculating a checksum over it
	// Block until the checksum is generated
	BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
	BankSel(EDMACSL);
	while(ReadETHReg(ECON1).ECON1bits.DMAST);

	// Obtain the resulting DMA checksum and the expected BIST checksum
	DMAChecksum.v[0] = ReadETHReg(EDMACSL).Val;
	DMAChecksum.v[1] = ReadETHReg(EDMACSH).Val;
	BankSel(EBSTCSL);
	BISTChecksum.v[0] = ReadETHReg((BYTE)EBSTCSL).Val;
	BISTChecksum.v[1] = ReadETHReg((BYTE)EBSTCSH).Val;
	
	return (DMAChecksum.Val == BISTChecksum.Val);
}//end TestMemory
#endif


/******************************************************************************
 * Function:        void MACSetDuplex(DUPLEX DuplexState) 
 *
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 *
 * Input:           Member of DUPLEX enum:
 *						FULL: Set full duplex mode
 *						HALF: Set half duplex mode
 *						USE_PHY: Set the MAC to match the PHYDPLXMODE bit in 
 *								 PHYCON.  This is controlled by LEDB on RESET.
 *
 * Output:          None
 *
 * Side Effects:    Changes bank bits to Bank 2.
 *
 * Overview:        Disables RX, TX logic, sets MAC up for full duplex 
 *					operation, sets PHY up for full duplex operation, and 
 *					reenables RX logic.  The back-to-back inter-packet gap 
 *					register (MACBBI

⌨️ 快捷键说明

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