標(biāo)題:
ENC28J60的UDP數(shù)據(jù)接收
[打印本頁]
作者:
xuwei
時(shí)間:
2015-6-13 16:56
標(biāo)題:
ENC28J60的UDP數(shù)據(jù)接收
指定雙方IP地址
指定雙方端口號
就可以進(jìn)行UDP通信了
程序里面的接收文件如下:
*********************************
接收數(shù)據(jù)包所有程序
************************************/
#include "ARP.h"
#include "ENC28J60_Buff_Operation.h"
#include "ENC28J60_Receive.h"
#include "ENC28J60_SPI.h"
#include "UART.H"
#include "ENC28J60_Send_Receive.h"
uchar flage=0;//釋放FIFO的上部分還是下半部分FLAGE=0,釋放下半部分FLAGE=1釋放上半部分
static xdata uint Receive_Next_Add_Pointer;//下個(gè)數(shù)據(jù)包的開始地址指針
static xdata uint Receive_Now_Add_Pointer;//當(dāng)前地址指針
static xdata uint Receive_MAC_Type;//數(shù)據(jù)包的類型
static xdata uint Receive_Size_Packet;//數(shù)據(jù)包的大小
static xdata uint Receive_Add_Pointer_MSB=0;
static xdata uint Receive_Add_Pointer_LSB=0;
static xdata uint Receive_MAC_Type_MSB; /*接收數(shù)據(jù)包的臨時(shí)地址指針緩沖區(qū)*/
static xdata uint Receive_MAC_Type_LSB;
static xdata uint Receive_ARP_Type_MSB;
static xdata uint Receive_ARP_Type_LSB;
static xdata uint Receive_ARP_Type;
xdata uchar Receive_Data[20];//接收到的UDP數(shù)據(jù)
/*****************************
接收數(shù)據(jù)包
45頁
*******************************/
void Receiving_data_packet()
{ uchar d2;
Receive_Next_Add_Pointer=0;//緩沖區(qū)的數(shù)據(jù)包下一個(gè)地址指針. 初始化
Receive_Now_Add_Pointer=0x300;//當(dāng)前數(shù)據(jù)緩沖區(qū)地址指針.
///檢測EPKTCNT是否為空
while(1) //死在里面么,這個(gè)是故意的
{
write_ENC28J60_REG_SPI(ECON1,5);//開啟接收
for(;;)
{
d2=read_ENC28J60_REG_SPI(EPKTCNT);//有無數(shù)據(jù)報(bào)?
// SendOneByte(d2);
if(d2>0)break;
}
READ_N_Packet();//讀數(shù)據(jù)包
Check_The_remaining_space();//檢查是否釋放緩沖區(qū)
write_ENC28J60_REG_SPI(ECON2,0x40);//PACKET減一
// SendOneByte(Receive_Add_Pointer_MSB);
//SendOneByte(Receive_Add_Pointer_LSB);
//SendOneByte(a);
// SendOneByte(a<<8);
}
}
/*******************************
檢查剩余空間,如果不夠就釋放空間
是這樣的流程:
首先解釋ERXRDPTL和ERXRDPTH這個(gè)寄存器是干什么的呢?他就是說硬件通過ERXWRPTL和ERXWRPTH寫入指定的緩存
那么他在那里停止呢?緩存器的底部?錯(cuò),這個(gè)接收緩沖區(qū)就是一個(gè)FIFO,他是循環(huán)的存儲結(jié)構(gòu),所以他在到底部
時(shí)不會停會跳到開始字節(jié)繼續(xù),那么這樣一來他不就停不下了嗎?顯然芯片設(shè)計(jì)的人不允許他這樣所以設(shè)置了這個(gè)
寄存器ERXRDPTL和ERXRDPTH,他就是停止一旦硬件寫到他的地址以后的數(shù)據(jù)他不在接收,全部丟棄,所以要想全部
一個(gè)包不少的把以太網(wǎng)上的數(shù)據(jù)接收回來就要周期性的更新這個(gè)地址,也就是說他需要程序自己控制而不要干涉他
否則你將不會得到連續(xù)的數(shù)據(jù)包,我程序里這樣設(shè)計(jì)的:首先在初始化設(shè)定接收緩存的開始地址和結(jié)束地址分別是
從0x300-0x1fff這7KB的區(qū)域全部是接收緩沖區(qū)(FIFO),初始化后ERXWRPTL和ERXWRPTH這個(gè)指針自動(dòng)更新對準(zhǔn)0X300
這個(gè)寫指針是硬件控制的,用戶控制不了,所以呢不用管,只要在乎這個(gè)ERXRDPTL和ERXRDPTH地址指針,這個(gè)指針我首先
付給他一個(gè)地址0x0e7e,也就是差不多在這個(gè)FIFO的一半的位置什么意思呢?表示如果我不更新這個(gè)指針的話那么硬件從0X300寫到
0X0E7E就不在寫了,所以我要一邊讀下一個(gè)包的地址一邊計(jì)算他逼近的距離,當(dāng)小與400個(gè)字節(jié)的時(shí)候就把這個(gè)指針向下移動(dòng)到0X1FFF
也就是FIFO的底部,這時(shí)候硬件就可以繼續(xù)向下,但是這時(shí)如果不更新這個(gè)指針,他就在0X1FFF的時(shí)候有就停止了,所以采取同樣的辦法
就是計(jì)算逼近距離小于400字節(jié)就更新指針到原來的位置0X0E7E,他又可以繼續(xù)寫了,就這樣有數(shù)據(jù)包就收數(shù)據(jù)包永遠(yuǎn)追不上指針,就像小時(shí)候
玩的一個(gè)游戲一個(gè)棍兩頭各一個(gè)動(dòng)物轉(zhuǎn)動(dòng)他們他們永遠(yuǎn)不相遇,就是這個(gè)道理,至于處理數(shù)據(jù)包這個(gè)就被抽象出來了,你想怎么處理就怎么處理
2011年11月23日
無錫第五項(xiàng)目部
王均偉
******************************/
/***********************
檢查是否釋放緩沖區(qū)函數(shù)
這個(gè)函數(shù)就是要不斷的檢查接收緩
存數(shù)據(jù)是不是達(dá)到臨界指針,到了
就要馬上讓指針下移以免數(shù)據(jù)重疊。
*************************/ /**************************/
void Check_The_remaining_space() //讀取當(dāng)前終止指針的值
{ uint m,l,d,d2; /**************************/
l=read_ENC28J60_REG_SPI(ERXRDPTL);
m=read_ENC28J60_REG_SPI(ERXRDPTH);
d2=((l&0x00ff)+((m<<8)&0xff00)); /*****************************/
d=d2-Receive_Next_Add_Pointer; // 下一個(gè)數(shù)據(jù)包的地址和當(dāng)前終止地址作比較
//看看是否接近到離終止指針400個(gè)字節(jié)的地方?
//還有這個(gè)Flage表示以0X0E7E為界的緩存的釋放,
//FLAGE=0表示釋放下半部分FIFO(0x0e7e-0x1fff)
//FLAGE=1表示釋放上半部分FIFO(0X1FFF-0X0E7E)
/***************************/
if((d<400)&(flage==0))//如果flage=0和
{
write_ENC28J60_REG_SPI(ERXRDPTL,0xff);
write_ENC28J60_REG_SPI(ERXRDPTH,0x1f);
flage=1;
}
else
if((d<400)&(flage==1))//如果flage=1和空間不足
{
write_ENC28J60_REG_SPI(ERXRDPTL,0x7e);
write_ENC28J60_REG_SPI(ERXRDPTH,0x0e);
flage=0;
}
}
/************************************************
讀取數(shù)據(jù)包和處理將在這里進(jìn)行
************************************************/
void READ_N_Packet()
{
/***********************數(shù)據(jù)處理開始*********************************************/
uint i;
/*定義接收到的包相關(guān)信息
比如MAC、源地址IP。目標(biāo)IP啥的
用來判斷是否需要ARP應(yīng)答
*/
xdata uchar Receive_MAC_Source_add_MAC[6];
xdata uchar Receive_ARP_Frame_sender_IP[4];
xdata uchar Receive_ARP_Frame_Target_IP[4];
xdata uchar Receive_IP_Frame_Type;//定義IP協(xié)議類型
xdata uchar Receive_Source_Port_MSB;
xdata uchar Receive_Source_Port_LSB;
xdata uchar Receive_Destination_MSB;
xdata uchar Receive_Destination_LSB;
xdata uint Receive_Destination;
xdata uint Receive_Source_Port;
xdata uchar Receive_Length_MSB;
xdata uchar Receive_Length_LSB;
xdata uint Receive_Length;//UDP數(shù)據(jù)長度
//這都是從接收的數(shù)據(jù)包檢索出的數(shù)據(jù),讀出來存變量*/
/**這里解釋一下read_buffer_add(Receive_Now_Add_Pointer+18)為什么是18,
首先抓包后的數(shù)據(jù)內(nèi)個(gè)MAC層的類型位置在12字節(jié)上,而這里要注意,ENC28J60內(nèi)部
是有個(gè)緩存他要先把下一數(shù)據(jù)包的存放地址寫進(jìn)去,占兩個(gè)字節(jié),然后是4個(gè)字節(jié)的
狀態(tài)字,加起來是6個(gè)字節(jié),所以要在ENC28J60的接收緩存中找到MAC幀類型就得要加上6
所以這里是18,注意是ENC28J60,不是PC,詳細(xì)應(yīng)該看手冊的45頁。。。!
2012年3月1日
于日照高科園
王均偉
**/
Receive_MAC_Type_MSB=read_buffer_add(Receive_Now_Add_Pointer+18); /***讀取數(shù)據(jù)包的類型*****/
Receive_MAC_Type_LSB=read_buffer_add(Receive_Now_Add_Pointer+19);
Receive_MAC_Type=( ((Receive_MAC_Type_MSB<<8)&0xff00)+(Receive_MAC_Type_LSB&0x00ff));
Receive_IP_Frame_Type=read_buffer_add(Receive_Now_Add_Pointer+29);//讀取IP部首的協(xié)議
Receive_Add_Pointer_MSB=read_buffer_add(Receive_Now_Add_Pointer+1);
Receive_Add_Pointer_LSB=read_buffer_add(Receive_Now_Add_Pointer);
Receive_Next_Add_Pointer=(((Receive_Add_Pointer_MSB<<8)&0xff00)+(Receive_Add_Pointer_LSB&0x00ff)); //計(jì)算下一個(gè)數(shù)據(jù)包的地址
Receive_ARP_Type_MSB=read_buffer_add(Receive_Now_Add_Pointer+26); /***讀取數(shù)據(jù)包的操作*****/
Receive_ARP_Type_LSB=read_buffer_add(Receive_Now_Add_Pointer+27);
Receive_ARP_Type=( ((Receive_ARP_Type_MSB<<8)&0xff00)+(Receive_ARP_Type_LSB&0x00ff));
Receive_Size_Packet=(Receive_Next_Add_Pointer-Receive_Now_Add_Pointer);//計(jì)算接收到的這個(gè)數(shù)據(jù)包的大小
/*************************************
如果是ARP請求就應(yīng)答
***************************************/
if((Receive_MAC_Type==0x0806)&(Receive_ARP_Type==0x0001))//檢索ARP請求,回應(yīng)
{
Receive_MAC_Source_add_MAC[0]=read_buffer_add(Receive_Now_Add_Pointer+12);
Receive_MAC_Source_add_MAC[1]=read_buffer_add(Receive_Now_Add_Pointer+13);
Receive_MAC_Source_add_MAC[2]=read_buffer_add(Receive_Now_Add_Pointer+14);
Receive_MAC_Source_add_MAC[3]=read_buffer_add(Receive_Now_Add_Pointer+15); //發(fā)送者M(jìn)AC
Receive_MAC_Source_add_MAC[4]=read_buffer_add(Receive_Now_Add_Pointer+16);
Receive_MAC_Source_add_MAC[5]=read_buffer_add(Receive_Now_Add_Pointer+17);
Receive_ARP_Frame_sender_IP[0]=read_buffer_add(Receive_Now_Add_Pointer+34);
Receive_ARP_Frame_sender_IP[1]=read_buffer_add(Receive_Now_Add_Pointer+35); //發(fā)送者IP
Receive_ARP_Frame_sender_IP[2]=read_buffer_add(Receive_Now_Add_Pointer+36);
Receive_ARP_Frame_sender_IP[3]=read_buffer_add(Receive_Now_Add_Pointer+37);
Receive_ARP_Frame_Target_IP[0]=read_buffer_add(Receive_Now_Add_Pointer+44);
Receive_ARP_Frame_Target_IP[1]=read_buffer_add(Receive_Now_Add_Pointer+45); //目標(biāo)IP
Receive_ARP_Frame_Target_IP[2]=read_buffer_add(Receive_Now_Add_Pointer+46);
Receive_ARP_Frame_Target_IP[3]=read_buffer_add(Receive_Now_Add_Pointer+47);
/***************************
如果IP地址是本機(jī)
******************************/
if((Receive_ARP_Frame_Target_IP[0]==192)&
(Receive_ARP_Frame_Target_IP[1]==168)&
(Receive_ARP_Frame_Target_IP[2]==1) &
(Receive_ARP_Frame_Target_IP[3]==233))
{
/*ARP 應(yīng)答*/
Send_ARP_Answer_packet( Receive_MAC_Source_add_MAC,Receive_ARP_Frame_sender_IP,Receive_ARP_Frame_Target_IP); //應(yīng)答
}
}
else
/******************************************************************************
如果不是ARP檢查是不是UDP是就接收數(shù)據(jù)
*********************************************************************************/
if((Receive_MAC_Type==0x0800)&(Receive_IP_Frame_Type==0x11))//檢索UDP數(shù)據(jù),接收
{
/*這個(gè)地方用的上滿ARP的變量由于是局部變量所以
可以用,只是用它作為中間量獲取IP,工判斷用
無實(shí)際意義*/
Receive_ARP_Frame_sender_IP[0]=read_buffer_add(Receive_Now_Add_Pointer+32);
Receive_ARP_Frame_sender_IP[1]=read_buffer_add(Receive_Now_Add_Pointer+33); //獲得發(fā)送者IP
Receive_ARP_Frame_sender_IP[2]=read_buffer_add(Receive_Now_Add_Pointer+34);
Receive_ARP_Frame_sender_IP[3]=read_buffer_add(Receive_Now_Add_Pointer+35);
Receive_ARP_Frame_Target_IP[0]=read_buffer_add(Receive_Now_Add_Pointer+36);
Receive_ARP_Frame_Target_IP[1]=read_buffer_add(Receive_Now_Add_Pointer+37); //獲得目標(biāo)IP
Receive_ARP_Frame_Target_IP[2]=read_buffer_add(Receive_Now_Add_Pointer+38);
Receive_ARP_Frame_Target_IP[3]=read_buffer_add(Receive_Now_Add_Pointer+39);
Receive_Source_Port_MSB=read_buffer_add(Receive_Now_Add_Pointer+40);
Receive_Source_Port_LSB=read_buffer_add(Receive_Now_Add_Pointer+41); //源端口
Receive_Source_Port=( ((Receive_Source_Port_MSB<<8)&0xff00)+(Receive_Source_Port_LSB&0x00ff));
Receive_Destination_MSB=read_buffer_add(Receive_Now_Add_Pointer+42);
Receive_Destination_LSB=read_buffer_add(Receive_Now_Add_Pointer+43); //目標(biāo)端口
Receive_Destination=( ((Receive_Destination_MSB<<8)&0xff00)+(Receive_Destination_LSB&0x00ff));
//數(shù)據(jù)長度
/*如果是192.168.1.89發(fā)來*/
if((Receive_ARP_Frame_Target_IP[0]==192)
&&(Receive_ARP_Frame_sender_IP[1]==168)
&&(Receive_ARP_Frame_sender_IP[2]==1)
&&(Receive_ARP_Frame_sender_IP[3]==89)
)
{
/*如果是8080端口發(fā)到8080的發(fā)來到本機(jī)8080的數(shù)據(jù)接收*/
if( (Receive_Source_Port==8080)
&&(Receive_Destination==8080)
)
{
/*計(jì)算接收到的數(shù)據(jù)字節(jié)*/
Receive_Length_MSB=read_buffer_add(Receive_Now_Add_Pointer+44); //
Receive_Length_LSB=read_buffer_add(Receive_Now_Add_Pointer+45); //
Receive_Length=((((Receive_Length_MSB<<8)&0xff00)+(Receive_Length_LSB&0x00ff))-8);
/*讀取數(shù)據(jù)字節(jié)最大20個(gè)字節(jié)*/
for(i=0;i<Receive_Length;i++)
{
Receive_Data[i]=read_buffer_add(Receive_Now_Add_Pointer+48+i);
}
P0=Receive_Data[0];
}
}
}
/***********************數(shù)據(jù)處理結(jié)束*********************************************/
Receive_Now_Add_Pointer=Receive_Next_Add_Pointer;//下一個(gè)數(shù)據(jù)包地址指針重裝如
}
復(fù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1