|
发表于 2020-7-4 21:33:59
|
显示全部楼层
记得之前用的时候,连续通讯会出现无法收到数据的情况,看看勘误手册有没有
- /******************************************************************
- *Function : Enc28j60PacketReceive
- *Description: Enc28j60接收以太包
- *Input : packet:接收数据指针 len:数据长度
- *Output : NULL
- *Return : NULL
- *Others : NULL
- ******************************************************************/
- u16_t Enc28j60PacketReceive(u8_t *packet,u16_t maxlen)
- {
- u16_t rxstat;
- u16_t len;
- u16_t rs,re;
- u8_t temp;
- if( Enc28j60Read(EIR) & EIR_RXERIF )
- {//判断接收缓冲有无溢出,清理标志.
- // 跳转回BANK0,写0清标记.
- Enc28j60Bank = 0;
- Enc28j60SetBank(ECON1);
- Enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
- Enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_RXERIF);
- Enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
- }
- // 1.检测是否接收到数据包.
- if( !(Enc28j60Read(EIR) & EIR_PKTIF) )
- {// 勘误:单检测 EIR_PKTIF 并不可靠 双重检测: EPKTCNT.
- if (Enc28j60Read(EPKTCNT) == 0x00) return 0;
- }
-
- // 设置接收缓存 读取指针 不使用temp中间变量来设置似乎有问题,IDE编译时强制转换不同?.
- // Enc28j60Write(ERDPTL, (u8_t)(NextPacketPtr));.
- // Enc28j60Write(ERDPTH, (u8_t)(NextPacketPtr>>8));
- temp = (u8_t)(NextPacketPtr);
- Enc28j60Write(ERDPTL,temp);
- temp = (u8_t)(NextPacketPtr>>8);
- Enc28j60Write(ERDPTH,temp);
-
- // 2.读取下一包的起始指针 <低字节在前> .
- temp = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- NextPacketPtr = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- NextPacketPtr <<= 8;
- NextPacketPtr |= temp;
- // 3.读取以太包的长度 <status[15..0]低字节在前>.
- // 注:Wireshark监控 一帧APR时,长度是42字节;.
- // ENC28J60在这里读取的长度是60字节,结果是正常的,42+14(空数据)+4CRC.
- temp = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- len = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- len <<= 8;
- len &= 0xff00;
- len |= temp;
- len -= 4; //减去4字节CRC.
-
- // 4.读取以太包的状态<status[15..0]低字节在前>.
- temp = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- rxstat = Enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- rxstat <<= 8;
- rxstat |= temp;
- // 最小长度判断(we reduce the MAC-reported length by 4 to remove the CRC).
- len = MIN(len,maxlen);
-
- // 5.检测接收是否OK,拷贝出以太网数据.
- if ((rxstat & 0x80)==0)len=0;
- else Enc28j60ReadBuffer(packet,len);
-
- // .6.前移读指针到下一帧前,释放已读取缓冲(5.读数据过程中,ERXRDPTL没有增加).
- // .注意:必须先写数据到ERXRDPTL,再写数据到ERXRDPTH才能正确设置该寄存器 Datasheet45页.
- // . 前移无需考虑边界.没有释放缓,缓冲溢出会导致无法接收数据.
- //【ENC28J60勘误手册】 14. Module: Memory (Ethernet Buffer).
- rs = Enc28j60Read(ERXSTH);
- rs <<= 8;
- rs |= Enc28j60Read(ERXSTL);
-
- re = Enc28j60Read(ERXNDH);
- re <<= 8;
- re |= Enc28j60Read(ERXNDL);
- if (NextPacketPtr - 1 < rs || NextPacketPtr - 1 > re)
- {//检测有无跨界.
- temp = (u8_t)re;
- Enc28j60Write(ERXRDPTL, temp);
- temp = (u8_t)(re>>8);
- Enc28j60Write(ERXRDPTH, temp);
- }
- else
- {
- temp = (u8_t)(NextPacketPtr-1);
- Enc28j60Write(ERXRDPTL, temp);
- temp = (u8_t)((NextPacketPtr-1)>>8);
- Enc28j60Write(ERXRDPTH, temp);
- }
-
- // 7. 数据包个数递减位EPKTCNT减1.
- Enc28j60Bank = 0;
- Enc28j60SetBank(ECON1);
- Enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
-
- return len;
- }
复制代码 |
|