|
三个功能:
1.UDP标准配置
2.IP校验
3.向以太网中送UDP包!
- /**本函数是一个类初始化函数
- 主要是一些不变的参数和部分数据的初始化
- **/
- void UDP_Frame_Set(
- TypeDef_MAC_Frame_H *MAC_Frame,
- TypeDef_IP_Frame_H *IP_Frame,
- TypeDef_UDP_Frame_H *UDP_Frame
- )//设置UDP相关参数
- {
-
- /**
-
- 整个UDP帧是由
- MAC帧+IP帧+UDP帧构成的!!!!!
- 编译器要开在大端模式!主要考虑用的外部RAM
- */
- /*****MAC部首设置***************************************************/
- /********目标MAC地址***************/
- MAC_Frame->Destination_MAC[0]=0;
- MAC_Frame->Destination_MAC[1]=0;
- MAC_Frame->Destination_MAC[2]=0;
- MAC_Frame->Destination_MAC[3]=0;
- MAC_Frame->Destination_MAC[4]=0;
- MAC_Frame->Destination_MAC[5]=0;
- /********源MAC地址*************/
- MAC_Frame->Source_add_MAC[0]=0x00;
- MAC_Frame->Source_add_MAC[1]=0x26;
- MAC_Frame->Source_add_MAC[2]=0x9E;
- MAC_Frame->Source_add_MAC[3]=0xC7;
- MAC_Frame->Source_add_MAC[4]=0x6C; //本机MAC固定的
- MAC_Frame->Source_add_MAC[5]=0xF3;
- /********类型长度******8*****/
- MAC_Frame->Type[0]=0x08;
- MAC_Frame->Type[1]=0x00;//0X0800IP包 0x0806ARP
- /**************IP部首设置**************************************************/
- IP_Frame ->IP_Version_Head=0x45;//IP版本是4,部首长度是20个字节
- IP_Frame ->IP_Tos=0;//IP的TOS一般设为0
- IP_Frame ->IP_Total_Length[0]=0;//设置总长度
- IP_Frame ->IP_Total_Length[1]=0;//设置总长度
- IP_Frame ->IP_Indentification[0]=0;
- IP_Frame ->IP_Indentification[1]=1; //标识字段,发送一个都会加一
- IP_Frame ->IP_Flage_FRAGMENT_OFFSET[0]=0; //3位标识和片偏移,这里是指IP分片,尽量不产生IP分片
- IP_Frame ->IP_Flage_FRAGMENT_OFFSET[1]=0;
- IP_Frame ->IP_TTL=64;//生存时间默认为32或者64,过一个路由器减去一!当此值为0此份报文被丢弃
- IP_Frame ->IP_Protocol=0x11;//表示协议,这是UDP协议
- /*IP部首校验和*/
- IP_Frame ->IP_Check_sum[0]=0;
- IP_Frame ->IP_Check_sum[1]=0; //0;
- /*本机IP*/
- IP_Frame ->IP_Source[0]=192;
- IP_Frame ->IP_Source[1]=168;
- IP_Frame ->IP_Source[2]=1;
- IP_Frame ->IP_Source[3]=233;
- /*目标IP地址这个得由ARP获得这里做初始化设置*/
- IP_Frame ->IP_Dstination[0]=0;
- IP_Frame ->IP_Dstination[1]=0;
- IP_Frame ->IP_Dstination[2]=0;
- IP_Frame ->IP_Dstination[3]=0;
- /***************UDP设置***************************************/
- UDP_Frame->UDP_Source_Port[0]=0x1f;
- UDP_Frame->UDP_Source_Port[1]=0x90;//源端口是8080
- UDP_Frame->UDP_Dstination_Port[0]=0x1f;
- UDP_Frame->UDP_Dstination_Port[1]=0x90;//目标端口是8080
- /*这个长度也得有实际数据决定
- 他的长度是UDP长度+数据比如数据长度是1个字节, 那么
- 这个长度就是UDP部首+1=8个字节+1个字节=9
-
- */
- // UDP_Frame->UDP_Length[0]=0;
- // UDP_Frame->UDP_Length[1]=0;
- /*
- 校验和也是得有数据才可以算出来,这里只是 初次赋值!!
- */
- UDP_Frame->UDP_check_sum[0]=0;
- UDP_Frame->UDP_check_sum[1]=0;
- //UDP_Frame->UDP_Data[0];//数据
-
-
- }
- /***************************************
- IP部首的校验和!他把IP部首看做是一连串的16位
- 数据,然后把这些数据加起来然后取反,所谓的二进制
- 反码求和,并不是字面上的先去凡在求和,其实是相加后再取反!!坑爹啊
- 他的作用是:
- 1.在发送端他首先把校验字段清0,其后进行二进制反码求和,
- 结果送到校验子段,
- 2。在发送端他接收到后直接的把所有数据进行反码求和,然后再读取这个值,如果是0,那么是对的,如果不是
- 那么证明这个IP数据帧是有问题的应该丢弃或者发送差错报文!
- 2012年3月3日
- 日照高科园
- 王均伟
- ************************************/
- uint IP_Check_Sum_Verify(TypeDef_IP_Frame_H *IP_Frame_Sum)
- {
- /*
- 一下算法源于百度,感谢再感谢!!
- 计算对IP首部检验和的算法如下:
- (1)把IP数据包的校验和字段置为0;
- (2)把首部看成以16位为单位的数字组成,依次进行二进制求和
- (注意:求和时应将最高位的进位保存,所以加法应采用32位加法);
- (3)将上述加法过程中产生的进位(最高位的进位)加到低16位
- (采用32位加法时,即为将高16位与低16位相加,之后还要把该次加
- 法最高位产生的进位加到低16位)
- (4)将上述的和取反,即得到校验和。
- 2012年3月3日于日照高科园
- 按照以上算法便可以!
- */
- xdata unsigned long a,b;
- xdata uchar i;
- xdata uint tab[10];
- xdata uint msb,lsb;
-
- msb=IP_Frame_Sum->IP_Version_Head; //IP的版本号和IP的部首长度,默认为0X45,版本是4,部首是20字节
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Tos; //ip的TOS据我抓包观察一般是00
- tab[0]=msb+lsb;
- msb=IP_Frame_Sum->IP_Total_Length[0];//总数据报文长度
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Total_Length[1];//总数据报文长度
- tab[1]=msb+lsb;
- msb=IP_Frame_Sum->IP_Indentification[0];//IP标识字段,标识字段唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Indentification[1];
- tab[2]=msb+lsb;
- msb=IP_Frame_Sum->IP_Flage_FRAGMENT_OFFSET[0];//标志位和片偏移
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Flage_FRAGMENT_OFFSET[1];//标志位和片偏移
- tab[3]=msb+lsb;
- msb=IP_Frame_Sum->IP_TTL; //生存时间
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Protocol; //协议类型
- tab[4]=msb+lsb;
- msb=IP_Frame_Sum->IP_Check_sum[0];//部首校验和
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Check_sum[0];//部首校验和
- tab[5]=msb+lsb;
- msb=IP_Frame_Sum->IP_Source[0];//32IP位源地址
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Source[1];//32IP位源地址
- tab[6]=msb+lsb;
- msb=IP_Frame_Sum->IP_Source[2];//32IP位源地址
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Source[3];//32IP位源地址
- tab[7]=msb+lsb;
- msb=IP_Frame_Sum->IP_Dstination[0];//32位IP目标地址
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Dstination[1];//32位IP目标地址
- tab[8]=msb+lsb;
- msb=IP_Frame_Sum->IP_Dstination[2];//32位IP目标地址
- msb=msb<<8;
- lsb=IP_Frame_Sum->IP_Dstination[3];//32位IP目标地址
- tab[9]=msb+lsb;
- /**我操原来是没有清空变量草,费了我一天时间,我说第一次运行正确,其后不对
- 没有清零!我擦我操!
- 2012年3月7日
- 日照高科园
- 王均伟*/
-
- a=0; //清零
- b=0;
-
- for(i=0;i<10;i++)
- {
- a=a+tab[i]; //变量加
- b=a;//暂存A中
- b+=(a>>16)&0x0000ffff; //取高位与地位相加,并且加完了清0高八位
- }
- b=~b; //取反
-
- return b;
- }
- /*******************************8
-
-
- 发送UDP数据包
- 指定目标IP,本地IP,本地端口,目标端口
- 还有数据大小,什么数据,第几个包
- uchar *MAC_Target_add,//MAC地址。一般情况下由ARP计算得出
- uchar *IP_Source_add,//IP源地址
- uchar *IP_Target_add,//IP目标地址
- uint UDP_Source_Port,UDP源端口
- uint UDP_Target_Port,UDP目标端口
- uchar * UDP_Send_Data, UDP数据
- uchar UDP_Send_Data_length UDP数据长度
- **********************************/
- void Send_UDP_packet( uchar *MAC_Target_add,
- uchar *IP_Target_add,
- uchar *UDP_Source_Port,
- uchar *UDP_Target_Port,
- uchar *UDP_Send_Data,
- uchar UDP_Send_Data_length
- )
- {
- TypeDef_MAC_Frame_H xdata MAC_Frame_H;//MAC定义一个结构体头
- TypeDef_IP_Frame_H xdata IP_Frame_H; //IP定义一个结构体头
- TypeDef_UDP_Frame_H xdata UDP_Frame_H;//UDP定义数据结构
- xdata uchar d;
- xdata uchar MSB,LSB; //中间量
- xdata uint da; //
- /*传递了一个结构指针进去指向了上面建立的变量
- 就是建立了一个映射,把所有的都映射了,
- 目的是要初始化
- 表示这里面的都是标准配置,一般不改变
- 要随时改变的就在这个函数下面设置了
- 比如MAC_Frame_H.Destination_MAC
- 他是个传递参量!
- */
- UDP_Frame_Set(&MAC_Frame_H,&IP_Frame_H,&UDP_Frame_H);//设置UDP相关参数
- /*MAC目标地址*/
- MAC_Frame_H.Destination_MAC[0]=MAC_Target_add[0];
- MAC_Frame_H.Destination_MAC[1]=MAC_Target_add[1];
- MAC_Frame_H.Destination_MAC[2]=MAC_Target_add[2];
- MAC_Frame_H.Destination_MAC[3]=MAC_Target_add[3];
- MAC_Frame_H.Destination_MAC[4]=MAC_Target_add[4];
- MAC_Frame_H.Destination_MAC[5]=MAC_Target_add[5];
- /*IP目标地址*/
- IP_Frame_H.IP_Dstination[0]=IP_Target_add[0];
- IP_Frame_H.IP_Dstination[1]=IP_Target_add[1];
- IP_Frame_H.IP_Dstination[2]=IP_Target_add[2];
- IP_Frame_H.IP_Dstination[3]=IP_Target_add[3];
- //数据长度,
- /*这个长度等于IP部首20字节+UDP部首8字节+UDP数据,这里是1字节UDP_Send_Data_length表示这是数据长度*/
- da=28+UDP_Send_Data_length;
- LSB=da;
- MSB=(da>>8)&0x00ff;
- IP_Frame_H.IP_Total_Length[0]=MSB;//设置总长度
- IP_Frame_H.IP_Total_Length[1]=LSB;//设置总长度 //29字节
-
-
- /*加入IP校验和*/
- da=IP_Check_Sum_Verify(&IP_Frame_H); //计算IP部首校验和
- LSB=da;
- MSB=(da>>8)&0x00ff;
- IP_Frame_H.IP_Check_sum[0]=MSB;
- IP_Frame_H.IP_Check_sum[1]=LSB; //写入IP部首校验和
- /*****************UDP***********************/
- UDP_Frame_H.UDP_Source_Port[0]=UDP_Source_Port[0];
- UDP_Frame_H.UDP_Source_Port[1]=UDP_Source_Port[1];//源端口是8080
- UDP_Frame_H.UDP_Dstination_Port[0]=UDP_Target_Port[0];
- UDP_Frame_H.UDP_Dstination_Port[1]=UDP_Target_Port[1];//目标端口是8080
- /*这个长度也得有实际数据决定
- 他的长度是UDP长度+数据比如数据长度是1个字节, 那么
- 这个长度就是UDP部首+1=8个字节+1个字节=9
-
- */
- da=8+UDP_Send_Data_length; //计算UDP数据长度
- LSB=da;
- MSB=(da>>8)&0x00ff;
- UDP_Frame_H.UDP_Length[0]=MSB;
- UDP_Frame_H.UDP_Length[1]=LSB;
- /*加载数据*/
- //注意这里的UDP数据我只分配了10个字节,要想加大数据量就得改结构体!
- for(d=0;d<UDP_Send_Data_length;d++)
- {
- UDP_Frame_H.UDP_Data[d]=UDP_Send_Data[d];//数据写入
- }
- //以上实际上就是设置了三个结构体,全部围绕这三个结构体展开的
-
- /* 物理操作 */
- set_send_buffer_add(0x0200,0x023f);//缓冲区的大小设定,开始200结束1fff
-
- write_buffer_add(0x0200,0x0e);//控制字节
- // MAC
- write_buffer_add(0x0201,MAC_Frame_H.Destination_MAC[0]);//
- write_buffer_add(0x0202,MAC_Frame_H.Destination_MAC[1]);//
- write_buffer_add(0x0203,MAC_Frame_H.Destination_MAC[2]);//
- write_buffer_add(0x0204,MAC_Frame_H.Destination_MAC[3]);//
- write_buffer_add(0x0205,MAC_Frame_H.Destination_MAC[4]);// MAC目的地址
- write_buffer_add(0x0206,MAC_Frame_H.Destination_MAC[5]);//
- write_buffer_add(0x0207, MAC_Frame_H.Source_add_MAC[0]);//
- write_buffer_add(0x0208, MAC_Frame_H.Source_add_MAC[1]);//
- write_buffer_add(0x0209, MAC_Frame_H.Source_add_MAC[2]);// MAC源地址
- write_buffer_add(0x020A, MAC_Frame_H.Source_add_MAC[3]);//
- write_buffer_add(0x020B, MAC_Frame_H.Source_add_MAC[4]);//
- write_buffer_add(0x020C, MAC_Frame_H.Source_add_MAC[5]);//
- write_buffer_add(0x020D, MAC_Frame_H.Type[0]);// MAC类型
- write_buffer_add(0x020E, MAC_Frame_H.Type[1]);//
-
- //IP
- write_buffer_add(0x020F,IP_Frame_H.IP_Version_Head);//
- write_buffer_add(0x0210,IP_Frame_H.IP_Tos);//
- write_buffer_add(0x0211,IP_Frame_H.IP_Total_Length[0]);
- write_buffer_add(0x0212,IP_Frame_H.IP_Total_Length[1]);
- write_buffer_add(0x0213,IP_Frame_H.IP_Indentification[0]);
- write_buffer_add(0x0214,IP_Frame_H.IP_Indentification[1]);
- write_buffer_add(0x0215,IP_Frame_H.IP_Flage_FRAGMENT_OFFSET[0]);
- write_buffer_add(0x0216,IP_Frame_H.IP_Flage_FRAGMENT_OFFSET[1]);
- write_buffer_add(0x0217,IP_Frame_H.IP_TTL);
- write_buffer_add(0x0218,IP_Frame_H.IP_Protocol);
- write_buffer_add(0x0219,IP_Frame_H.IP_Check_sum[0]);
- write_buffer_add(0x021A,IP_Frame_H.IP_Check_sum[1]);
- write_buffer_add(0x021B,IP_Frame_H.IP_Source[0]);
- write_buffer_add(0x021C,IP_Frame_H.IP_Source[1]);
- write_buffer_add(0x021D,IP_Frame_H.IP_Source[2]);
- write_buffer_add(0x021E,IP_Frame_H.IP_Source[3]);
- write_buffer_add(0x021F,IP_Frame_H.IP_Dstination[0]);
- write_buffer_add(0x0220,IP_Frame_H.IP_Dstination[1]);
- write_buffer_add(0x0221,IP_Frame_H.IP_Dstination[2]);
- write_buffer_add(0x0222,IP_Frame_H.IP_Dstination[3]);
- //UDP
- write_buffer_add(0x0223,UDP_Frame_H.UDP_Source_Port[0]);
- write_buffer_add(0x0224,UDP_Frame_H.UDP_Source_Port[1]);
- write_buffer_add(0x0225,UDP_Frame_H.UDP_Dstination_Port[0]);
- write_buffer_add(0x0226,UDP_Frame_H.UDP_Dstination_Port[1]);
- write_buffer_add(0x0227,UDP_Frame_H.UDP_Length[0]);
- write_buffer_add(0x0228,UDP_Frame_H.UDP_Length[1]);
- write_buffer_add(0x0229,UDP_Frame_H.UDP_check_sum[0]);
- write_buffer_add(0x022A,UDP_Frame_H.UDP_check_sum[1]);
- //数据 //发送数量UDP_Send_Data_length
- //数据在 UDP_Frame_H.UDP_Data[]里;
-
- for(d=0;d<UDP_Send_Data_length;d++)
- {
- write_buffer_add((0x022B+d),UDP_Frame_H.UDP_Data[d]);
-
- }
- write_ENC28J60_REG_SPI(ECON1,0x0c);//允许发送,允许接收
- for(;;)
- {
-
- d=read_ENC28J60_REG_SPI(EIR);//读取数据包接收标志位
- if((d&0x08)==0x08)break; //发送完毕??OK退出ifNO死在里面
-
- }
-
-
-
-
- }
复制代码
|
|