由於公司需要,最近接觸了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;
}
至此,整個移植測試過程結束,謝謝大家交流和討論。