|
三個功能:
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死在里面
-
- }
-
-
-
-
- }
復制代碼
|
|