最近在调试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("执行接收回调函数rn");
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;itot_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("收到数据:%srn",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:%drn",a);
if (a == 0)
{
while(lwip_comm_init()) //lwip 初始化
{
printf("LWIP Init Falied!rn");
}
// while(udp_demo_init()) //初始化udp_demo(创建udp_demo线程)
// {
// printf("UDP Init Falied!rn");
// }
// while(tcp_client_init()) //初始化tcp_client(创建tcp_client线程)
// {
// printf("TCP_CLIENT_INIT Init Falied!rn");
// }
// while(tcp_server_init()) //初始化tcp_server(创建tcp_server线程)
// {
// printf("TCP_SERVECE_INIT Init Falied!rn");
// }
while(igmp_demo_init()) //初始化udp_demo(创建udp_demo线程)
{
printf("IGMP Init Falied!rn");
}
#if LWIP_DHCP //这里LWIP_DHCP为0 使用静态IP地址
lwip_comm_dhcp_creat(); //创建DHCP任务
#endif
OSTaskSuspend(DP83848INIT_TASK_PRIO); //挂起任务.进入挂起态
}
OSTimeDly(200);
}
}
7 现象
|