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

📄 enc28j60.c

📁 58enc28j06protuesuip09.rar
💻 C
字号:
#include "enc28j60.h"
#include "spi.h"


#define ETHERNET_MIN_PACKET_LENGTH	0x3C
#define ETHERNET_HEADER_LENGTH		0x0E

#define IP_TCP_HEADER_LENGTH 40
#define TOTAL_HEADER_LENGTH (IP_TCP_HEADER_LENGTH+ETHERNET_HEADER_LENGTH)

#define MIN(a,b) (a) < (b) ? (a) : (b)
idata u8_t Enc28j60Bank;
idata u16_t NextPacketPtr;

 
void delay_us(int t1)
{
	while(t1--);
}

void delay_ms(int t1)
{ 
	idata int i; 
	while(t1--) 
	{
		i=1000;while(i--);
	}
}


//*******************************************************************************************
//
// Function : enc28j60ReadOp
// Description : 
//
//*******************************************************************************************
u8_t enc28j60ReadOp(u8_t op, u8_t address)
{
	u8_t dat1;	
	CS =0;
	// issue read command
	WriteByte(op | (address & ADDR_MASK));	
	dat1 = ReadByte();
	// do dummy read if needed (for mac and mii, see datasheet page 29)
	if(address & 0x80) 	dat1 = ReadByte();
	CS=1;
	return(dat1);
}
//*******************************************************************************************
//
// Function : enc28j60WriteOp
// Description : 
//
//*******************************************************************************************
void enc28j60WriteOp(u8_t op, u8_t address, u8_t mydat)
{
	CS=0;
	// issue write command
	WriteByte( op | (address & ADDR_MASK));
	// write data
	WriteByte(mydat);
	CS=1;
}

//*******************************************************************************************
//
// Function : enc28j60_mac_is_linked
// Description : return MAC link status.
//
//*******************************************************************************************

u8_t enc28j60_mac_is_linked(void)
{
	if ( (enc28j60_read_phyreg(PHSTAT1) & PHSTAT1_LLSTAT ) )
	   {    
		return 1;	    /*ok*/
	   }
	else
	   {	   
		return 0;	    /*error*/
	   }
}



//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
void enc28j60SetBank(u8_t address)
{
	// set the bank (if needed)
	if((address & BANK_MASK) != Enc28j60Bank)
	{
		// set the bank
		enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
		enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
		Enc28j60Bank = (address & BANK_MASK);
	}
}
//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
u8_t enc28j60Read(u8_t address)
{
	// select bank to read
	enc28j60SetBank(address);	
	// do the read
	return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
}
//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
void enc28j60Write(u8_t address, u8_t mydat)
{
	// select bank to write
	enc28j60SetBank(address);

	// do the write
	enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, mydat);
}
//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************

u16_t enc28j60_read_phyreg(u8_t address)
{
	u16_t mydat;
	
	// set the PHY register address
	enc28j60Write(MIREGADR, address);
	enc28j60Write(MICMD, MICMD_MIIRD);
	
	// Loop to wait until the PHY register has been read through the MII
	// This requires 10.24us
	while( (enc28j60Read(MISTAT) & MISTAT_BUSY) );
	
	// Stop reading
	//enc28j60Write(MICMD, MICMD_MIIRD);
	enc28j60Write(MICMD,0x00);	  /*by gjk 09/03/09  赋值0x00*/
	// Obtain results and return
	mydat = enc28j60Read ( MIRDH );
	mydat<<=8;	 /*jerkoh090120*/
	mydat |= enc28j60Read ( MIRDL );
	

	return mydat;
}

//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
void enc28j60PhyWrite(u8_t address, u16_t mydat)
{
	// set the PHY register address
	enc28j60Write(MIREGADR, address);
	// write the PHY data
	enc28j60Write(MIWRL, mydat & 0x00ff);
	enc28j60Write(MIWRH, mydat >> 8);
	// wait until the PHY write completes
	while(enc28j60Read(MISTAT) & MISTAT_BUSY)
	{
		delay_us(15);
	}
}

void enc28j60ReadBuffer(u16_t len, u8_t* dat)
{
    // assert CS
    // ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
    CS = 0;
    // issue read command
	//SPDR = ENC28J60_READ_BUF_MEM;
	WriteByte(ENC28J60_READ_BUF_MEM);
    //while(!(SPSR & (1<<SPIF)));
    while(len--)
    {
        // read data
		//SPDR = 0x00;
        //while(!(SPSR & (1<<SPIF)));
        //*dat++ = SPDR;
		*dat++ = ReadByte();
    }	
    // release CS
	//ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
	CS = 1;
}

void enc28j60WriteBuffer(u16_t len, u8_t* dat)
{
    // assert CS
	//ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
	CS = 0;
    
    // issue write command
	//SPDR = ENC28J60_WRITE_BUF_MEM;
	WriteByte(ENC28J60_WRITE_BUF_MEM);
   // while(!(SPSR & (1<<SPIF)));
    while(len--)
    {
        // write data
		//SPDR = *dat++;
        //while(!(SPSR & (1<<SPIF)));
		WriteByte(*dat++);
    }	
    // release CS
    //ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
	CS = 1;
}





void enc28j60PacketSend(u16_t len, u8_t* packet)
{



    // Set the write pointer to start of transmit buffer area
	enc28j60Write(EWRPTL, TXSTART_INIT);
    enc28j60Write(EWRPTH, TXSTART_INIT>>8);

    // Set the TXND pointer to correspond to the packet size given
	enc28j60Write(ETXNDL, (TXSTART_INIT+len));
    enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);

    // write per-packet control byte
	enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);

    // TODO, fix this up

    if( uip_len <= TOTAL_HEADER_LENGTH )
    {
        // copy the packet into the transmit buffer
		enc28j60WriteBuffer(len, packet);
    }
    else
    {
          len -= TOTAL_HEADER_LENGTH;
        enc28j60WriteBuffer(TOTAL_HEADER_LENGTH, packet);
        enc28j60WriteBuffer(len, (unsigned char *)uip_appdata);
    }



    //
	// Errata workaround #12, reset TX logic
	//
	{
        // clear TXRST bit in ECON1
		//enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
		//delay(100);
		// set TXRST bit in ECON1
		//enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
	}
    // send the contents of the transmit buffer onto the network
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
}




u16_t enc28j60PacketReceive(u16_t maxlen, u8_t* packet)
{
    u16_t rxstat;
    u16_t len;

    // check if a packet has been received and buffered
	if( !(enc28j60Read(EIR) & EIR_PKTIF) )
    {
        // Errata workaround #6, PKTIF is not reliable
		// double check by looking at EPKTCNT
		if (enc28j60Read(EPKTCNT) == 0)
            return 0;
    }
    
    // Make absolutely certain that any previous packet was discarded	
	//if( WasDiscarded == FALSE)
	//	MACDiscardRx();

    // Set the read pointer to the start of the received packet
	enc28j60Write(ERDPTL, (NextPacketPtr));
    enc28j60Write(ERDPTH, (NextPacketPtr)>>8);

    // read the next packet pointer
	NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
    NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

    // read the packet length
	len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
    len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

    // read the receive status
	rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
    rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

    // limit retrieve length
	// (we reduce the MAC-reported length by 4 to remove the CRC)
	len = MIN(len, maxlen);

    // copy the packet from the receive buffer
	enc28j60ReadBuffer(len, packet);

    // Move the RX read pointer to the start of the next received packet
	// This frees the memory we just read out
/*
    enc28j60Write(ERXRDPTL, (NextPacketPtr));
    enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
*/
    // Errata workaround #13. Make sure ERXRDPT is odd
	//
	{
        u16_t rs,re;
        rs = enc28j60Read(ERXSTH);
        rs <<= 8;
        rs |= enc28j60Read(ERXSTL);
        re = enc28j60Read(ERXNDH);
        re <<= 8;
        re |= enc28j60Read(ERXNDL);
        if (NextPacketPtr - 1 < rs || NextPacketPtr - 1 > re)
        {
            enc28j60Write(ERXRDPTL, (re));
            enc28j60Write(ERXRDPTH, (re)>>8);
        }
        else
        {
            enc28j60Write(ERXRDPTL, (NextPacketPtr-1));
            enc28j60Write(ERXRDPTH, (NextPacketPtr-1)>>8);
        }
    }

    // decrement the packet counter indicate we are done with this packet
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);

    return len;
}

void dev_init(void)
{
    enc28j60_init();
}

void dev_send(void)
{
    enc28j60PacketSend(uip_len, uip_buf);
}

u16_t dev_poll(void)
{
    return enc28j60PacketReceive(UIP_BUFSIZE, uip_buf);
}

void enc28j60_init(void)
{


    // perform system reset
	enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
 //   delay(50);
    // check CLKRDY bit to see if reset is complete
	//while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
	// Errata workaround #2, CLKRDY check is unreliable, delay 1 mS instead
	delay_ms(5);

    // lamp test
//	enc28j60PhyWrite(PHLCON, 0x0AA2);



    // do bank 0 stuff
	// initialize receive buffer
	// 16-bit transfers, must write low byte first

    // set receive buffer start address
	NextPacketPtr = RXSTART_INIT;
    enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
    enc28j60Write(ERXSTH, RXSTART_INIT>>8);

    // set receive pointer address
	enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
    enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);

    // set receive buffer end
	// ERXND defaults to 0x1FFF (end of ram)
	enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
    enc28j60Write(ERXNDH, RXSTOP_INIT>>8);

    // set transmit buffer start
	// ETXST defaults to 0x0000 (beginnging of ram)
	enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
    enc28j60Write(ETXSTH, TXSTART_INIT>>8);

    // do bank 2 stuff
	// enable MAC receive
	enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
    // bring MAC out of reset
	enc28j60Write(MACON2, 0x00);
    // enable automatic padding and CRC operations
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
//	enc28j60Write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
	// set inter-frame gap (non-back-to-back)
	enc28j60Write(MAIPGL, 0x12);
    enc28j60Write(MAIPGH, 0x0C);
    // set inter-frame gap (back-to-back)
	enc28j60Write(MABBIPG, 0x12);
    // Set the maximum packet size which the controller will accept
	enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);	
    enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);

    // do bank 3 stuff
	// write MAC address
	// NOTE: MAC address in ENC28J60 is byte-backward
	enc28j60Write(MAADR5, UIP_ETHADDR0);
	enc28j60Write(MAADR4, UIP_ETHADDR1);
	enc28j60Write(MAADR3, UIP_ETHADDR2);
	enc28j60Write(MAADR2, UIP_ETHADDR3);
	enc28j60Write(MAADR1, UIP_ETHADDR4);
	enc28j60Write(MAADR0, UIP_ETHADDR5);

    // no loopback of transmitted frames
	enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
    enc28j60PhyWrite(PHLCON,0x0472);

    enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);  //D2	=0xb0
    // switch to bank 0
	enc28j60SetBank(ECON1);
    // enable interrutps
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
    // enable packet reception
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
/*
    enc28j60PhyWrite(PHLCON, 0x0AA2);

    // setup duplex ----------------------

    // Disable receive logic and abort any packets currently being transmitted
    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS|ECON1_RXEN);
    
    {
        uint16_t temp;
        // Set the PHY to the proper duplex mode
        temp = enc28j60PhyRead(PHCON1);
        temp &= ~PHCON1_PDPXMD;
        enc28j60PhyWrite(PHCON1, temp);
        // Set the MAC to the proper duplex mode
        temp = enc28j60Read(MACON3);
        temp &= ~MACON3_FULDPX;
        enc28j60Write(MACON3, temp);
    }

    // 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
    //enc28j60Write(MABBIPG, DuplexState ? 0x15 : 0x12);	
    
    // Reenable receive logic
    enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);

    // setup duplex ----------------------
*/
}


⌨️ 快捷键说明

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