關於w5500客戶端和服務器的調試心得

由於公司需要,最近接觸了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、解決通訊線問題後更新完程序,將板子用網線通過一個分線盒和電腦連接上,此時電腦連接的是路由器,IP192.168.31.166,板子本地IP設置爲192.168.123進行測試發現不能ping通,

解決辦法,直接用網線將電腦和板子連接,關閉路由器,社本地IP192.168.0.101,設置板子IP192.168.0.100,再次進行測試,可以ping通了。完善程序中的端口配置,打開pctcpIP客戶端,設置爲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;
}

 

至此,整個移植測試過程結束,謝謝大家交流和討論。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章