OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11084|回复: 4

lwip+stm32f407+IGMP 终于调通了

[复制链接]

11

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2016-3-23
在线时间
32 小时
发表于 2016-10-20 13:22:32 | 显示全部楼层 |阅读模式
最近在调试IGMP,在两个平台上分别调试,分别是 (1)lwip+stm32f407+IGMP+UCOSII +DP83848

(2)lwip+stm32f407+IGMP+LAN8720
先说第一个代操作系统的平台
关键步骤如下
1,dp83848初始化时,这个参数设置ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;                                                //开启接收所有的帧  这个参数一定要打开,否则IGMP接收失败。(前几天调试接收不到组播数据,就是因为这个配置出错)
2   LWIP中打开IGMP开关。opt.h中

      #define LWIP_IGMP                       1

3  .ethernetif.c文件中,low_level_init函数,使能IGMP标志

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

4  需要定时调用igmp_tmr(),由于 #define LWIP_IGMP                       1,已打开了IGMP,而且使用UCOSII操作系统,不需要专门处理igmp_tmr()。

此函数的调用是timers.c

5 def.h中定义
/**/
#define LWIP_RAND   rand //添加
/**/
#ifdef __cplusplus
}



6 相关函数,这里IGMP是作为一个进程单独运行的
//组播接收,回调函数  
void udp_server_rev(void *arg,struct udp_pcb* upcb,struct pbuf* p,struct ip_addr*addr ,u16_t port){  
  
    int i;  
    printf("执行接收回调函数\r\n");       
    if(p!=NULL){  
        if((p->tot_len)>=LWIP_DEMO_BUF){         //如果长度过长则额外处理         
            memcpy(lwip_demo_buf,p->payload,LWIP_DEMO_BUF);  
            lwip_demo_buf_len = LWIP_DEMO_BUF;  
        }else{               
            memcpy(lwip_demo_buf,p->payload,p->tot_len);  
            lwip_demo_buf_len = p->tot_len;  
        }  
      
     for(i=0;i<p->tot_len;i++)//测试组播时,有时候即使没发出去也可能显示收到,因此,我这里将收到的数据加2,以作区分  
        {  
            printf("%02x  ",lwip_demo_buf);  
            lwip_demo_buf=lwip_demo_buf+2;  
        }  
        printf("\n");   
                               
                                UDP_Send();
    }
                  
}  
   
static void igmp_thread(void *arg)
{
struct netconn *conn;  
struct ip_addr local_addr,group_addr,remote_addr;  
err_t err;
static struct netbuf  *recvbuf;
       
IP4_ADDR(&local_addr,192,168,4,211); //开发板IP地址
IP4_ADDR(&group_addr,230,0,0,6);  //组播地址
IP4_ADDR(&remote_addr,192,168,4,128);//主机地址
  
conn=netconn_new(NETCONN_UDP);
        if(conn!=NULL)
        {
                err=netconn_bind(conn,NULL,UDP_MULTICASE_RECV_PORT);                 
                err=netconn_join_leave_group(conn,&group_addr,&local_addr,NETCONN_JOIN);  
                while(1)  
                {  
                         netconn_recv(conn,&recvbuf); //接收数据       
                         if(recvbuf!=NULL)  
                         {  
                                 printf("收到数据:%s\r\n",recvbuf); //打印接收到的数据
                                 netconn_sendto(conn,recvbuf,&remote_addr,UDP_MULTICASE_SEND_PORT);  //把接收到的数据 再发送
                                 netbuf_delete(recvbuf);  
                         } else
                         OSTimeDlyHMSM(0,0,0,5);
                }
    netconn_delete(conn);               
        }
}


//创建IGMP线程
//返回值:0 igmp创建成功
//                其他 igmp创建失败
INT8U igmp_demo_init(void)
{
        INT8U res;
        OS_CPU_SR cpu_sr;
        OS_ENTER_CRITICAL();        //关中断
        res = OSTaskCreate(igmp_thread,(void*)0,(OS_STK*)&IGMP_TASK_STK[IGMP_STK_SIZE-1],IGMP_PRIO); //创建UDP线程
        OS_EXIT_CRITICAL();                //开中断
        return res;
}


void dp83848init_task(void *pdata)
{
        u8 a;
       
        while(1)
        {
                a=DP83848_Init();
        //        printf("a:%d\r\n",a);


                if (a == 0)
                {
                                        while(lwip_comm_init()) //lwip 初始化
                                {
                                printf("LWIP Init Falied!\r\n");
                                }
//                                while(udp_demo_init())                                                                                 //初始化udp_demo(创建udp_demo线程)
//                                {
//                                printf("UDP Init Falied!\r\n");
//                                }
//                                while(tcp_client_init())                                                                         //初始化tcp_client(创建tcp_client线程)
//                                {
//                                printf("TCP_CLIENT_INIT Init Falied!\r\n");
//                                }
//                                while(tcp_server_init())                                                                         //初始化tcp_server(创建tcp_server线程)
//                                {
//                                printf("TCP_SERVECE_INIT Init Falied!\r\n");
//                                }
                                while(igmp_demo_init())                                                                                 //初始化udp_demo(创建udp_demo线程)
                                {
                                printf("IGMP Init Falied!\r\n");
                                }
                                  #if LWIP_DHCP //这里LWIP_DHCP为0  使用静态IP地址
                                        lwip_comm_dhcp_creat();           //创建DHCP任务
                                        #endif       
                                OSTaskSuspend(DP83848INIT_TASK_PRIO);        //挂起任务.进入挂起态
                }
               
                OSTimeDly(200);
        }                       

}


7 现象

QQ截图20161020131509.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2016-3-23
在线时间
32 小时
 楼主| 发表于 2016-10-20 13:30:33 | 显示全部楼层
本帖最后由 jihaolin 于 2016-10-20 13:38 编辑

对于第二个平台,1,2,3.部为完全相同,第四步在lwip_comm.c文件中48行左右添加#ifdef LWIP_IGMP
u32  IGMPTimer=0;
#endif

然后在void lwip_periodic_handle(void)函数中添加
#if LWIP_IGMP
  if(lwip_localtime-IGMPTimer>=IGMP_TMR_INTERVAL)
  {
    IGMPTimer=lwip_localtime;
    igmp_tmr();
  }
#endif

第五步 完全相同
第六步代码见源文件

igmp_demo.zip

2.77 KB, 下载次数: 544

源文件

回复 支持 1 反对 0

使用道具 举报

11

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2016-3-23
在线时间
32 小时
 楼主| 发表于 2016-10-20 13:25:27 | 显示全部楼层
#define UDP_MULTICASE_RECV_PORT 9090   // multicast port for recive  
#define UDP_MULTICASE_SEND_PORT 8080   // multicast port for send  
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-7-25
在线时间
0 小时
发表于 2017-7-25 11:24:27 | 显示全部楼层
网上找了半天,才发现这个好东西,感谢楼主啊,特地给你注册一个号,点赞
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2019-11-7
在线时间
1 小时
发表于 2019-11-7 12:15:31 | 显示全部楼层
本帖最后由 lky2417 于 2019-11-7 12:40 编辑

感谢楼主!
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 17:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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