由于公司需要,最近接触了w5500这款嵌入式以太网控制器
TS-W5500模块特点:
1、尺寸小:5CM*3CM
2、4层板设计并了TVS等保护IC,差分走线,保障了良好的EMC兼容性
3、5V、3V单片机都兼容
W5500
W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加简易
的互联网连接方案。W5500集成了TCP/IP协议栈,10/100M以太网数据链路层(MAC)
及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。
久经市场考验的WIZnet全硬件TCP/IP协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP 以
及PPPoE协议。W5500内嵌32K字节片上缓存以供以太网包处理。如果你使用W5500,
你只需要一些简单的Socket编程就能实现以太网应用。这将会比其他嵌入式以太网方案
更加快捷、简便。用户可以同时使用8个硬件Socket独立通讯。
W5500提供了SPI(外设串行接口)从而能够更加容易与外设MCU整合。而且,
W5500的使用了新的高效SPI协议支持80MHz速率,从而能够更好的实现高速网络通讯。
为了减少系统能耗,W5500提供了网络唤醒模式(WOL)及掉电模式供客户选择使用。
参考资源:http://bbs.21ic.com/icview-825510-1-1.html
程序是参考飞鸿踏雪的例程,在这里我分享下跟人开发中遇到的问题及解决办法。
1、将飞鸿踏雪的文件加入到自己的工程后,初始化会死机在
/* PHY link status check */
do{
if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){
printf("Unknown PHY Link stauts.\r\n");
}
}while(tmp == PHY_LINK_OFF);
这个地方。
解决办法:
检查SPI驱动程序是否配置正确,片选引脚、复位引脚是否正确配置并和实际硬件对应,这个地方出问题属于物理链路层的问题检查软件驱动和硬件接线,应该可以解决问题。
2、移植飞鸿踏雪的服务器程序进行测试,发现网络接口处的两个指示灯并未亮或闪烁,服务器程序肯定没跑通。
问题原因,公司同事在做pcb板时忘记将5500的通讯引脚和接口的通信引脚相连,经过一番周折,用导线将引脚一个一个连接上,在进行测试,指示灯终于亮了,信心大增。
3、解决通讯线问题后更新完程序,将板子用网线通过一个分线盒和电脑连接上,此时电脑连接的是路由器,IP为192.168.31.166,板子本地IP设置为192.168.123进行测试发现不能ping通,
解决办法,直接用网线将电脑和板子连接,关闭路由器,社本地IP为192.168.0.101,设置板子IP为192.168.0.100,再次进行测试,可以ping通了。完善程序中的端口配置,打开pc端tcpIP客户端,设置为tcpclient,测试连接目标板IP,可以连接上并能进行通信。
/**
* @brief TCP服务器
* @retval None
*/
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret;
uint16_t size = 0, sentsize=0;
switch(getSn_SR(sn))
{
case SOCK_ESTABLISHED :
if(getSn_IR(sn) & Sn_IR_CON)
{
printf("%d:Connected\r\n",sn);
setSn_IR(sn,Sn_IR_CON);
}
if((size = getSn_RX_RSR(sn)) > 0)
{
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
ret = recv(sn,buf,size);
if(ret <= 0) return ret;
sentsize = 0;
while(size != sentsize)
{
ret = send(sn,buf+sentsize,size-sentsize);
if(ret < 0)
{
close(sn);
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
}
break;
case SOCK_CLOSE_WAIT :
printf("%d:CloseWait\r\n",sn);
if((ret=disconnect(sn)) != SOCK_OK) return ret;
printf("%d:Closed\r\n",sn);
break;
case SOCK_INIT :
printf("%d:Listen, port [%d]\r\n",sn, port);
if( (ret = listen(sn)) != SOCK_OK) return ret;
break;
case SOCK_CLOSED:
printf("%d:LBTStart\r\n",sn);
if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)
return ret;
printf("%d:Opened\r\n",sn);
break;
default:
break;
}
return 1;
}
4、测试将板子作为客户端,PC为服务器,移植飞鸿踏雪的例程,配置好服务器客户端端口,发现老是timeout,程序卡在
经过一顿百度,卡在此处是本地发出请求,没有应答,所以socket不会处于就绪状态。
解决办法是关闭电脑的防火墙,再次进行测试就ok了。
int32_t loopback_tcpclient(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret;
uint16_t size = 0, sentsize=0;
switch(getSn_SR(sn))
{
case SOCK_INIT :
printf("%d:connect [%d]\r\n",sn, Server_Port);
if(connect(sn,Server_IP,Server_Port) != SOCK_OK)
{
disconnect(sn);
}
break;
case SOCK_ESTABLISHED ://socket0Á¬½Ó½¨Á¢
if(getSn_IR(sn) & Sn_IR_CON)
{
printf("%d:Connected\r\n",sn);
setSn_IR(sn,Sn_IR_CON);
}
if((size = getSn_RX_RSR(sn)) > 0)
{
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
ret = recv(sn,buf,size);
if(ret <= 0) return ret;
sentsize = 0;
while(size != sentsize)
{
ret = send(sn,buf+sentsize,size-sentsize);
if(ret < 0)
{
close(sn);
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
}
break;
case SOCK_CLOSE_WAIT ://socket0µÈ´ý¹Ø±Õ
printf("%d:CloseWait\r\n",sn);
if((disconnect(sn)) != SOCK_OK)
break;
case SOCK_CLOSED://socket0¹Ø±Õ£¬´ò¿ªsocket0µÄÒ»¸ö¶Ë¿Ú
printf("%d:ClientStart\r\n",sn);
socket(sn,Sn_MR_TCP,anyport++,0);
if(anyport > 5000)
{
anyport=3000;
}
printf("%d:Opened port[%d]\r\n",sn,anyport-1);
break;
default:
break;
}
return 1;
}
至此,整个移植测试过程结束,谢谢大家交流和讨论。