#include "stm32f10x.h"
#include "ENC28J60_Send.h"
#include "ENC28J60_SPI.h"
#include "ENC28J60_Buff_Operation.h"
#include "ENC28J60_Receive.h"
#include "UDP.h"
#include "USART.h"
static uint8_t flage=0;//释放FIFO的上部分还是下半部分 FLAGE=0,释放下半部分 FLAGE=1释放上半部分
static uint16_t Receive_Next_Add_Pointer;//下个数据包的开始地址指针
static uint16_t Receive_Now_Add_Pointer;//当前地址指针
static uint16_t Receive_MAC_Type;//数据包的类型
//static uint16_t Receive_Size_Packet;//数据包的大小
static uint16_t Receive_Add_Pointer_MSB=0;
static uint16_t Receive_Add_Pointer_LSB=0;
static uint16_t Receive_MAC_Type_MSB; /*接收数据包的临时地址指针缓冲区*/
static uint16_t Receive_MAC_Type_LSB;
static uint16_t Receive_ARP_Type_MSB;
static uint16_t Receive_ARP_Type_LSB;
static uint16_t Receive_ARP_Type;
uint8_t Receive_Data[20];//接收到的UDP数据
/*UDP相关设置*/
uint8_t MAC_Target_add[6]={0x20,0x6A,0x8A,0x8C,0x74,0x23};//目标MAC
uint8_t IP_Target_add[4]={202,201,244,21};//ip目标
uint8_t UDP_Source_Port[2]={0x1f,0x90}; //udp本机IP 8080
uint8_t UDP_Target_Port[2]={0x1f,0x90}; //UDP目标端口8080
uint8_t UDP_Send_Data[]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa};//发送的数据
//xdata uint IP_Receive_Send_check_Sum[10];//用于校验和计算的数组
//xdata uint IP_CHECK_MUNB;//计算后的IP部首的校验和被写入这里面
/*****************************
接收数据包
45页
*******************************/
void Receiving_data_packet()
{
uint8_t d2;
Receive_Next_Add_Pointer=0;//缓冲区的数据包下一个地址指针. 初始化
Receive_Now_Add_Pointer=0x300;//当前数据缓冲区地址指针.
///检测EPKTCNT是否为空
// while(1) //死在里面么,这个是故意的
// {
write_ENC28J60_REG_SPI(ECON1,5);//开启接收
for(;;)
{
d2=read_ENC28J60_REG_SPI(EPKTCNT);//有无数据报?
//my_send_byte(d2);
if(d2>0)break;
}
// GPIO_SetBits(GPIOD, GPIO_Pin_11 | GPIO_Pin_8);//GPIOD->BSRR = 0x00000f00;//置为PD8-PD11
READ_N_Packet();//读数据包
Check_The_remaining_space();//检查是否释放缓冲区
write_ENC28J60_REG_SPI(ECON2,0x40);//PACKET减一
// SendOneByte(Receive_Add_Pointer_MSB);
//SendOneByte(Receive_Add_Pointer_LSB);
//SendOneByte(a);
// SendOneByte(a<<8);
// }
}
/*******************************
检查剩余空间,如果不够就释放空间
是这样的流程:
首先解释ERXRDPTL和ERXRDPTH这个寄存器是干什么的呢?他就是说硬件通过ERXWRPTL和ERXWRPTH写入指定的缓存
那么他在那里停止呢?缓存器的底部?错,这个接收缓冲区就是一个FIFO,他是循环的存储结构,所以他在到底部
时不会停会跳到开始字节继续,那么这样一来他不就停不下了吗?显然芯片设计的人不允许他这样所以设置了这个
寄存器ERXRDPTL和ERXRDPTH,他就是停止一旦硬件写到他的地址以后的数据他不在接收,全部丢弃,所以要想全部
一个包不少的把以太网上的数据接收回来就要周期性的更新这个地址,也就是说他需要程序自己控制而不要干涉他
否则你将不会得到连续的数据包,我程序里这样设计的:首先在初始化设定接收缓存的开始地址和结束地址分别是
从0x300-0x1fff这7KB的区域全部是接收缓冲区(FIFO),初始化后ERXWRPTL和ERXWRPTH这个指针自动更新对准0X300
这个写指针是硬件控制的,用户控制不了,所以呢不用管,只要在乎这个ERXRDPTL和ERXRDPTH地址指针,这个指针我首先
付给他一个地址0x0e7e,也就是差不多在这个FIFO的一半的位置什么意思呢?表示如果我不更新这个指针的话那么硬件从0X300写到
0X0E7E就不在写了,所以我要一边读下一个包的地址一边计算他逼近的距离,当小与400个字节的时候就把这个指针向下移动到0X1FFF
也就是FIFO的底部,这时候硬件就可以继续向下,但是这时如果不更新这个指针,他就在0X1FFF的时候有就停止了,所以采取同样的办法
就是计算逼近距离小于400字节就更新指针到原来的位置0X0E7E,他又可以继续写了,就这样有数据包就收数据包永远追不上指针,就像小时候
玩的一个游戏一个棍两头各一个动物转动他们他们永远不相遇,就是这个道理,至于处理数据包这个就被抽象出来了,你想怎么处理就怎么处理
2011年11月23日
无锡第五项目部
王均伟
******************************/
/***********************
检查是否释放缓冲区函数
这个函数就是要不断的检查接收缓
存数据是不是达到临界指针,到了
就要马上让指针下移以免数据重叠。
*************************/ /**************************/
void Check_The_remaining_space() //读取当前终止指针的值
{ uint16_t 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; // 下一个数据包的地址和当前终止地址作比较
//看看是否接近到离终止指针400个字节的地方?
//还有这个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;
}
}
/************************************************
读取数据包和处理将在这里进行
主要是从BUFF里取出数据包并且处理,比如ARP、UDP、的数据提取和回应啥的
************************************************/
void READ_N_Packet()
{
/***********************数据处理开始*********************************************/
uint8_t i; //定义一个计数变量好用来接收数据
// xdata uchar n;//计数的
/*定义接收到的包相关信息
比如MAC、源地址IP。目标IP啥的
用来判断是否需要ARP应答
*/
uint8_t Receive_MAC_Source_add_MAC[6];
uint8_t Receive_ARP_Frame_sender_IP[4];
uint8_t Receive_ARP_Frame_Target_IP[4];
uint8_t Receive_IP_Frame_Type;//定义IP协议类型
uint8_t Receive_Source_Port_MSB;
uint8_t Receive_Source_Port_LSB;
uint8_t Receive_Destination_MSB;
uint8_t Receive_Destination_LSB;
uint16_t Receive_Destination;
uint16_t Receive_Source_Port;
uint8_t Receive_Length_MSB;
uint8_t Receive_Length_LSB;
uint16_t Receive_Length;//UDP数据长度
// xdata uint IP_Chrck_sum_MSB;
// xdata uint IP_Chrck_sum_LSB;
//这都是从接收的数据包检索出的数据,读出来存变量*/
/**这里解释一下read_buffer_add(Receive_Now_Add_Pointer+18)为什么是18,
首先抓包后的数据内个MAC层的类型位置在12字节上,而这里要注意,ENC28J60内部
是有个缓存他要先把下一数据包的存放地址写进去,占两个字节,然后是4个字节的
状态字,加起来是6个字节,所以要在ENC28J60的接收缓存中找到MAC帧类型就得要加上6
所以这里是18,注意是ENC28J60,不是PC,详细应该看手册的45页!!!!!
2012年3月1日
于日照高科园
王均伟
**/
Receive_MAC_Type_MSB=read_buffer_add(Receive_Now_Add_Pointer+18); /***读取数据包的类型***** ARP--0806 */
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部首的协议
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)); //计算下一个数据包的地址
Receive_ARP_Type_MSB=read_buffer_add(Receive_Now_Add_Pointer+26); /***读取数据包的操作***** requst用0001表示 */
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);//计算接收到的这个数据包的大小
/*************************************
如果是ARP请求就应答
http://blog.csdn.net/xukai871105/article/details/17564487
***************************************/
if((Receive_MAC_Type==0x0806)&(Receive_ARP_Type==0x0001))//检索ARP请求,回应
{
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); //电脑MAC
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); //电脑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); //单片机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地址是本机
******************************/
if((Receive_ARP_Frame_Target_IP[0]==202)&
(Receive_ARP_Frame_Target_IP[1]==201)&
(Receive_ARP_Frame_Target_IP[2]==244) &
(Receive_ARP_Frame_Target_IP[3]==51))
{
/*ARP 发送一帧数据应答*/
Send_ARP_Answer_packet( Receive_MAC_Source_add_MAC,Receive_ARP_Frame_sender_IP,Receive_ARP_Frame_Target_IP); //应答
}
//else
}
/******************************************************************************
如果不是ARP检查是不是UDP是就接收数据
*********************************************************************************/
if((Receive_MAC_Type==0x0800)&(Receive_IP_Frame_Type==0x11))//检索UDP数据,接收
{GPIO_ResetBits(GPIOC, GPIO_Pin_6 | GPIO_Pin_7 );
/*这个地方用的上满ARP的变量由于是局部变量所以
可以用,只是用它作为中间量获取IP,工判断用
无实际意义*/
// if(IP_CHECK_MUNB==0)
// {
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); //电脑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); //单片机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); //单片机端口
Receive_Destination=( ((Receive_Destination_MSB<<8)&0xff00)+(Receive_Destination_LSB&0x00ff));
//数据长度
/*如果是192.168.1.89发来*/
// if((Receive_ARP_Frame_Target_IP[0]==202)
// &&(Receive_ARP_Frame_sender_IP[1]==201)
// &&(Receive_ARP_Frame_sender_IP[2]==244)
// &&(Receive_ARP_Frame_sender_IP[3]==53))
// {
/*如果是8080端口发到8080的发来到本机8080的数据接收*/
// if( (Receive_Source_Port==8001)
// &&(Receive_Destination==8080)
// )
// {
/*本来想在这里加一个接收校验,结果发现一些问题
发送端并没有进行校验计算,而接收端老是能接收到校验数据,而且还是
错误的校验数据,费解!这里,也许是校验算法问题,也许是接收问题**/
/*
n=20;//初始化N
for(i=0;i<10;i++)
{
IP_Chrck_sum_MSB=read_buffer_add(Receive_Now_Add_Pointer+n);
IP_Chrck_sum_MSB=(IP_Chrck_sum_MSB<<8)&0xff00;//
n++;
IP_Chrck_sum_LSB=read_buffer_add(Receive_Now_Add_Pointer+n);
IP_Receive_Send_check_Sum
=IP_Chrck_sum_MSB+IP_Chrck_sum_LSB;
n++;
}
IP_CHECK_MUNB=IP_Receive_Send_check_Sum[5];
SendOneByte(IP_CHECK_MUNB);
SendOneByte((IP_CHECK_MUNB>>8));
*/
/*计算IP部首校验和*/
// IP_CHECK_MUNB=IP_Check_Sum_Verify(IP_Receive_Send_check_Sum,10);
//SendOneByte(IP_CHECK_MUNB);
//SendOneByte((IP_CHECK_MUNB>>8));
/*以上部分主要是对IP部首进行数据校验,如果校验后的结果是0,那么接收反之*/
/*计算接收到的数据字节*/
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);
/*读取数据字节最大20个字节*/
for(i=0;i
{
/*读数据存数组数据长度不可以超过接收数组长度*/
Receive_Data=read_buffer_add(Receive_Now_Add_Pointer+48+i);
}
if(Receive_Data[0]==0x0f)
{
Receive_Data[1]++; //接收到有效数据后自动加1
UDP_Send_Data[0]= Receive_Data[0];//接收的数据加载到发送缓冲区
//my_send_byte(UDP_Send_Data[0]);
Send_UDP_packet( MAC_Target_add,
IP_Target_add,
UDP_Source_Port,
UDP_Target_Port,
UDP_Send_Data,
1
);
}
}
// }
//}
/***********************数据处理结束*********************************************/
Receive_Now_Add_Pointer=Receive_Next_Add_Pointer;//下一个数据包地址指针重装如
}