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 + -
显示快捷键?