打印

ENC28J60数据发送成功,但对方就是没收到,怎么回事?

[复制链接]
8402|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yyywill|  楼主 | 2010-11-17 14:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ENC28J60数据发送成功,但对方就是没收到,怎么回事?
用的PIC18F单片机+ENC28J60,用官方的协议栈,一点问题都没有,ICMP,TCP,UDP都通。 但用网上的大家都在用的 Guido Socher 写的协议栈(ic_arp_udp_tcp.c和simple_sever.c), http://www.pic16.com/bbs/dispbbs.asp?boardid=33&Id=49773

ping的时候能接收到数据,发出回复的数据通过串口发出看了也是对的,但就是收不到响应数据。我在计算机上ping 192.168.1.50后,通过串口看到计算机发过来的数据里的MAC地址是板子的MAC地址,但如果发不出数据计算机也无法获取的板子的MAC。

在板子发送完后读取了 ESTAT 为 1 ,为发送成功,但就是收不到,怎么回事啊???
来自 2楼
yyywill|  楼主 | 2010-11-19 16:52 | 只看该作者
这年头碰到问题还得自己解决,发个帖都没人回.

问题终于解决了,下面说说问题在哪.
开始始终以为是始初化代码有问题,一直在那块找问题,废了好长时间.

计算机发送ARP数据包,可以响应.但板子接收数据不流畅,感觉接收有问题,
经过细细分析查找,终于发现问题在u16 enc28j60PacketReceive(u16 maxlen, u8* packet)函数中.
NextPacketPtr |= (enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8);
下面这个写法在MCC18中很有问题,改成如下写法:
temp = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
temp <<= 8;
NextPacketPtr |= temp;
还有
len |= (enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8);
rxstat |= (enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8);
也要改,板子数据接收流畅,没有问题.
(到这为止还以为MCC18不支持这种多步操作一行的写法)
ARP数据包可以发送出去,通过比较ARP和ICMP包响应函数发现,
void make_echo_reply_from_request(unsigned char* buf, unsigned  int len)
函数中调用了make_ip(buf),而该函数中又调了checksum函数,然后把该函数中的多步操作一行的写法
改成如下:
unsigned  int checksum(unsigned char* buf, unsigned  int len, unsigned char type)
{
        // type 0=ip
        //      1=udp
        //      2=tcp
        unsigned long sum = 0;
        unsigned int temp;
        //if(type==0){
        //        // do not add anything
        //}
        if (type == 1)
        {
                sum += IP_PROTO_UDP_V; // protocol udp
                // the length here is the length of udp (data+header len)
                // =length given to this function - (IP.scr+IP.dst length)
                sum += len;
                sum -= 8; // = real tcp len
        }
        else if (type == 2)
        {
                sum += IP_PROTO_TCP_V;
                // the length here is the length of tcp (data+header len)
                // =length given to this function - (IP.scr+IP.dst length)
                sum += len;
                sum -= 8; // = real tcp len
        }
        // build the sum of 16bit words
        while (len > 1)
        {
                temp = *buf;
                temp <<= 8;
                temp |= *(buf+1);
                temp &= 0xFFFF;
                sum += temp;
                buf += 2;
                len -= 2;
        }
        // if there is a byte left then add it (padded with zero)
        if (len)
        {
                temp = *buf;
                temp <<= 8;
                sum += temp;
        }
        // now calculate the sum over the bytes in the sum
        // until the result is only 16bit long
        while (sum >> 16)
        {               
                //sum = (sum & 0xFFFF) + (sum >> 16);
                temp = sum >> 16;
                sum &= 0xFFFF;
                sum += temp;
        }
        // build 1's complement:
        sum ^= 0xFFFF;
        return((unsigned  int) sum);
}
此时,ICMP包有响应,能PING通了, :)
再调UDP和TCP.
在调TCP的时候,发现下面这段
        init_len_info(buf); //计算有效数据长度,存到info_data_len中
        //可能无有效数据,只响应
        dat_p = get_tcp_data_pointer();//在buf中找到有效数据的起始地址
        if (dat_p == 0)//无有效数据
        {
                if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)//ACK=1,FIN=1 发送方已经没有数据发送了,用来释放连接
                {//客户端主动断开连接
                        // finack, answer with ack
                        make_tcp_ack_from_any(buf);
                }
                // just an ack with no data, wait for next packet
                continue;
        }
在TCP建立连接的时候,有一帧数据会进到这段,而有效数据长度(dat_p)应该为0,
实际测试发现建立连接的时候始终不为0,最后发现问题在init_len_info函数中,
temp = buf[IP_TOTLEN_H_P]<< 8;
改成
temp = buf[IP_TOTLEN_H_P];
temp <<= 8;
后,正常,至此终于发现MCC18中左移不能写成 a=b<<8;要写成a=b;a<<=8;
以上都是这个问题造成的,搞了好长时间,真是郁闷了好长时间.

在simpleserver.c中还有2个地方要改成如下:
if ( strncmpram2pgm((rom char *)"GET ", (char *)&buf[dat_p], 4) != 0 )
if (strncmpram2pgm((rom char *)"/ ", (char *) &(buf[dat_p + 4]), 2) == 0)

fill_tcp_data_p函数也要改:
unsigned  int fill_tcp_data_p(unsigned char* buf, unsigned  int pos,auto const rom char * progmem_s)
{
/*   char c;
   while( c = (char)*(progmem_s++) )   //#define  pgm_read_byte(ptr)  ((char)*(ptr))
   {
      buf[TCP_CHECKSUM_L_P + 3 + pos] = c;
      pos++;
   }*/
   unsigned  int len;
   
   //char *strcpypgm2ram (auto char *s1, auto const MEM_MODEL rom char *s2);
   strcpypgm2ram((char *)&buf[TCP_CHECKSUM_L_P + 3 + pos],progmem_s);
   len = strlenpgm(progmem_s);
   len += pos;
   return(len);
}

问题解决了,我还是写出来给大家一个参考.如果大家发帖有问题解决了,也希望大家说说怎么解决的,
不要就只说句"问题解决了".

如果我的问题对你有帮助,请你顶一下.

使用特权

评论回复
板凳
gengxuetao| | 2010-11-17 17:37 | 只看该作者
前一段时间也在用ENC28J60,用的是LWIP协议栈,出现的问题也很奇怪,发送间隔小于200MS就容易出现只能收不能发的情况,问题到现在还没有解决,原因查找中

使用特权

评论回复
地板
lou0908| | 2010-11-28 21:01 | 只看该作者
这年头热心人确实不多,顶LZ

使用特权

评论回复
5
ocon| | 2010-11-30 08:32 | 只看该作者
非普遍性的问题确实不好回答,想遇上一个用过和你同样方案的人就更难了,呵呵

使用特权

评论回复
6
自然的天逸| | 2010-11-30 11:25 | 只看该作者
没有用过 只有学习的份

使用特权

评论回复
7
kongformat| | 2010-12-26 09:39 | 只看该作者
学习中!

使用特权

评论回复
8
zhouxiaoliang| | 2011-1-25 14:32 | 只看该作者
LZ你的协议栈哪里找的啊,http://www.pic16.com/bbs/dispbbs.asp?boardid=33&Id=49773 这里,不完整啊

使用特权

评论回复
9
akingqin| | 2011-6-17 13:36 | 只看该作者
enc28j60

使用特权

评论回复
10
xzm7358| | 2012-4-15 21:18 | 只看该作者
学习中!楼主给力

使用特权

评论回复
11
Wobbi| | 2012-4-17 10:25 | 只看该作者
可以用彙編全部用自己的代碼, 找問題就容易得多了.

使用特权

评论回复
12
AppBaby| | 2012-5-4 17:06 | 只看该作者
可怜的lZ 这不是你的错..;P

使用特权

评论回复
13
abc97| | 2014-4-20 11:55 | 只看该作者
很好

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

29

帖子

0

粉丝