W5500以太网控制器芯片(二):ioLibrary库实现TCP客户端

#W5500以太网控制芯片相关文章链接#

上一篇:

W5500以太网控制器芯片(一):ioLibrary库实现TCP服务器
 

前面已经通过移植官方的ioLibrary库实现了TCP回环测试(W5500做tcp服务器),下面我们来实现W5500做TCP客户端,连接远程的TCP服务器。

准备工具:

a、电脑上装一个网络调试工具,做TCP服务器用

b、一个路由器,后面电脑和W5500都要接到路由器上

c、W5500+支持SPI接口的MCU或者SOC

d、官方的ioLibrary库文件(上一篇文章中说明了下载方式)


1、移植驱动

基本TCP客户端测试依旧不需要引入其他驱动,只要W5500的基本驱动即可,即前一篇文章的W5500、socket、wizchip_config的c和h文件引入工程中即可,与TCP服务器的引入方式一致

2、SPI接口初始化

与TCP服务器的也完全一致,直接参照前一篇文章即可,分别实现以下3类接口:
(1)SPI读写
(2)进入、退出临界区
(3)片选信号输出

3、实现TCP客户端

(1)网络初始化:参照上一篇文章,包括network_init,以及上面几个SPI接口函数的注册
 

    delay_init();	    	 	//延时函数初始化
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2

	uart_init(115200);	 	//串口初始化
		
	LED_Init();
 
	SPI2_Init();            //初始化SPI

	// First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP 
	/* Critical section callback */
	//reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);	//注册临界区函数
	reg_wizchip_cris_cbfunc(NULL, NULL); // 注册临界区函数
		
	reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);// 注册片选函数

	/* SPI Read & Write callback function */
	reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);	//注册读写函数
 
	/* WIZCHIP SOCKET Buffer initialize */
	if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){
		 printf("WIZCHIP Initialized fail.\r\n");
		 while(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);
	
	/* Network initialization */
	network_init();

(2)定义一下要连接的服务器的IP和端口

uint8_t dest_ip[4] = {10, 1, 1, 144};
uint16_t dest_port = 	5000;

(3)TCP客户端事件处理函数实现

/**
  * @brief  TCP客户端事件处理函数
  */
int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport)
{
   int32_t ret; // return value for SOCK_ERRORs
   uint16_t size = 0, sentsize=0;

   // Port number for TCP client (will be increased)
   uint16_t any_port = 	5000;

   // Socket Status Transitions
   // Check the W5500 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status)
   switch(getSn_SR(sn))
   {
      case SOCK_ESTABLISHED :
         if(getSn_IR(sn) & Sn_IR_CON)	// Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
         {
#ifdef _LOOPBACK_DEBUG_
			printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
			setSn_IR(sn, Sn_IR_CON);  // this interrupt should be write the bit cleared to '1'
         }

         //
         // Data Transaction Parts; Handle the [data receive and send] process
         //
		 if((size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
         {
			if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
			ret = recv(sn, buf, size); // Data Receive process (H/W Rx socket buffer -> User's buffer)

			if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
			size = (uint16_t) ret;
			sentsize = 0;

			// Data sentsize control
			while(size != sentsize)
			{
				ret = send(sn, buf+sentsize, size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
				
				printf("%s\r\n",buf);
				
				if(ret < 0) // Send Error occurred (sent data length < 0)
				{
					close(sn); // socket close
					return ret;
				}
				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
			}
         }
		 //
         break;

      case SOCK_CLOSE_WAIT :
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:CloseWait\r\n",sn);
#endif
         if((ret=disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOPBACK_DEBUG_
         printf("%d:Socket Closed\r\n", sn);
#endif
         break;

      case SOCK_INIT :
#ifdef _LOOPBACK_DEBUG_
    	 printf("%d:Try to connect to the %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
    	 if( (ret = connect(sn, destip, destport)) != SOCK_OK) return ret;	//	Try to TCP connect to the TCP server (destination)
         break;

      case SOCK_CLOSED:
    	  close(sn);
    	  if((ret=socket(sn, Sn_MR_TCP, any_port++, SF_TCP_NODELAY)) != sn) return ret; // TCP socket open with 'any_port' port number
#ifdef _LOOPBACK_DEBUG_
    	 printf("%d:TCP client loopback start\r\n",sn);
         //printf("%d:Socket opened\r\n",sn);
#endif
         break;
      default:
			{
         break;
			}
   }
   return 1;
}

上面将W5500客户端从电脑服务器上收到的TCP数据通过串口打印出来,同时回复给电脑

(4)在主进程中加入TCP客户端事件处理

	/*******************************/
	/* WIZnet W5500 Code Examples  */
	/*******************************/
  /* Main loop */
	while(1)
	{
		//TCP客户端回环测试
		loopback_tcpc(SOCK_TCPS, gDATABUF, dest_ip, dest_port);

		delay_ms(20);
		LED1 = 0;
		delay_ms(20);
		LED1 = 1;

	} // end of Main loop

在循环中定时处理TCP客户端事件,同时闪一下灯(循环间隔不重要,别太长就行)

4、验证客户端

 (1)首先,我们要将电脑和设备全部接到路由器上(电脑不必用以太网,wifi连上去也一样)

(2)检查路由器的网关地址和路由器给电脑分配的IP地址



当然,路由器找不到该功能的,CMD命令行ipconfig一下查电脑的IP和网关即可


此时,读到的网关为10.1.1.1,所以我们要把W5500的默认IP地址改到该网段下(前三个网段一致),比如10.1.1.200,参照前一篇文章。


wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0x08, 0xdc,0x00, 0xab, 0xcd},
                            .ip = {10, 1, 1, 200},
                            .sn = {255,255,255,0},
                            .gw = {10, 1, 1, 1},
                            .dns = {8,8,8,8},
                            .dhcp = NETINFO_STATIC};

(4)在电脑上使用网络调试工具,开启一个TCP服务器(注意端口号服务器要和客户端程序里设置的一致,比如此处设置的都是5000)

 (5)设备写入程序,上电开始测试


从串口数据上可以看到,设备开始连接,并连接电脑成功





电脑发送的数据,W5500原样返回,同时串口返回的数据也符合我们的预期。

这样,TCP客户端模式收发数据就实现了。注意:

(1)、W5500设置的IP的不应该与路由器内其他设备冲突
(2)、连接的服务器不只可以是本地的电脑,如果路由器是联网的,那么连接任意公网内的TCP服务器都是可以的,比如如果你有个云服务器,在上面开一个TCP服务器,也是可以连上的
 
当然,我们实际使用,肯定不可能将W5500连上网口后,还要检查路由器的IP,然后重新改一下程序,把W5500的IP地址改掉,这也不现实。所以,还要在W5500上引入DHCP服务,这个东西下一篇文章再说。

下一篇:
        W5500以太网控制器芯片(三):实现DHCP服务

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值