|
ENC28J60+UIP 组播和广播无法接收问题
[复制链接]
采用UIP进行组播和广播时遇到两个问题,一是无法接收组播数据;二是广播数据大于18字节时无法接收
检查组播数据接收时发现EPKTCNT寄存器显示是有数据的,但是UIP_UDP_APPCALL里面uip_newdata()为零表示无数据;因此猜测是uip把数据包丢弃了;
顺藤摸瓜,发现:
#if UIP_BROADCAST
DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
if(BUF->proto == UIP_PROTO_UDP &&
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
/*&&
uip_ipchksum() == 0xffff*/) {
goto udp_input;
}
#endif /* UIP_BROADCAST */
原来有宏定义,于是找到UIP_BROADCAST的定义,结果是另一个宏定义
#ifndef UIP_CONF_BROADCAST
#define UIP_BROADCAST 0
#else /* UIP_CONF_BROADCAST */
#define UIP_BROADCAST UIP_CONF_BROADCAST
#endif /* UIP_CONF_BROADCAST */
于是增加一句#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);
这次运行试试,果然成功了。
|
|