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

📄 ip.c

📁 2812 TCP/IP协议的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************
修改于07.7.27,在RST8019末尾加入延时,保证发送不丢包
************************************************************************/
#include    "DSP28_Device.h"
extern	Uint16	TxEthnetFrameBuffer[1518/2];
extern	Uint16	RxEthnetFrameBuffer[100/2];
extern	Uint16	IsAns;

const Uint16 MyMAC[] = 
{0xE002,0xA04C,0x7C7E};

const Uint16 MyIP[] =
{0xA8C0,0x0301};

const Uint16 RemoteIP[] =
{0xA8C0,0x0101};

const Uint16 SubnetMask[] =
{0xFFFF,0x00FF};

const Uint16 GatewayIP[] = 
{0xA8C0,0x0101};

Uint16	TxBufFlag;
Uint16	bnry,curr;
Uint16 UDPUserDataLenth; 
Uint16 RemoteMAC[3]={0x1900,0x22E0,0x7802};                             // 48 bit MAC,赋初值便于调试
//Uint16 RemoteMAC[3];
Uint16 RecdFrameMAC[3];
Uint16 RecdFrameIP[2];
Uint16 RecdIpFrameLenth;
Uint16 TxFrameSize;
Uint16 ARPAnswerSuccessFlag;

/**********************************************************************
**函数原型:    void  	delay_ms(uint ms_number)
**入口参数:		ms_number: 延时的毫秒数
**出口参数:		无
**返 回 值:	无      
**说    明:	延时预定的时间,延时时间与特定的处理器有关
************************************************************************/
/*void	Delay_MS(Uint16	 ms_number)
{
	Uint16  i;
	Uint16  j;
	for(j = 0;j < ms_number;j++)
		for(i = 0;i < 10000;i++);
}*/
void	Delay_MS(Uint16	 ms_number)
{
	Uint16  i;
	Uint16  j;
	Uint16	tepDlay;
	for(j = 0;j < ms_number;j++)
	{
		for(i = 0;i < 227;i++)
		{
			tepDlay++;
			if (tepDlay==100)
			{
				tepDlay=0;
			}
		}
	}

}
/**********************************************************************
**函数原型:    void  page(uchar pagenumber)
**入口参数:   	Uint16	pagenumber: 要切换的页
**出口参数:		无
**返 回 值:	无      
**说    明:	选择页,可选择0,1,2三页,第四页ne000兼容芯片保留 
************************************************************************/
/*void	page(Uint16 pagenumber)
{
	Uint16 temp;
	temp=Reg00&0x3b;
	pagenumber=pagenumber<<6;
	Reg00=temp | pagenumber; 
}*/
void	page(Uint16 pagenumber)
{
	Uint16	temp;
	temp = Reg00;				//command register
	temp = temp&0x3B ; 			//注意txp位不能要
	pagenumber=pagenumber <<6;
	temp=temp | pagenumber;
	Reg00=temp;
}
/**********************************************************************
**函数原型:    void  	RST8019(void)
**入口参数:		无
**出口参数:		无
**返 回 值:	无      
**说    明:	复位8019AS
************************************************************************/
void 	RST8019(void)
{
	Uint16	resetTmp;
	Set8019RST;
	Delay_MS(50);
	Clr8019RST;
	Delay_MS(100);
	resetTmp=RegReset;
	RegReset=resetTmp;
	Delay_MS(100);//延迟10ms保证芯片复位成功;
}

/**********************************************************************
**函数原型:     void 	Init8019()
**入口参数:		无
**出口参数:		无
**返 回 值:		无              
**说    明:		对芯片的工作寄存器进行设置,各个寄存器的用法可参考文档和
**				络芯片的数据手册
************************************************************************/
void	Init8019()
{
	Reg00=0x21;   //使芯片处于停止模式,这时进行寄存器设置
	Delay_MS(10); //延时10毫秒,确保芯片进入停止模式
	page(0);
	Reg0a=0x00;   //清rbcr0
	Reg0b=0x00;   //清rbcr1
	Reg0c= 0xee;  //RCR,监视模式,不接收数据包,11101110 
	//Reg0c= 0xec;  //RCR,监视模式,不接收数据包,11101100,小于64字节不接收
	Reg0d= 0xe2;  //TCR,loop back模式,Auto发送禁止,ENC module Loopback,Internal Lookback;11100010,rcr自动生成
	Reg01=0x4c;//Pstart
	Reg02=0x80;//Pstop
	Reg03=0x4c;//BNRY
	Reg04=0x40;  //TPSR,发送起始页寄存器
	Reg07=0xff;  //清除所有中断标志位,中断状态寄存器,ISR
	Reg0f=0x00;  //中断屏蔽寄存器清0,禁止中断IMR
	Reg0e=0xC9;  // 数据配置寄存器,16位dma方式,LS位怎么回事?该位与TCR中的两个LOOPBACK位是对应的,为何此处设置不一致?
	//Reg0e=0xC1; //相对于上面设定了loopback模式??
	page(1);
	Reg07=0x4d;
	Reg08=0x00;
	Reg09=0x00;
	Reg0a=0x00;
	Reg0b=0x00;
	Reg0c=0x00;
	Reg0d=0x00;
	Reg0e=0x00;
	Reg0f=0x00;
	//Reg00=0x22;  //这时让芯片开始工作,以上为loopback测试??
	//page(1);
	Reg01=0x02;
	Reg02=0xE0;
	Reg03=0x4C;
	Reg04=0xA0;
	Reg05=0x7E;
	Reg06=0x7C;
	page(0);
	//Reg0e=0xC9;
	Reg0c=0xcc;  //将芯片设置成正常模式,跟外部网络连接RCR
	//Reg0c=0xde; //不要过滤小于64字节的数据,11011110,且物理地址不需要与自己的MAC相符
	Reg0d=0xe0;//TCR:11100000CRC enable;
	Reg00=0x22;  //启动芯片开始工作
	Reg07=0xff;		//清除所有中断标志位
	Reg0f=0x03;//仅限接受中断
	///test
	IsAns=Reg07;
	page(2);
	IsAns=Reg01;
	IsAns=Reg02;
	IsAns=Reg04;
	IsAns=Reg0c;
	IsAns=Reg0d;
	IsAns=Reg0e;
	IsAns=Reg0f;
	
}
Uint16 CalcCheckSum(Uint16 *Start, Uint16 Count, Uint16 IsTCP, Uint16 IsUDP)
{
    Uint32 Sum;
    Sum = 0;
    if ((IsTCP)||(IsUDP)) 
    {
        Sum += MyIP[0];
        Sum += MyIP[1];
        Sum += RemoteIP[0];
        Sum += RemoteIP[1];
        Sum += SwapWord(Count*2);
        if(IsTCP)
             Sum += SwapWord(PROTOCOL_TCP);
        else
             Sum += SwapWord(PROTOCOL_UDP);
    }
    while (Count > 0) 
    {
        Sum += *Start;
        Start ++;
        Count --;
    }
    Sum = (Sum & 0xFFFF) + ((Sum >> 16)&0xFFFF);
    if(Sum&0xFFFF0000)
        Sum++;
    return((Uint16)((~Sum)&0xFFFF));
}
/**********************************************************************
**函数原型:    void 		SendFrame(Uint16 *TxdNetBuff,Uint16  length)
**入口参数:		Uint16    	*TxdNetBuff	:指向发送缓冲区
**              uint length					:发送数据包的长度
**出口参数:		无
**返 回 值:	无              
**说    明:	发送数据包,以太网底层驱动程序,所有的数据发送都要通过该程序
************************************************************************/
void	SendFrame(Uint16 *TxdNetBuff,Uint16 length)
{
	Uint16	i,ii;
   	if(length<46/2)
		{
  			for(i=length;i<60/2;i++)	TxEthnetFrameBuffer[i]=0;
  			length=60/2;
		}
	
	page(0);						//切换至第0页
	length = length <<1;
	TxBufFlag=!TxBufFlag;			//设置两个发缓区,提高发送效率
	if(TxBufFlag)
		{Reg09=0x40 ;}				//设置发送页地址,RSAR设置远程DMA起始地址
	else
		{Reg09=0x46 ;}				//设置发送页地址

	Reg08=0x00; 					//read page address low
	Reg0b = length >>8;				//写发送长度高位,RBCR
	Reg0a = length & 0x00ff;        //写发送长度低位  
	Reg00=0x12;						//write dma, page0

	for(i=0;i<length/2;i++)

		{
			Reg10 = TxEthnetFrameBuffer[i];
		}

/***************************************/
//以下为终止DMA操作
			Reg0b=0x00; 
			Reg0a=0x00;
			Reg00=0x22;			//结束或放弃DMA操作
/***************************************/

		for(i=0;i<6;i++)	//最多重发6次
			{
				for(ii=0;ii<1000;ii++)
					{//检查CR寄存器的txp位是否为低,为1说明正在发送,为0说明发完或出错放弃
    					if((Reg00&0x04)==0)  
    						{ break; }
    				}
				if((Reg04&0x01)!=0)//表示发送成功,判断发送状态寄存器TSR,决定是否出错
					{break;};
				Reg00=0x3e;
			}

		Reg07=0xff;//清除发送完标志
		if(TxBufFlag)
			{
				Reg04=0x40;   //txd packet start;
			}
		else
			{
 				Reg04=0x46;  //txd packet start;
			}
		Reg06=length>>8;  //high byte counter
		Reg05=length&0xff;//low byte counter
		Reg07=0xff;//清除所有中断标志位,等待发送完成中断
		Reg00=0x3e;       //to sendpacket;
}

	/**********************************************************************
**函数原型:    Uint16        Rec_NewPacket()
**入口参数:		无
**出口参数:		无
**返 回 值:	0          没有新数据包
**              1          接收到新数据包
**说    明:	查询是否有新数据包并接收进缓冲区
************************************************************************/
Uint16	RecFrame()
{
	Uint16	i,ii;
	Uint16	Temp,length;
	union{
			Uint16	total;	
			struct{
					Uint16	high:8;
					Uint16	low:8;
				  }e;
		 }d;
		 		  		
	page(0);
	bnry = Reg03;				//bnry page have read 读页指针
	bnry = bnry & 0x00FF;
	page(1);
	curr = Reg07;				//curr writepoint 8019写页指针
	curr = curr & 0x00FF;
	page(0);
	if((curr==0))return(0);	//读的过程出错
	bnry++;
	if(bnry>0x7f)	bnry=0x4c;
	if(bnry!=curr)			//此时表示有新的数据包在缓冲区里
		{					
			page(0);//在任何操作都最好返回page0
     //=======================================
			Reg09=bnry;		//读页地址的高字节
			Reg08=0x00; 	//读页地址的低字节
			Reg0b=0x00;		//读取字节计数高字节
			Reg0a=18;       //读取字节计数低字节
			Reg00=0x0a;     //启动Remote DMA读操作


			for(i=0;i<9;i++)	//读取一包的前18个字节:4字节的8019头部,6字节目的地址,6字节原地址,2字节协议
            	{
               		RxEthnetFrameBuffer[i]=Reg10;
              	}
//====================================中止DMA操作
			Reg0b=0x00;	//
			Reg0a=0x00;	//
			Reg00=0x22;	//结束或放弃DMA操作
//====================================
			
			d.total = RxEthnetFrameBuffer[0];
			length = RxEthnetFrameBuffer[1];
			if(((d.e.high & 0x01)==0)||(d.e.low > 0x7f) || (d.e.low < 0x4c)||( length > 1517))
				{//接收状态错误或下一数据包的起始页地址错误或接收的数据包长度>1500字节
					page(1);
					curr=Reg07; 	//page1
					page(0);		//切换回page0
					bnry = curr -1;
					if(bnry < 0x4c) 	bnry =0x7f;

⌨️ 快捷键说明

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