采用UIP進行組播和廣播時遇到兩個問題,一是無法接收組播數據;二是廣播數據大于18字節時無法接收
檢查組播數據接收時發現EPKTCNT寄存器顯示是有數據的,但是UIP_UDP_APPCALL里面uip_newdata()為零表示無數據;因此猜測是uip把數據包丟棄了;
順藤摸瓜,發現:
#if UIP_BROADCAST
DEBUG_PRINTF("UDP IP checksum 0xx\n", uip_ipchksum());
if(BUF->proto == UIP_PROTO_UDP &&
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
) {
goto udp_input;
}
#endif
原來有宏定義,于是找到UIP_BROADCAST的定義,結果是另一個宏定義
#ifndef UIP_CONF_BROADCAST
#define UIP_BROADCAST 0
#else
#define UIP_BROADCAST UIP_CONF_BROADCAST
#endif
于是增加一句#define UIP_CONF_BROADCAST 1,繼續運行,
結果發現還是沒有效果,于是回到剛才的程序,這才恍然大悟,原來是通過
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
來進行判定,其中all_ones_addr定義為全部都是F,也就是255.255.255.255,所以只要廣播數據才會進入udp_input,自己的數據包是192.168.1.255,所以被丟棄
找到問題之后就容易解決了,在下面增加一段程序
if(BUF->proto == UIP_PROTO_UDP &&
((BUF->destipaddr[1]&0xFF00)==0xFF00)) {
goto udp_input;
}
作用就是判定ip地址最后一位是否為255,如果是則進入udp_input,修改完成之后,發幾個數據試試,運行果然就正確了。
可是在正式使用時發現又不行了,繼續加斷點找,這次發現是ENC28J60沒有收到,EPKTCNT一直為0;經過反復試驗,發現只要18字節以內就能收的到,大于就收不到了。上網搜一下發現有大神說要配置ENC28J60,于是找到ERXFCON寄存器,其中最低兩位為1表示接收,于是在初始化時配置一下,設置為接收數據包:
temp=enc28j60Read(ERXFCON);
temp=temp|0x03;
enc28j60Write(ERXFCON,temp);
這次運行試試,果然成功了。
|