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

📄 eth.c

📁 基于51单片机和RTL8019以太网控制器的嵌入式以太网控制程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
void reconstruct_ping(unsigned char table_index)
{
	txdnet.etherframe.protocal=0x0800;
	txdnet.ipframe.verandihl=0x45;
	txdnet.ipframe.typeofserver=0x00;
	txdnet.ipframe.totallength=60;
    txdnet.ipframe.ttl=0x80;
	txdnet.ipframe.frameindex=frameindex;
	frameindex++;
	txdnet.ipframe.segment=0x0000;
	txdnet.ipframe.protocal=0x0001;//icmp
    txdnet.ipframe.crc=0;
    txdnet.ipframe.destip[0]=ping_table[table_index].ip.words[0];
    txdnet.ipframe.destip[1]=ping_table[table_index].ip.words[1];
    txdnet.ipframe.sourceip[0]=my_ip_address.words[0];
    txdnet.ipframe.sourceip[1]=my_ip_address.words[1];
    txdnet.ipframe.crc=createipheadcrc(&txdnet);
    txdnet.icmpframe.type=0x08;// is icmp request;
	txdnet.icmpframe.option=0x00;		//该句由Mingtree加
    txdnet.icmpframe.crc=0;
	txdnet.icmpframe.id=0x0300;
	txdnet.icmpframe.seq=frameindex;
    txdnet.icmpframe.crc=createicmpcrc();
}
//------------------------------------------------------------------------
//函数功能:定时操作,放在1秒循环任务中
//
//入参:	无
//
//返回值:	无
//
//
//作者:
//
//注意:	用于对PING_TABLE进行操作,该函数是处理PING的最重要函数
//
//
//注释:	Mingtree
//日期:	2004-10-28
//------------------------------------------------------------------------
void PingCycle()    //定时操作,放在1秒循环任务中
{
	unsigned char  i;

	//对PING_TABLE表进行扫
	for(i=0;i<MaxLenPingBuf;i++)
	{
		switch(ping_table[i].status)
		{
		case 0:
			//空闲,直接返回
			break;
		case 1:		//已发出但无应答(过了1s还未应答),输出超时
			//TODO
			//在这里添加串口发送代码,先上位机显示主机不可达
			PrintUnreach();
			break;
		case 2:		//发出且应答.注意,如果收到回显应答,则在PING_ECHO里进行处理,对状态进行修改
			ping_table[i].times=ping_table[i].times-1;
			if(0==ping_table[i].times)
            {
				ping_table[i].status=0;
				break;
			}

		case 4:		////第一次准备发(用于同步1秒时钟)
			//查ARP缓存
			if(findmacadr(ping_table[i].ip,&ping_ethernet_address))
			{
                //因为发送缓冲区的内容已经发生改变,因此重新构造PING包
                reconstruct_ping(i);
				//填写发送包的MAC地址
				ping_table[i].pack->etherframe.uDestID[0]=ping_ethernet_address.words[0];
				ping_table[i].pack->etherframe.uDestID[1]=ping_ethernet_address.words[1];
				ping_table[i].pack->etherframe.uDestID[2]=ping_ethernet_address.words[2];

				//进行发送
				send_packet(ping_table[i].pack,74);
				//改变状态
				ping_table[i].status=1;
			}
			else
			{
				//ARP表里没有对应项,发送ARP请求
				arp_request(ping_table[i].ip);

				//改变状态
				ping_table[i].status=3;
			}
			break;
		case 3:		//等待ARP
			//查ARP缓存
			if(findmacadr(ping_table[i].ip,&ping_ethernet_address))
			{
				//因为发送缓冲区的内容已经发生改变,因此重新构造PING包
				reconstruct_ping(i);
				//填写发送包的MAC地址
				ping_table[i].pack->etherframe.uDestID[0]=ping_ethernet_address.words[0];
				ping_table[i].pack->etherframe.uDestID[1]=ping_ethernet_address.words[1];
				ping_table[i].pack->etherframe.uDestID[2]=ping_ethernet_address.words[2];
				//进行发送
				send_packet(ping_table[i].pack,74);	
			}
			//已经发出ARP,但是没发回,改变状态
			ping_table[i].status=1;
			break;
		default:
			ping_table[i].status=0;
		}
	}
}

//------------------------------------------------------------------------
//函数功能?
//
//入参:	无
//
//
//
//
//作者:
//
//注意:
//
//
//注释:	Mingtree
//日期:	2004-10-28
//------------------------------------------------------------------------
bit query_8019()
{
	char 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=bnry++;
	if (bnry>0x7f)	bnry=0x4c;
	if (bnry!=curr)	//此时表示有新的数据包在缓冲区里
		return 1;
 	reg0b=0x00; reg0a=0x00;  reg00=0x22;//complete dma page 0
}
unsigned int checksum(unsigned int xdata *check,unsigned int length)//计算校验和
{
	unsigned long sum=0;
	unsigned int i;
	for (i=0;i<(length)/2;i++)
		sum+=*check++;
	if(length&0x01)//表示长度为单数
		sum=sum+((*check)&0xff00);
	sum=(sum&0xffff)+((sum>>16)&0xffff);//高16位和低16位相加
	if(sum&0xffff0000)//表示有进位
		sum++;
	return ( (unsigned int)(~((sum)&0xffff))  );
}
bit verifyipheadcrc(union netcard xdata *pRxdnet)//对ip头进行校验,错误返回0,正确返回1
{
	unsigned int crc;

	crc=checksum(&(pRxdnet->ippacket.ippacket[0]),(pRxdnet->ipframe.verandihl&0x0f)*4);
	if(crc==0) return (1);
	return(0);
}




//------------------------------------------------------------------------
//函数功能:主循环
//
//入参:	无
//
//
//
//
//作者:
//
//注意:
//
//
//注释:	Mingtree
//日期:	2004-11-10
//------------------------------------------------------------------------
void maincycle(void)//主循环
{
	if(recv_packet(&rxdnet)==1)
	{ //PrintStr("Good packet!");
		temp_ip_address.words[0]=rxdnet.ipframe.destip[0];
		temp_ip_address.words[1]=rxdnet.ipframe.destip[1];

		if(rxdnet.etherframe.protocal==0x0806)
		{//表示收到一个arp请求包
			if(rxdnet.arpframe.operation==0x0001)
				arp_answer();//ARP request,处理arp数据包
			if(rxdnet.arpframe.operation==0x0002) 
			{
				arp_process();//ARP answer
				//tcp保活测试
				TCP_ATYARP();
			}
		}
		else
			if((rxdnet.etherframe.protocal==0x0800)&&((rxdnet.ipframe.verandihl&0xf0)==0x40)&&(temp_ip_address.dwords==my_ip_address.dwords))
			{
				if(verifyipheadcrc(&rxdnet))
				{//表示收到一个ip包,仅处理ip v4
					switch(rxdnet.ipframe.protocal)
					{
					case 1://表示为icmp协议
                		if(rxdnet.icmpframe.type==8) //是一个ping的请求包
	                		ping_answer();
				    	else if(rxdnet.icmpframe.type==0)
				        	ping_echo(); //是一个ping的应答包
						break;
          			case 6: //表示是tcp协议
                 	//	process_tcp();
						tcp_rcve(&rxdnet);
		          		break;
          			case 0x11: //表示是udp协议
						udp_rcve(&rxdnet);
                  		break;
		           default:;
				}
			}
		}
	}
}
//******************************************************
//函数功能:读网关配置信息
//参数:    
//          
//说明:
//作者:    Mingtree
//日期:    2005-11-03
//******************************************************
void ReadGateway()
{
	unsigned char i;

	//网关IP
	for(i=0;i<4;i++)
	{
		addr0=RLDDR;
		addr1=GATEIP+i;
		x5045ReadData();
		gateway_ip_address.bytes[i]=WriteBuf;
	}

	//子网掩码
	mask_ip_address.bytes[0] = 255;
	mask_ip_address.bytes[1] = 255;
	mask_ip_address.bytes[2] = 255;
	mask_ip_address.bytes[3] = 0;

}

//******************************************************
//函数功能:读本地IP
//参数:    
//          
//说明:
//作者:    Mingtree
//日期:    2004-09-12
//******************************************************
void ReadLIP()
{
	unsigned char i;
	for(i=0;i<4;i++)
	{
		addr0=RLDDR;
		addr1=LIPADDR+i;
		x5045ReadData();
		my_ip_address.bytes[i]=WriteBuf;
	}
}
//******************************************************
//函数功能:读本地MAC
//参数:    
//          
//说明:
//作者:    Mingtree
//日期:    2004-09-12
//******************************************************
void ReadMAC()
{
	unsigned char i;
	for(i=0;i<6;i++)
	{
		addr0=RLDDR;
		addr1=MACADDR+i;
		x5045ReadData();
		my_ethernet_address.bytes[i]=WriteBuf;
	}
}
void PingDisp()
{
	unsigned char xdata Echo[255]={'R','e','p','l','y',' ','f','r','o','m'};
	unsigned char xdata IP[16];
	unsigned char i;
	HEXToIPadr(IP,&ping_ip_address);

	//16为255.255.255.255整个字符的长度,包括“.”
	for(i=0;i<16;i++)
		Echo[10+i]=IP[i];
	PrintStr(Echo);
}

void HEXToIPadr(unsigned char xdata *Str,union IP_address xdata *ip)
{
	unsigned char i;
	unsigned char x,y;

	for(i=0;i<4;i++){
		x=ip->bytes[i];
		if(x>99){
			y=x/100;*Str++=y+'0';
			x=x-100*y;y=x/10;*Str++=y+'0';
			x=x-10*y;*Str++=x+'0';
			if(i==3) *Str++='\0';
			else *Str++='.';
		}
		else if(x>9){
			y=x/10;*Str++=y+'0';
			x=x-10*y;*Str++=x+'0';
			if(i==3) *Str++='\0';
			else *Str++='.';
		}
		else{
			*Str++=x+'0';
			if(i==3) *Str++='\0';
			else *Str++='.';
		}
	}	
}

void PrintUnreach()//显示字符串
{
	unsigned char xdata Host[255]={'H','o','s','t',' '};
	unsigned char xdata IP[16];
	unsigned char xdata Unreach[13]={'U','n','r','e','a','c','h','a','b','l','e','!','\0'};
	unsigned char i,j;
	HEXToIPadr(IP,&ping_ip_address);

	//16为255.255.255.255整个字符的长度,包括“.”
	for(i=0;i<16;i++)
		Host[5+i]=IP[i];
	//定位'\0'
	for(i=0;i<16;i++)
	{
		if(0x00==IP[i])
			break;
	}
	if(i<16)
		j=i;
	else
		j=15;
	for(i=0;i<13;i++)
		Host[5+j+i]=Unreach[i];
	PrintStr(Host);
}
/*
void Test8019()
{
	unsigned char i,temp=0;
	reg09=0x40;		//txdwrite highaddress
	reg08=0x00; 			//read page address low
	reg0b=00;				//read count high
	reg0a=16;		//read count low;
	reg00=0x12;	
	for(i=0;i<16;i++)
	{
		reg10=temp;
		temp++;
	}
	reg0b=0x00;		//read count high   中止DMA操作
	reg0a=0x00;		//read count low;
	reg00=0x22;		//complete dma page 0
	//读
	reg09=0x40;			//read page address high
	reg08=0x00; 		//read page address low
	reg0b=0x00;			//read count high
	reg0a=16;			//read count low;
	reg00=0x0A;			//read dma
	for(i=0;i<16;i++)
	{
   		 temp=reg10;
		 PrintByte(temp);
	}

	// 以下3句为中止dma的操作,可以不要    
	reg0b=0x00;		//read count high   中止DMA操作
	reg0a=0x00;		//read count low;
	reg00=0x22;		//complete dma page 0
}	 */

⌨️ 快捷键说明

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