#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服务,这个东西下一篇文章再说。
?
?
?
|