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

📄 enc28j60.c

📁 基于STC单片机与MICROCHIP ENC28J60的TCPIP以太网控制器
💻 C
字号:

#include "reg51.H"
#include "REGISTER.h"
#include "uip.h"
#include "uipopt.h"

//SPTCL寄存器
#define NUM 8
#define SPTCL_SSIG  0x80
#define SPTCL_SPEN 	0x40
#define SPTCL_MSTR 	0x10
#define SPTCL_CPOL 	0x08
#define SPTCL_CPHA 	0x04
#define SPTCL_SPR1 	0x02
#define SPTCL_SPR0 	0x01

//SPSTAT寄存器
#define SPSTAT_SPIF 	0x80
#define SPSTAT_WCOL 	0x40

sbit P10 = P1^0;
sbit P11 = P1^1;		   			//add1
sbit P12 = P1^2;					 //add1
sbit CS = P1^3;					 
sbit SS = P1^4;

sfr BRT = 0x9c;					//add7
#define RELOAD 0xF1			

extern unsigned char xdata STAT_AB ;		//ADD8

//extern unsigned char xdata UARTtimer;
extern unsigned char tick_count;		//add7
extern unsigned char ab_count;

static unsigned int NextPacketPtr = 0;      
static unsigned char Enc28j60Bank;	
typedef unsigned int INT16U;
typedef unsigned char INT8U;

void delay_ms(unsigned char num)				//延时num个毫秒
	{unsigned char i,j;
		if(num>1)
		{for (i=0;i<200;i++)
			for(j=0;j<200;j++);
		num--;}	
	}


void init_SPI(void)
	{	P1M0 =0xb8;
		P1M1 =0x40;
		SS=1;
		SPSTAT=0xC0;
		SPCTL =  SPTCL_SPEN | SPTCL_MSTR;	//选择为主机模式,SPI使能,SPI 口只能工作在00模式下				 
	}

void System_Reset(void)
	{ 	CS = 0;
	// write data
	SPDAT = ENC28J60_SOFT_RESET;
	while(!(SPSTAT & SPSTAT_SPIF));
	//SPSTAT&=~SPSTAT_SPIF;
	 SPSTAT=0xC0;
	CS = 1;
	}

/*==========================================================
//	function:	write data to addr
==========================================================*/
void encWriteOp(unsigned char op,unsigned char addr,unsigned char outdata)
{
	CS = 0;

	// send write command
	SPDAT = op | (addr & ADDR_MASK);
	while(!(SPSTAT & SPSTAT_SPIF));
	SPSTAT=0xC0;				 	 //写1的时候进行清零操作
	// write data
	SPDAT = outdata;
	while(!(SPSTAT & SPSTAT_SPIF));
	SPSTAT=0xC0;
	CS = 1;
}

/*==========================================================
//	function:	read data from addr
==========================================================*/
unsigned char encReadOp(unsigned char op,unsigned char addr)
{
	unsigned char indata;
   
	CS = 0;
	
	// send read command
	SPDAT = op | (addr & ADDR_MASK);
	while(!(SPSTAT & SPSTAT_SPIF));
	SPSTAT=0xC0;
	// read data
	SPDAT = 0x00;
	while(!(SPSTAT & SPSTAT_SPIF));
	SPSTAT=0xC0;
	// do dummy read if needed
	if(addr & 0x80)
	{
		SPDAT = 0x00;
		while(!(SPSTAT & SPSTAT_SPIF));
		SPSTAT=0xC0;
	}
	indata = SPDAT;
	
	CS = 1;

	return (indata);
}


/*==========================================================
//	function:	set enc28j60 register bank
==========================================================*/
void encSetBank(unsigned char addr)
{
	// set the bank (if needed)
	if((addr & BANK_MASK) != Enc28j60Bank)
	{
		// clear the set
		encWriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
		// set the bank
		encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (addr & BANK_MASK)>>5);
		Enc28j60Bank = (addr & BANK_MASK);
	}
}

/*==========================================================
//	function:	read regsiter
==========================================================*/
unsigned char encRead(unsigned char addr)
{
	// set the bank
	encSetBank(addr);
	// do the read
	return encReadOp(ENC28J60_READ_CTRL_REG, addr);
}
/*==========================================================
//	function:	read data buffer form enc28j60
==========================================================*/
void encReadBuffer(unsigned int temp_len,unsigned char *indata)
{
		CS = 0;
		// send read command
		SPDAT = ENC28J60_READ_BUF_MEM;
		while(!(SPSTAT & SPSTAT_SPIF));
		SPSTAT = 0xC0;
		while(temp_len--)
				{
					// read data
					SPDAT = 0x00;
					while(!(SPSTAT &  SPSTAT_SPIF));
					*indata++ = SPDAT; 
					SPSTAT = 0xC0;		
				}
		CS = 1;
}
/*==========================================================
//	function:	write regsiter
==========================================================*/
void encWrite(unsigned char addr,unsigned char outdata)
{
	// set the bank
	encSetBank(addr);
	// do the write
	encWriteOp(ENC28J60_WRITE_CTRL_REG, addr, outdata);
}

/*==========================================================
//	function:	set MAC address
==========================================================*/
void nicSetMacAddress(void)
{
	// write MAC address
	// NOTE: MAC address in ENC28J60 is byte-backward
	encWrite(MAADR0, UIP_ETHADDR5);
	encWrite(MAADR1, UIP_ETHADDR4);
	encWrite(MAADR2, UIP_ETHADDR3);
	encWrite(MAADR3, UIP_ETHADDR2);
	encWrite(MAADR4, UIP_ETHADDR1);
	encWrite(MAADR5, UIP_ETHADDR0);
}
/*==========================================================
//	function:	write PHY regsiter
==========================================================*/
void encPhyWrite(unsigned char addr, unsigned int outdata)
{
	// set the PHY register address
	encWrite(MIREGADR, addr);
	
	// write the PHY data
	encWrite(MIWRL, outdata);	
	encWrite(MIWRH, outdata>>8);
	// wait until the PHY write completes
	while(encRead(MISTAT) & MISTAT_BUSY);

}
/*==========================================================
//	function:	chip init
==========================================================*/
void encInit(void)
{
	// initialize I/O

	init_SPI();	
	
	
	// perform system reset
	System_Reset();
	// check CLKRDY bit to see if reset is complete
	delay_ms(NUM);

	while(!(encRead(ESTAT) & ESTAT_CLKRDY));

	// do bank 0 stuff
	// initialize receive buffer
	// 16-bit transfers, must write low byte first
	// set receive buffer start address
	encWrite(ERXSTL, RXSTART_INIT&0xFF);
	encWrite(ERXSTH, RXSTART_INIT>>8);
	// set receive pointer address
	encWrite(ERXRDPTL, RXSTART_INIT&0xFF);
	encWrite(ERXRDPTH, RXSTART_INIT>>8);
	// set receive buffer end
	// ERXND defaults to 0x1FFF (end of ram)
	encWrite(ERXNDL, RXSTOP_INIT&0xFF);
	encWrite(ERXNDH, RXSTOP_INIT>>8);

	//set send buffer end
	encWrite(ETXNDL,RXSTART_INIT&0xFF);
	encWrite(ETXNDH,RXSTART_INIT>>8);

	 if(encRead(ERXNDL)==0xff)				 //add1
		 {	P11=0;
		 }

	//bank 1  滤波器的设置
	encWrite(ERXFCON,0x60);		  //1:and,0:or the second bit

	// do bank 2 stuff
	// enable MAC receive
	encWrite(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
	// bring MAC out of reset
	encWrite(MACON2, 0x00);
	
	 if((encRead(MACON1)==(MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS))&&(encRead(MACON2)==0x00))
		{	P12=0;			  				//add1
		}

	// enable automatic padding and CRC operations		 //改,只能对ETH类进行位操作

	encWrite(MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);

	// set inter-frame gap (non-back-to-back)
	encWrite(MAIPGL, 0x12);
	encWrite(MAIPGH, 0x0C);
	// set inter-frame gap (back-to-back)
	encWrite(MABBIPG, 0x12);
	// Set the maximum packet size which the controller will accept
	encWrite(MAMXFLL, MAX_FRAMELEN&0xFF);	
	encWrite(MAMXFLH, MAX_FRAMELEN>>8);
	
	// do bank 3 stuff
	// write MAC address
	// NOTE: MAC address in ENC28J60 is byte-backward
	nicSetMacAddress();

	// no loopback of transmitted frames
	encPhyWrite(PHCON2, PHCON2_HDLDIS);

	encPhyWrite(PHCON1, PHCON1_PDPXMD);

	encPhyWrite(PHLCON,0x07b0);
	
	// switch to bank 0
	encSetBank(ECON1);
    encWrite(EIE,0x00);
    encWrite(EIR,0x00);
	// enable packet reception
	encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
	 // Stop timer/ counter 0.                                         
    Timer0off();          

    // Set timer/ counter 0 as mode 1 16 bit timer.      
   // TMOD &= 0xF0;
    TMOD |= 0x11;

    // Preload for 0.5s periodic interrupt.    
    TH0 = ETH_T0_RELOAD >> 8; 
    TL0 = ETH_T0_RELOAD;

	TH1 = ETH_T1_RELOAD >> 8; 
    TL1 = ETH_T1_RELOAD;

	AUXR=0x00;					//设置为12个时钟周期
	//UART initialize		add7
	AUXR=AUXR|0x05;
	BRT=RELOAD;
	SCON=0x50;
	PCON=0x00;
	AUXR=AUXR|0x10;			//启动计数
	ES=1;
    // Enable timer/ counter 0 overflow interrupt.            
    ET0 = 1;
  	ET1 = 1;	
	EA = 1;
}

/***********************发送接受函数********************/
void EthdevSPI_Sendpack(void)
	{	
		INT8U len,leno;
  	 	INT8U *ptr;
		EA=0;				

		ptr = uip_buf;					//将指针指向发送数据的首地址	
		
		//是否要判断接受忙,发送未完成,DMA操作?
		//写发送缓冲区首地址
		encWrite(ETXSTL, TXSTART_INIT&0xFF);	 
		encWrite(ETXSTH, TXSTART_INIT>>8);
		// Set the write pointer to start of transmit buffer area
		encWrite(EWRPTL, TXSTART_INIT);
		encWrite(EWRPTH, TXSTART_INIT>>8);	
		
		len	= UIP_TCPIP_HLEN + UIP_LLH_LEN;	  //UIP_LLH_LEN=14,UIP_TCPIP_HLEN=40
		
		leno=uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN;			
							
		CS = 0;

		SPDAT = ENC28J60_WRITE_BUF_MEM;
		while(!(SPSTAT & SPSTAT_SPIF));
		SPSTAT = 0xc0;

		SPDAT = 0x0e;					//包发送方式控制量,该控制量不存放在uip_buf中
		while(!(SPSTAT & SPSTAT_SPIF));
		SPSTAT = 0xC0;					 // 发送一个包控制字0e,确定发送方式为MACON3中设置

/****** 通过SPI口写进ENC28J60的缓冲区  UIP_LLH_LEN=14,UIP_TCPIP_HLEN=40  *****/
		while(len--)
			{
				// write data
				SPDAT = *ptr++;
				while(!(SPSTAT & SPSTAT_SPIF));
				SPSTAT = 0xC0;
			}
			
		ptr = (unsigned char *)uip_appdata;				//指向应用数据区					
		
		while(leno--)
			{	// write data
				SPDAT = *ptr++;
				while(!(SPSTAT & SPSTAT_SPIF));
				SPSTAT = 0xC0;
			}
					CS = 1;

		// Set the TXND pointer to correspond to the packet size given
		encWrite(ETXNDL, (TXSTART_INIT+uip_len));
		encWrite(ETXNDH, (TXSTART_INIT+uip_len)>>8);
		 
		encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);	//ECON1.TXRTS=1,开发送请求位

		   EA=1;
	}
/************************读缓冲器中数据****************************/

unsigned int EthdevSPI_read(void)
	{	INT8U i=0,*ptr;
		INT16U  tlen,rxstat;
	
		// check if a packet has been received and buffered		 (encReadOp(ENC28J60_READ_CTRL_REG, EIR) & EIR_PKTIF)!=0)||	||(encRead(EPKTCNT)==0)
	if(encRead(EPKTCNT)>0) 
		{	 	EA=0;	
	//	encWriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF);		//清0	  

		// Set the read pointer to the start of the received packet
		encWrite(ERDPTL, (NextPacketPtr));
		encWrite(ERDPTH, (NextPacketPtr)>>8);
	
			// read the next packet pointer
		NextPacketPtr  = encReadOp(ENC28J60_READ_BUF_MEM, 0);
		NextPacketPtr |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
	
		 	// read the packet length		 接受状态字的内容
		tlen  = encReadOp(ENC28J60_READ_BUF_MEM, 0);				 //有效数据+填充+CRC
		tlen |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
		 
		tlen=tlen-4;
		// read the receive status
		rxstat  = encReadOp(ENC28J60_READ_BUF_MEM, 0);
		rxstat |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;	
	
		ptr = uip_buf;
			 						 
		if(tlen>UIP_BUFSIZE)									//此包太大,将丢弃				
			{		
				P1=P1&0xfe;											//add1
				tlen = 0;		   			//return 0; 错误
			}
		 else{
				encReadBuffer(tlen,ptr);
			   }
		// Move the RX read pointer to the start of the next received packet
		// This frees the memory we just read out			前移接收缓冲器读指针ERXRDPT
		encWrite(ERXRDPTL, (NextPacketPtr));
		encWrite(ERXRDPTH, (NextPacketPtr)>>8);
		// decrement the packet counter indicate we are done with this packet
	  //encWrite(EPKTCNT,(encread(EPKTCNT)-1));
		encWriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); 
		
		EA=1;	
		   }
		  else{ 	 
		  			tlen=0;
				}
	   
		return tlen;
		   
	}


static void etherdev_timer0_isr(void) interrupt 1 using 1
{	struct uip_conn xdata *uip_connr_temp= uip_conn;	
		 unsigned char  xdata k;
	Timer0off();
    // Reload timer/ counter 0 for 0.1s periodic interrupt.   
    TH0 = ETH_T0_RELOAD >> 8;
    TL0 = ETH_T0_RELOAD;
	 k++;
	 if(k>=40)
	 {	k=0;   
		uip_connr_temp->timer--;
	if(uip_connr_temp->timer==0)	{ Timer0off();
				return;
				}
					}	
   Timer0on();
    return;
}

static void etherdev_timer1_isr(void) interrupt 3 using 3				  
   {   	struct datatrans_state *ts;	
   	unsigned char xdata k;
    ts = (struct datatrans_state xdata *)(uip_conn->appstate);
		Timer1off();
	TH1 = ETH_T1_RELOAD >> 8;		  	//和k形成1s的延时
    TL1 = ETH_T1_RELOAD;
	k++;
	 if(k>=50)
	 {	k=0;
	//  UARTtimer++;
	 tick_count++;	   					//更新ARP表的
	 if(STAT_AB==1){
	 ts->count++;						 //连接时间计数
	 if(ts->count==ab_count) 				//不同s时延
	  	  return;
	 }
	 	}
	 	Timer1on();
		return;
   }

⌨️ 快捷键说明

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