问题出现在arp阶段,MCU可以正常接收arp数,并且使用UIP解析正常,但是向电脑端响应arp请求时,通过Wireshark发现接收到的响应arp包数据格式不正常!
#define UIP_BUF ((struct uip_eth_hdr *)&uip_buf[0])
tapdev_init();//初始化enc28j60
print("init enc28j60 success!");
uip_init();
uip_ipaddr_t ipaddr;
uip_ipaddr(ipaddr, 192, 168, 1, 8);
uip_sethostaddr(ipaddr);
uip_ipaddr(ipaddr, 192, 168, 1, 1);
uip_setdraddr(ipaddr);
uip_ipaddr(ipaddr, 255, 255, 252, 0);
uip_setnetmask(ipaddr);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
uip_len = tapdev_read();//uip_len在uip.c中声明
if(uip_len == 0){
continue;
}
print("ok");
if(UIP_BUF->type == htons(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
if(uip_len>0){
print("rarp package send!!!");
print3((char*)uip_buf, uip_len);
tapdev_send();
}
}
/* USER CODE BEGIN 3 */
}
tapdev.c 实现enc28j60收发代码:
#include <tapdev.h>
#include "enc28j60.h"
#include <uip.h>
//引用uip.c中声明的uip_ethaddr
extern struct uip_eth_addr uip_ethaddr;
//MAC
unsigned char my_mac[6] = {0x29, 0x7C, 0x07, 0x37, 0x24, 0x63};
void tapdev_init(void)
{
enc28j60Init(my_mac);
for (int i = 0; i < 6; i++)
{
uip_ethaddr.addr[i] = my_mac[i];
}
}
unsigned int tapdev_read(void)
{
enc28j60PacketReceive(MAX_FRAMELEN, uip_buf);
}
void tapdev_send(void)
{
enc28j60PacketSend(uip_len, uip_buf);
}
更详细代码已上上传到蓝奏云,如果不愿下载,请评论通知我,我会尽快回复!
怀疑是用cubemx 生成代码时,SPI配置有问题,请帮忙确认, 非常感谢!
全部代码:
https://wwb.lanzouw.com/iNiJSxx0bah 密码:e5bk
使用cubemx + keil5
目前就想用uip ,实现电脑可以ping通的效果。
本人第一次使用SPI接口,非常希望各位能给一些解决办法的思路,非常感谢!
问题已解决,在调用驱动的写缓冲区操作(enc28j60WriteBuffer)时,写数据前,没有先执行写缓冲区命令,直接写入的数据,导致数据不正常:
void enc28j60WriteBuffer(unsigned int len, unsigned char* data)
{
ENC28J60_CSL();
// issue write command
/* 通过SPI发送写取缓冲区命令*/
SPI1_ReadWrite(ENC28J60_WRITE_BUF_MEM);//没有调用这句
while(len)
{
len--;
SPI1_ReadWrite(*data);
data++;
}
ENC28J60_CSH();
}
遇见这种问题,如果想测试发送包是否正常,可以先手动调用enc28j60PacketSend(len, data)函数,比如调用enc28j60PacketSend发送0xAA,0xBB,0xCC十六进制数据,通过Wireshark拦截消息,看是否有接收到MCU发送数据包,并且发送数据包数据是否为0xAA,0xBB,0xCC.如果可以正常接收并且准确接收AA,BB,CC,表示驱动发送功能正常。
最后有些驱动函数名称有些区别,贴一下enc28j60PacketSend实现:
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
{
// Set the write pointer to start of transmit buffer area
enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
enc28j60Write(EWRPTH, TXSTART_INIT>>8);
// Set the TXND pointer to correspond to the packet size given
enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
// write per-packet control byte (0x00 means use macon3 settings)
enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
// copy the packet into the transmit buffer
enc28j60WriteBuffer(len, packet);
// send the contents of the transmit buffer onto the network
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
// Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
if( (enc28j60Read(EIR) & EIR_TXERIF) )
{
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
}
}
有关和enc28j60的一接线些信息,麻烦可以看一下上次提问的问题:
https://ask.csdn.net/questions/7608372?answer=53634904
上次中间加了一个路由器,这次是enc28j60直连电脑。正因为上次电脑和enc28j60中间有一个路由器,路由器拦截了错误格式的数据包,给我的现象是enc28j60没有发送数据,其实发送了,被路由器拦截了……
之前使用的协议栈好像不是官方写的,所以怀疑是代码的问题,所以换uip,但问题依旧,严重怀疑是在cubemx配置SPI配置的不对...
另外在ENC28J60说明书中,看到了接口的一些信息:
建议先测试一下ENC28J60的发送函数,感觉发出来的数据完全是乱的。
如果你怀疑SPI没有配置正确,可以把接收到的包用串口打印下来看看是否和wireshark里抓到的一致,如果一致,那SPI应该没有问题,接收过程,其实SPI是有读有写的。