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

📄 eth.c

📁 51单片机加rt8019硬件平台,上web方案及详细代码
💻 C
字号:
//-------------------------eth.c----------------
#include <absacc.h>
#include<string.h>	
#include"includes.h"

uchar txbuf=0;			 //发送缓冲区选择0,1

/*****************************************
 8019热复位
******************************************/
void rtl8019_reset() 
{
    REG1f=0x0f;      
    delay_us(DY200MS);
} 

/*****************************************
 8019寄存器换页
******************************************/
void page(uchar pgnum)
{
    uchar temp;
    temp=REG00;        
    temp=temp&0x3B ;//高两位清零
    pgnum=pgnum <<6;
    temp=temp | pgnum;
    REG00=temp;
}
/*****************************************
 写8019MAC地址
******************************************/
void write_mac()
{
    page(1);
    REG01=mymac[0];
    REG02=mymac[1];
    REG03=mymac[2];
    REG04=mymac[3];
    REG05=mymac[4];
    REG06=mymac[5];
    page(0);
}

/*****************************************
8019初始化 
*****************************************/
void init_8019()
{
    delay_us(DY10MS);
	rtl8019_reset();        
    REG00=0x21;         //选择页0寄存器,8019停止运行
    delay_us(DY10MS);   //延时10毫秒,确保芯片进入停止模式

    page(0);
    REG0a=0x00;    	    //清远程DMA计数器RBCR0,RBCR1
	REG0b=0x00;

    REG0c= 0xe0;        //RCR接收配置 只检查数据不存入缓存 
    REG0d= 0xe2;        //TCR传输配置 back mode 使芯片处于mon和loopback模式,跟外部网络断开  

//使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
    REG01=0x4c;    		//PSTART 接收缓存环开始页地址
	REG02=0x80;    		//PSTOP	接收缓存环结束页地址
	REG03=0x4c;			//BNRY
//使用0x4c-0x7f为网卡的接收缓冲区,共52页。
    REG04=0x40;			//TPSR	要发送包的起始页

    REG07=0xff;         //清除所有中断标志位
    REG0f=0x00;         //设置中断屏蔽寄存器,屏蔽所有中断
    REG0e=0xc8;         //DCR数据配置 使用FIFO缓存,普通模式,8位数据DMA

    page(1);
    REG07=0x4d;    		//CURR初始化当前页寄存器,指向当前正在写的页的下一页

	REG08=0x00;    		//08-0F组播地址
	REG09=0x00;
    REG0a=0x00;    
	REG0b=0x00;    
    REG0c=0x00;    
	REG0d=0x00;    
	REG0e=0x00;
    REG0f=0x00;
    write_mac();
    page(0);
    REG0c=0xcc;          //设置接收配置寄存器,使用接收缓冲区,仅接收自己地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃,校验错的数据包不接收
    REG0d=0xe0;			 //设置发送配置寄存器,启用CRC自动生成和自动校验,工作在正常模式
    REG00=0x22;          //这时让芯片开始工作
    REG07=0xff;    
}

/*****************************************
发送以太网帧 最小为60字节,最大1514字节
*****************************************/	 
void frame_send(uchar xdata * outbuf, uint len)
{
	uchar i;
	uint cnt;

	page(0);
	if(len<60)
		len=60;		
  
	REG09=(0x40 + txbuf*6);	        //RSAR1 设置远程DMA起始地址的高字节 	
	REG08=0x00; 		            //RSAR0 设置远程DMA起始地址的低字节

	REG0b=len>>8;		            //RBCR1 设置远程DMA计数器高字节
	REG0a=len&0xff;		            //RBCR0 设置远程DMA计数器低字节
	REG00=0x12;			            //write dma, page0

	for(cnt=0;cnt<len;cnt++)	
	   REG10=*(outbuf+cnt);
	   
	REG0b=0x00;                     //read count high   中止DMA操作
	REG0a=0x00;                     //read count low;
	REG00=0x22;                     //complete dma page 0 	
	
	REG04=(0x40 + txbuf*6);	         //TPSR 设置发送包起始页	
	REG06=len>>8;	                 //TBCR1 设置要发送包长度高字节
	REG05=len&0xff;	                 //TBCR0 设置要发送包长度低字节
	REG07=0xff;
	REG00=0x3e;		                 //to sendpacket;  

	for(i=0;i<16;i++)	             //最多重发16次
	{
		for(cnt=0;cnt<1000;cnt++)	 //检查txp为是否为低
		{
			if ((REG00&0x04)==0) 
				break;
		}
		if ((REG04&0x01)!=0)    	 //PTX=1表示发送成功
			break;
		REG00=0x3e;
	}
	REG07=0xff;	                     //清除所有中断标志位 		
	clean_buf(outbuf,len);
}

/*****************************************
接收以太网帧,如果收到一个有效的数据包,
返回收到的数据,否则返回NULL
*****************************************/
uint frame_receive(uchar xdata * inbuf)
{
    uchar bnry,curr,next_page,temp;    
	uint len, cnt;

    page(0);
    bnry=REG03;        //读页指针指向已被主机读取了的那页的下页
	
    page(1);
    curr=REG07;        //写页指针,指向所接收包的第一页地址
    page(0);
    if ((curr==0))     //读的过程出错
		return(0);    
    next_page=bnry;

    bnry=bnry + 1;

    if (bnry>0x7f)    
		bnry=0x4c;	

    if (bnry!=curr)    //此时表示有新的数据包在缓冲区里
    {
        //读取一包的前4个字节:4字节的8019头部
        page(0);
        REG09=bnry;     //RSAR1设置远程DMA起始地址 high
        REG08=0x00;     //RSAR0设置远程DMA起始地址 low

        REG0b=0x00;     //RBCR1 设置远程DMA计数器高字节
        REG0a=4;        //RBCR1read count low;
        REG00=0x0a;     //read dma

        temp = REG10;   //接收状态     
		temp = REG10;	//下一页指针
		
        next_page = temp-1;  //next page start-1

        len = REG10;    //帧长度2BYTE      
		temp = REG10;
        len += temp<<8;

        REG0b=0x00; 
		REG0a=0x00;  
		REG00=0x22;//complete dma page 0

        if(len == 0)
        {
            page(1);
            curr=REG07;     //page1
            page(0);        
            bnry = curr -1;

            if(bnry < 0x4c) 
				bnry =0x7f;

            REG03=bnry;     //write to bnry   
            REG07=0xff;     //清除中断状态
            return(0);
        }


        REG09=bnry;    //read page address high
        REG08=4;     //read page address low

        REG0b=len>>8;    //read count high
        REG0a=len&0xff;    //read count low;
        REG00=0x0a;    //read dma

        for(cnt=0;cnt<len;cnt++)
        {
            inbuf[cnt]=REG10;
        }
        REG0b=0x00;    
		REG0a=0x00; 
		REG00=0x22;
    //dma complete  page0     
        bnry=next_page;
        if (bnry<0x4c)  bnry=0x7f;
        REG03=bnry;     //write to bnry    
        REG07=0xff;
        return (len);    
    }
    return (0);
}
/*****************************************
查询标志位,判断是否有新数据
*****************************************/
uchar query_8019(void)
{   
    uchar bnry,curr;
    page(0);
       bnry=REG03;     //bnry page have read 读页指针
    page(1);
    curr=REG07;        //curr writepoint 8019写页指针
    page(0);
	
    if ((curr==0))    
		return(0);
	
    bnry++;
    if (bnry>0x7f)    
		bnry=0x4c; 	
	
    if (bnry!=curr)    //此时表示有新的数据包在缓冲区里	
	   return(1);
	
	   		  
    REG0b=0x00; 
	REG0a=0x00;  
	REG00=0x22;        //complete dma page 0
	return(0);
}

/*****************************************
发送以太网帧,加上帧头
*****************************************/
void eth_send(uchar xdata * outbuf, uchar * macaddr, uint frame_type, uint len)
{
    Eth_Header xdata * eth;

   	LED=0;	//指示灯亮				

    eth = (Eth_Header xdata *)outbuf;
    memcpy(eth->dest_macaddr, macaddr, 6);
    memcpy(eth->source_macaddr, mymac, 6); 
    eth->frame_type = frame_type; 
	 	
    frame_send(outbuf, len + 14);

//	TRACE("SEND > ETH_FRAME",NULL,0,0); 
   	LED=1;	//指示灯				
}

 
/*****************************************
接收以太网帧,转相应的处理程序
*****************************************/
void eth_process(uchar xdata * Databuf)
{
    Eth_Header xdata * eth;

	eth = (Eth_Header xdata *)Databuf;

	if (eth->frame_type < 1518)//小于1518表示为长度,否则表示使用上层协议
        return; 
		     
     switch (eth->frame_type)
     {
        case ARP_PACKET:
			TRACE("ARP_PACKET",NULL,0,0);
            arp_receive(Databuf);				
            break;

        case IP_PACKET:
			TRACE("IP_PACKET",NULL,0,0);
            ip_receive(Databuf);
            break;

        default: 
			TRACE("UNKNOW_PACKET",NULL,0,0);
            break;
     }

}

⌨️ 快捷键说明

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