您的位置:首页 > 其它

STM32F103ZET6+ENC28J60+LWIP实现UDP组播

2017-05-04 18:10 211 查看
移植正点原子的UDP通信历程。

1.将ENC28J60_Write(ERXFCON,ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);//能实现UDP,TCP的收发。但组播数据不行。

   修改为ENC28J60_Write(ERXFCON,ERXFCON_CRCEN);//实现组播

2.打开LWIP中的IGMP。在opt.h文件中    #define LWIP_IGMP                       1

3.在ethernetif.c中的static err_t low_level_init(struct netif *netif)中,添加NETIF_FLAG_IGMP

netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP|NETIF_FLAG_IGMP;//添加IGMP

4.在lwip_comm.c中的void lwip_periodic_handle()中加入

#if LWIP_IGMP
if(lwip_localtime-IGMPTimer >= IGMP_TMR_INTERVAL)
{
IGMPTimer = lwip_localtime;

    igmp_tmr();

  }

 #endif

周期性处理igmp_tmr();函数

5.UDP初始化

void Init_UDP_Server(void)

{

    IP4_ADDR(&ipgroup, 224,0,0,50);//组播IP地址  

#if LWIP_IGMP  

    igmp_joingroup(IP_ADDR_ANY,(struct ip_addr *)(&ipgroup));//组播加入当前  

#endif  

    udp_server_pcb = udp_new();  

    if(udp_server_pcb!=NULL){  

        udp_bind(udp_server_pcb,IP_ADDR_ANY,9999);//组播端口  

        udp_recv(udp_server_pcb,udp_demo_recv,NULL);//接收回调函数  

    }  

}

6.添加组播发送函数

void multicast_send_data(unsigned char * data,unsigned short len)  

{  

    struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);  

    memcpy(p->payload, data, len);

        udp_sendto(udp_server_pcb, p,(struct ip_addr *) (&ipgroup),9999);  

    pbuf_free(p);  

}

7.UDP接受回调函数

//UDP回调函数

void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)

{
u32 data_len = 0;
struct pbuf *q;
if(p!=NULL)
//接收到不为空的数据时
{
memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零
for(q=p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
{
//判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于
//的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)) memcpy(udp_demo_recvbuf+data_len,q->payload,(UDP_DEMO_RX_BUFSIZE-data_len));//拷贝数据
else memcpy(udp_demo_recvbuf+data_len,q->payload,q->len);
data_len += q->len;  

if(data_len > UDP_DEMO_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出

}
upcb->remote_ip=*addr;
//记录远程主机的IP地址
upcb->remote_port=port;  
//记录远程主机的端口号
lwipdev.remoteip[0]=upcb->remote_ip.addr&0xff;
//IADDR4
lwipdev.remoteip[1]=(upcb->remote_ip.addr>>8)&0xff; //IADDR3
lwipdev.remoteip[2]=(upcb->remote_ip.addr>>16)&0xff;//IADDR2
lwipdev.remoteip[3]=(upcb->remote_ip.addr>>24)&0xff;//IADDR1 
udp_demo_flag|=1<<6;
//标记接收到数据了
pbuf_free(p);//释放内存
}else
{
udp_disconnect(upcb);
udp_demo_flag &= ~(1<<5);
//标记连接断开


}

8.编译会有几个错误,需要在def.h中加入

#define LWIP_RAND   rand

在lwipopts.h中

#define MEMP_NUM_SYS_TIMEOUT    6

在igmp.h中将group->timer = (LWIP_RAND() % (max_time - 1)) + 1;改为

group->timer = max_time + 1;

9.编译通过后运行,监听组播地址是224.0.0.50端口号是9999
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: