找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4307|回复: 0
打印 上一主题 下一主题
收起左侧

UDP数据发送程序,缓冲区可以扩展,不过得有足够的SRAM

[复制链接]
跳转到指定楼层
楼主
ID:82781 发表于 2015-6-13 16:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
三个功能:
1.UDP标准配置
2.IP校验
3.向以太网中送UDP包!

  1. /**本函数是一个类初始化函数
  2.    主要是一些不变的参数和部分数据的初始化
  3.    **/
  4. void UDP_Frame_Set(
  5.      TypeDef_MAC_Frame_H *MAC_Frame,
  6.      TypeDef_IP_Frame_H  *IP_Frame,
  7.      TypeDef_UDP_Frame_H *UDP_Frame
  8.      )//设置UDP相关参数
  9. {


  10.   /**

  11.     整个UDP帧是由
  12.     MAC帧+IP帧+UDP帧构成的!!!!!
  13.    编译器要开在大端模式!主要考虑用的外部RAM
  14.   */
  15.   /*****MAC部首设置***************************************************/  
  16.            /********目标MAC地址***************/
  17.      MAC_Frame->Destination_MAC[0]=0;
  18.     MAC_Frame->Destination_MAC[1]=0;
  19.     MAC_Frame->Destination_MAC[2]=0;
  20.     MAC_Frame->Destination_MAC[3]=0;
  21.     MAC_Frame->Destination_MAC[4]=0;
  22.     MAC_Frame->Destination_MAC[5]=0;
  23.      /********源MAC地址*************/
  24.     MAC_Frame->Source_add_MAC[0]=0x00;
  25.     MAC_Frame->Source_add_MAC[1]=0x26;
  26.     MAC_Frame->Source_add_MAC[2]=0x9E;
  27.     MAC_Frame->Source_add_MAC[3]=0xC7;
  28.     MAC_Frame->Source_add_MAC[4]=0x6C;   //本机MAC固定的
  29.     MAC_Frame->Source_add_MAC[5]=0xF3;
  30.      /********类型长度******8*****/
  31.        MAC_Frame->Type[0]=0x08;
  32.        MAC_Frame->Type[1]=0x00;//0X0800IP包 0x0806ARP
  33. /**************IP部首设置**************************************************/
  34.     IP_Frame ->IP_Version_Head=0x45;//IP版本是4,部首长度是20个字节
  35.     IP_Frame ->IP_Tos=0;//IP的TOS一般设为0
  36.     IP_Frame ->IP_Total_Length[0]=0;//设置总长度
  37.     IP_Frame ->IP_Total_Length[1]=0;//设置总长度
  38.     IP_Frame ->IP_Indentification[0]=0;
  39.     IP_Frame ->IP_Indentification[1]=1; //标识字段,发送一个都会加一
  40.     IP_Frame ->IP_Flage_FRAGMENT_OFFSET[0]=0;    //3位标识和片偏移,这里是指IP分片,尽量不产生IP分片
  41.     IP_Frame ->IP_Flage_FRAGMENT_OFFSET[1]=0;
  42.     IP_Frame ->IP_TTL=64;//生存时间默认为32或者64,过一个路由器减去一!当此值为0此份报文被丢弃
  43.     IP_Frame ->IP_Protocol=0x11;//表示协议,这是UDP协议
  44.     /*IP部首校验和*/
  45.     IP_Frame ->IP_Check_sum[0]=0;
  46.     IP_Frame ->IP_Check_sum[1]=0; //0;
  47.      /*本机IP*/
  48.     IP_Frame ->IP_Source[0]=192;
  49.     IP_Frame ->IP_Source[1]=168;
  50.     IP_Frame ->IP_Source[2]=1;
  51.     IP_Frame ->IP_Source[3]=233;
  52.      /*目标IP地址这个得由ARP获得这里做初始化设置*/
  53.     IP_Frame ->IP_Dstination[0]=0;
  54.     IP_Frame ->IP_Dstination[1]=0;
  55.     IP_Frame ->IP_Dstination[2]=0;
  56.     IP_Frame ->IP_Dstination[3]=0;
  57. /***************UDP设置***************************************/

  58.        UDP_Frame->UDP_Source_Port[0]=0x1f;
  59.     UDP_Frame->UDP_Source_Port[1]=0x90;//源端口是8080
  60.     UDP_Frame->UDP_Dstination_Port[0]=0x1f;
  61.     UDP_Frame->UDP_Dstination_Port[1]=0x90;//目标端口是8080
  62.     /*这个长度也得有实际数据决定
  63.    他的长度是UDP长度+数据比如数据长度是1个字节, 那么
  64.    这个长度就是UDP部首+1=8个字节+1个字节=9
  65.          
  66.    */
  67.      // UDP_Frame->UDP_Length[0]=0;
  68.   // UDP_Frame->UDP_Length[1]=0;
  69.    /*
  70.   校验和也是得有数据才可以算出来,这里只是 初次赋值!!
  71.    */
  72.    UDP_Frame->UDP_check_sum[0]=0;
  73.    UDP_Frame->UDP_check_sum[1]=0;
  74.    //UDP_Frame->UDP_Data[0];//数据



  75. }
  76. /***************************************
  77. IP部首的校验和!他把IP部首看做是一连串的16位
  78. 数据,然后把这些数据加起来然后取反,所谓的二进制
  79. 反码求和,并不是字面上的先去凡在求和,其实是相加后再取反!!坑爹啊
  80. 他的作用是:
  81. 1.在发送端他首先把校验字段清0,其后进行二进制反码求和,
  82. 结果送到校验子段,
  83. 2。在发送端他接收到后直接的把所有数据进行反码求和,然后再读取这个值,如果是0,那么是对的,如果不是
  84. 那么证明这个IP数据帧是有问题的应该丢弃或者发送差错报文!
  85. 2012年3月3日
  86. 日照高科园
  87. 王均伟
  88. ************************************/
  89. uint IP_Check_Sum_Verify(TypeDef_IP_Frame_H *IP_Frame_Sum)
  90. {
  91. /*
  92.      一下算法源于百度,感谢再感谢!!
  93.      计算对IP首部检验和的算法如下:  
  94.    (1)把IP数据包的校验和字段置为0;
  95.   (2)把首部看成以16位为单位的数字组成,依次进行二进制求和
  96.         (注意:求和时应将最高位的进位保存,所以加法应采用32位加法);
  97.   (3)将上述加法过程中产生的进位(最高位的进位)加到低16位
  98.        (采用32位加法时,即为将高16位与低16位相加,之后还要把该次加
  99.          法最高位产生的进位加到低16位)
  100.   (4)将上述的和取反,即得到校验和。

  101.    2012年3月3日于日照高科园
  102.    按照以上算法便可以!
  103. */
  104. xdata unsigned long a,b;
  105. xdata uchar i;
  106.     xdata uint tab[10];
  107. xdata uint msb,lsb;
  108.   
  109. msb=IP_Frame_Sum->IP_Version_Head; //IP的版本号和IP的部首长度,默认为0X45,版本是4,部首是20字节
  110.     msb=msb<<8;
  111. lsb=IP_Frame_Sum->IP_Tos; //ip的TOS据我抓包观察一般是00
  112. tab[0]=msb+lsb;
  113. msb=IP_Frame_Sum->IP_Total_Length[0];//总数据报文长度
  114. msb=msb<<8;
  115. lsb=IP_Frame_Sum->IP_Total_Length[1];//总数据报文长度
  116. tab[1]=msb+lsb;
  117. msb=IP_Frame_Sum->IP_Indentification[0];//IP标识字段,标识字段唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1
  118. msb=msb<<8;
  119. lsb=IP_Frame_Sum->IP_Indentification[1];
  120. tab[2]=msb+lsb;

  121.    msb=IP_Frame_Sum->IP_Flage_FRAGMENT_OFFSET[0];//标志位和片偏移
  122.    msb=msb<<8;
  123.    lsb=IP_Frame_Sum->IP_Flage_FRAGMENT_OFFSET[1];//标志位和片偏移
  124.     tab[3]=msb+lsb;
  125.     msb=IP_Frame_Sum->IP_TTL; //生存时间
  126.   msb=msb<<8;
  127. lsb=IP_Frame_Sum->IP_Protocol; //协议类型
  128. tab[4]=msb+lsb;
  129. msb=IP_Frame_Sum->IP_Check_sum[0];//部首校验和
  130. msb=msb<<8;
  131. lsb=IP_Frame_Sum->IP_Check_sum[0];//部首校验和
  132. tab[5]=msb+lsb;
  133.     msb=IP_Frame_Sum->IP_Source[0];//32IP位源地址
  134. msb=msb<<8;
  135. lsb=IP_Frame_Sum->IP_Source[1];//32IP位源地址
  136. tab[6]=msb+lsb;
  137. msb=IP_Frame_Sum->IP_Source[2];//32IP位源地址
  138. msb=msb<<8;
  139. lsb=IP_Frame_Sum->IP_Source[3];//32IP位源地址
  140. tab[7]=msb+lsb;
  141. msb=IP_Frame_Sum->IP_Dstination[0];//32位IP目标地址
  142. msb=msb<<8;
  143. lsb=IP_Frame_Sum->IP_Dstination[1];//32位IP目标地址
  144. tab[8]=msb+lsb;
  145. msb=IP_Frame_Sum->IP_Dstination[2];//32位IP目标地址
  146. msb=msb<<8;
  147. lsb=IP_Frame_Sum->IP_Dstination[3];//32位IP目标地址
  148. tab[9]=msb+lsb;
  149.   /**我操原来是没有清空变量草,费了我一天时间,我说第一次运行正确,其后不对
  150. 没有清零!我擦我操!
  151. 2012年3月7日
  152. 日照高科园
  153. 王均伟*/   
  154.   
  155.    a=0;  //清零
  156.    b=0;
  157.    
  158.    for(i=0;i<10;i++)
  159.    {
  160.    a=a+tab[i]; //变量加
  161. b=a;//暂存A中
  162. b+=(a>>16)&0x0000ffff; //取高位与地位相加,并且加完了清0高八位
  163. }
  164.     b=~b; //取反

  165.    return b;
  166. }
  167. /*******************************8


  168.    发送UDP数据包
  169.   指定目标IP,本地IP,本地端口,目标端口
  170.   还有数据大小,什么数据,第几个包
  171.         uchar *MAC_Target_add,//MAC地址。一般情况下由ARP计算得出
  172.                         uchar *IP_Source_add,//IP源地址
  173.         uchar *IP_Target_add,//IP目标地址
  174.         uint   UDP_Source_Port,UDP源端口
  175.         uint   UDP_Target_Port,UDP目标端口
  176.         uchar * UDP_Send_Data, UDP数据
  177.         uchar UDP_Send_Data_length UDP数据长度
  178. **********************************/
  179. void Send_UDP_packet(   uchar *MAC_Target_add,
  180.         uchar *IP_Target_add,
  181.         uchar *UDP_Source_Port,
  182.         uchar *UDP_Target_Port,
  183.         uchar *UDP_Send_Data,
  184.         uchar UDP_Send_Data_length
  185.        )
  186. {

  187. TypeDef_MAC_Frame_H xdata  MAC_Frame_H;//MAC定义一个结构体头
  188. TypeDef_IP_Frame_H  xdata  IP_Frame_H; //IP定义一个结构体头
  189. TypeDef_UDP_Frame_H xdata  UDP_Frame_H;//UDP定义数据结构  
  190. xdata uchar  d;
  191. xdata uchar MSB,LSB;   //中间量
  192. xdata uint da; //
  193.    /*传递了一个结构指针进去指向了上面建立的变量
  194.        就是建立了一个映射,把所有的都映射了,
  195.     目的是要初始化
  196.     表示这里面的都是标准配置,一般不改变
  197.     要随时改变的就在这个函数下面设置了
  198.     比如MAC_Frame_H.Destination_MAC
  199.     他是个传递参量!
  200.      */
  201. UDP_Frame_Set(&MAC_Frame_H,&IP_Frame_H,&UDP_Frame_H);//设置UDP相关参数

  202.      /*MAC目标地址*/
  203.   MAC_Frame_H.Destination_MAC[0]=MAC_Target_add[0];
  204.   MAC_Frame_H.Destination_MAC[1]=MAC_Target_add[1];
  205.   MAC_Frame_H.Destination_MAC[2]=MAC_Target_add[2];
  206.   MAC_Frame_H.Destination_MAC[3]=MAC_Target_add[3];
  207.   MAC_Frame_H.Destination_MAC[4]=MAC_Target_add[4];
  208.   MAC_Frame_H.Destination_MAC[5]=MAC_Target_add[5];
  209.      /*IP目标地址*/
  210.   IP_Frame_H.IP_Dstination[0]=IP_Target_add[0];
  211.   IP_Frame_H.IP_Dstination[1]=IP_Target_add[1];
  212.   IP_Frame_H.IP_Dstination[2]=IP_Target_add[2];
  213.   IP_Frame_H.IP_Dstination[3]=IP_Target_add[3];
  214.       //数据长度,
  215. /*这个长度等于IP部首20字节+UDP部首8字节+UDP数据,这里是1字节UDP_Send_Data_length表示这是数据长度*/
  216.     da=28+UDP_Send_Data_length;
  217.     LSB=da;
  218.              MSB=(da>>8)&0x00ff;
  219.   IP_Frame_H.IP_Total_Length[0]=MSB;//设置总长度
  220.   IP_Frame_H.IP_Total_Length[1]=LSB;//设置总长度  //29字节
  221.          
  222.    
  223.     /*加入IP校验和*/
  224. da=IP_Check_Sum_Verify(&IP_Frame_H); //计算IP部首校验和
  225. LSB=da;
  226. MSB=(da>>8)&0x00ff;
  227. IP_Frame_H.IP_Check_sum[0]=MSB;
  228. IP_Frame_H.IP_Check_sum[1]=LSB; //写入IP部首校验和

  229. /*****************UDP***********************/
  230.   UDP_Frame_H.UDP_Source_Port[0]=UDP_Source_Port[0];
  231.   UDP_Frame_H.UDP_Source_Port[1]=UDP_Source_Port[1];//源端口是8080
  232.   UDP_Frame_H.UDP_Dstination_Port[0]=UDP_Target_Port[0];
  233.   UDP_Frame_H.UDP_Dstination_Port[1]=UDP_Target_Port[1];//目标端口是8080
  234.     /*这个长度也得有实际数据决定
  235.    他的长度是UDP长度+数据比如数据长度是1个字节, 那么
  236.    这个长度就是UDP部首+1=8个字节+1个字节=9
  237.          
  238.    */
  239.    da=8+UDP_Send_Data_length; //计算UDP数据长度
  240.     LSB=da;
  241.              MSB=(da>>8)&0x00ff;
  242.       UDP_Frame_H.UDP_Length[0]=MSB;
  243.    UDP_Frame_H.UDP_Length[1]=LSB;
  244.            /*加载数据*/
  245.        //注意这里的UDP数据我只分配了10个字节,要想加大数据量就得改结构体!
  246.    for(d=0;d<UDP_Send_Data_length;d++)
  247.    {
  248.       UDP_Frame_H.UDP_Data[d]=UDP_Send_Data[d];//数据写入
  249.    }

  250. //以上实际上就是设置了三个结构体,全部围绕这三个结构体展开的
  251.    
  252. /*              物理操作            */
  253. set_send_buffer_add(0x0200,0x023f);//缓冲区的大小设定,开始200结束1fff

  254. write_buffer_add(0x0200,0x0e);//控制字节
  255. //        MAC
  256. write_buffer_add(0x0201,MAC_Frame_H.Destination_MAC[0]);//
  257. write_buffer_add(0x0202,MAC_Frame_H.Destination_MAC[1]);//
  258. write_buffer_add(0x0203,MAC_Frame_H.Destination_MAC[2]);//
  259. write_buffer_add(0x0204,MAC_Frame_H.Destination_MAC[3]);//
  260. write_buffer_add(0x0205,MAC_Frame_H.Destination_MAC[4]);//   MAC目的地址
  261. write_buffer_add(0x0206,MAC_Frame_H.Destination_MAC[5]);//
  262. write_buffer_add(0x0207, MAC_Frame_H.Source_add_MAC[0]);//
  263. write_buffer_add(0x0208, MAC_Frame_H.Source_add_MAC[1]);//
  264. write_buffer_add(0x0209, MAC_Frame_H.Source_add_MAC[2]);//  MAC源地址
  265. write_buffer_add(0x020A, MAC_Frame_H.Source_add_MAC[3]);//
  266. write_buffer_add(0x020B, MAC_Frame_H.Source_add_MAC[4]);//
  267. write_buffer_add(0x020C, MAC_Frame_H.Source_add_MAC[5]);//
  268. write_buffer_add(0x020D, MAC_Frame_H.Type[0]);//   MAC类型
  269. write_buffer_add(0x020E, MAC_Frame_H.Type[1]);//
  270.    

  271.     //IP
  272. write_buffer_add(0x020F,IP_Frame_H.IP_Version_Head);//
  273. write_buffer_add(0x0210,IP_Frame_H.IP_Tos);//
  274. write_buffer_add(0x0211,IP_Frame_H.IP_Total_Length[0]);
  275. write_buffer_add(0x0212,IP_Frame_H.IP_Total_Length[1]);
  276. write_buffer_add(0x0213,IP_Frame_H.IP_Indentification[0]);
  277. write_buffer_add(0x0214,IP_Frame_H.IP_Indentification[1]);
  278. write_buffer_add(0x0215,IP_Frame_H.IP_Flage_FRAGMENT_OFFSET[0]);
  279. write_buffer_add(0x0216,IP_Frame_H.IP_Flage_FRAGMENT_OFFSET[1]);
  280. write_buffer_add(0x0217,IP_Frame_H.IP_TTL);
  281. write_buffer_add(0x0218,IP_Frame_H.IP_Protocol);
  282. write_buffer_add(0x0219,IP_Frame_H.IP_Check_sum[0]);
  283. write_buffer_add(0x021A,IP_Frame_H.IP_Check_sum[1]);
  284. write_buffer_add(0x021B,IP_Frame_H.IP_Source[0]);
  285. write_buffer_add(0x021C,IP_Frame_H.IP_Source[1]);
  286. write_buffer_add(0x021D,IP_Frame_H.IP_Source[2]);
  287. write_buffer_add(0x021E,IP_Frame_H.IP_Source[3]);
  288. write_buffer_add(0x021F,IP_Frame_H.IP_Dstination[0]);
  289. write_buffer_add(0x0220,IP_Frame_H.IP_Dstination[1]);
  290. write_buffer_add(0x0221,IP_Frame_H.IP_Dstination[2]);
  291. write_buffer_add(0x0222,IP_Frame_H.IP_Dstination[3]);

  292.        //UDP
  293. write_buffer_add(0x0223,UDP_Frame_H.UDP_Source_Port[0]);
  294. write_buffer_add(0x0224,UDP_Frame_H.UDP_Source_Port[1]);
  295. write_buffer_add(0x0225,UDP_Frame_H.UDP_Dstination_Port[0]);
  296. write_buffer_add(0x0226,UDP_Frame_H.UDP_Dstination_Port[1]);
  297. write_buffer_add(0x0227,UDP_Frame_H.UDP_Length[0]);
  298. write_buffer_add(0x0228,UDP_Frame_H.UDP_Length[1]);
  299. write_buffer_add(0x0229,UDP_Frame_H.UDP_check_sum[0]);
  300. write_buffer_add(0x022A,UDP_Frame_H.UDP_check_sum[1]);
  301.     //数据  //发送数量UDP_Send_Data_length
  302.             //数据在 UDP_Frame_H.UDP_Data[]里;
  303.    
  304.     for(d=0;d<UDP_Send_Data_length;d++)
  305.     {
  306. write_buffer_add((0x022B+d),UDP_Frame_H.UDP_Data[d]);
  307.    
  308.     }

  309. write_ENC28J60_REG_SPI(ECON1,0x0c);//允许发送,允许接收
  310.   for(;;)
  311.   {

  312.    d=read_ENC28J60_REG_SPI(EIR);//读取数据包接收标志位
  313.    if((d&0x08)==0x08)break;  //发送完毕??OK退出ifNO死在里面
  314.   
  315.      }   




  316. }
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表