📄 enc28j60.c
字号:
void BFSReg(unsigned char Address, unsigned char Data)
{
Set_BFS(Address,Data);
}//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(unsigned char Register, WORD Data)
{
// Write the register address
BankSel(MIREGADR);
WriteReg((unsigned char)MIREGADR, Register);
// Write the data
// Order is important: write low byte first, high byte last
WriteReg((unsigned char)MIWRL, ((WORD_VAL*)&Data)->v[0]);
WriteReg((unsigned char)MIWRH, ((WORD_VAL*)&Data)->v[1]);
// Wait until the PHY register has been written
BankSel(MISTAT);
while(ReadMACReg((unsigned char)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
*****************************************************************************/
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)
BOOL TestMemory(void)
{
#define RANDOM_FILL 0b0000
#define ADDRESS_FILL 0b0100
#define PATTERN_SHIFT 0b1000
#define RANDOM_RACE 0b1100
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(EBSTCON, EBSTCON_TME |
EBSTCON_BISTST |
ADDRESS_FILL);
// Wait for the BIST to complete and disable test mode before
// starting any DMA operations.
while(ReadETHReg(EBSTCON).EBSTCONbits.BISTST);
BFCReg(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(EBSTCSL).Val;
BISTChecksum.v[1] = ReadETHReg(EBSTCSH).Val;
BFCReg(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.
WriteReg(EBSTSD, TMR0L);
WriteReg(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(EBSTCON).EBSTCONbits.BISTST);
BFCReg(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(EBSTCSL).Val;
BISTChecksum.v[1] = ReadETHReg(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 (MACBBIPG) is updated to maintain a 9.6us gap.
*
* Note: If a packet is being transmitted or received while this
* function is called, it will be aborted.
*****************************************************************************/
void MACSetDuplex(DUPLEX DuplexState)
{
REG Register;
PHYREG PhyReg;
// Disable receive logic and abort any packets currently being transmitted
BFCReg(ECON1, ECON1_TXRTS | ECON1_RXEN);
// Set the PHY to the proper duplex mode
PhyReg = ReadPHYReg(PHCON1);
if(DuplexState == USE_PHY)
{
DuplexState = PhyReg.PHCON1bits.PDPXMD;
}
else
{
PhyReg.PHCON1bits.PDPXMD = DuplexState;
WritePHYReg(PHCON1, PhyReg.Val);
}
// Set the MAC to the proper duplex mode
BankSel(MACON3);
Register = ReadMACReg(MACON3);
Register.MACON3bits.FULDPX = DuplexState;
WriteReg(MACON3, Register.Val);
// Set the back-to-back inter-packet gap time to IEEE specified
// requirements. The meaning of the MABBIPG value changes with the duplex
// state, so it must be updated in this function.
// In full duplex, 0x15 represents 9.6us; 0x12 is 9.6us in half duplex
WriteReg(MABBIPG, DuplexState ? 0x15 : 0x12);
// Reenable receive logic
BFSReg(ECON1, ECON1_RXEN);
}//end MACSetDuplex
/******************************************************************************
* 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: The first packet transmitted may get lost at the RX end if
* you don't wait for the link to go up first. 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(unsigned char 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(unsigned char NewConfig)
{
BankSel(ECOCON);
WriteReg(ECOCON, NewConfig);
}//end SetCLKOUT
/******************************************************************************
* Function: unsigned char GetCLKOUT(void)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: None
*
* Output: unsigned char - 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
*****************************************************************************/
unsigned char GetCLKOUT(void)
{
BankSel(ECOCON);
return ReadETHReg(ECOCON).Val;
}//end GetCLKOUT
void Software_Reset_Ethernet(void)
{
putSPIchar(0xff);
delay(0x1000);
}
unsigned char Read_RCR(unsigned char addr) //Read controller register
{
unsigned char data;
// print2("Read_RCR->addr=: ", 0, addr);
addr=addr&0x1f;
data=getSPIchar(addr);
// print2("Read_RCR->data=: ", 0, data);
return(data);
}
unsigned char Read_MACRCR(unsigned char addr) //Read MAC controller register
{
unsigned char data;
// print2("Read_MACRCR->addr=: ", 0, addr);
addr=addr&0x1f;
data=getSPIchar(addr);
data=getSPIchar(addr);
// data=getSPIchar2(addr); //Added by lfei
// print2("Read_MACRCR->data=: ", 0, data);
return(data);
}
void Write_WCR(unsigned char addr,unsigned char data) //Write contr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -