本文主要介绍采用W5500和计算机之间互相PING,看看网络是否连接是否正常。

1、什么是PING

ping是Packet Internet Groper的缩写,中文意思是"因特网包探索器"。
ping用于确定本地主机能否与另一台主机成功交换(发送与接收)数据包,判断网络是否通畅。
Ping命令可以进行以下操作:
①通过将ICMP(Internet控制消息协议)回显(Echo)数据包发送到计算机,并侦听回显回复数据包来验证网络的物理连接。
②每个发送的数据包最多等待一秒。
③打印已传输和接收的数据包数。
ping成功只保证当前主机与目的主机间存在一条连通的物理路径。
IPRAW属于IP层的数据通信,它是比TCP、UDP低一层协议
MACRAW是一个低于IP层的以太网MAC通信,它能够灵活使用目的主机的上层协议。

W5500工作在 IPRAW模式下,去PING远程计算机,同时,远程计算机也可以PING 这个W5500。W5500工作在TCP模式下,远程计算机可以随时去PING这个W5500。这个PING功能,可以了解一下,不是很重要。

2、ioLibrary库下载地址
下载地址:https://gitee.com/wiznet-hk/STM32F10x_W5500_Examples
源文件下载地址:https://gitee.com/wiznet-hk
密码生成工具:https://open.iot.10086.cn/doc/iot_platform/images/tools/token.exe

源工程文件可以参考,他不能使用计算机去PING这个W5500。我这里做了修正。 

3、 W5500_Variable.c

#include "W5500_Variable.h"
#include "socket.h"	// Just include one header for WIZCHIP
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()

//W5500的网络参数
//本地物理地址:00 08 DC 11 11 11
//本地IP地址:192.168.1.199
//本地子网掩码:	255.255.255.0
//本地网关:192.168.1.1
//DNS服务器IP地址:8.8.8.8
//程序固化IP地址
/* network information */
wiz_NetInfo net_info = {
    {0x00, 0x08, 0xdc,0x11, 0x11, 0x11},
    {192, 168, 1, 199},
    {255,255,255,0},
    {192, 168, 1, 1},
    {8,8,8,8},//DNS服务器IP
    NETINFO_STATIC}; //静态IP,程序固化IP地址
wiz_NetInfo net_info;

uint16_t Local_Port=4000;//W5500本地端口为4000

uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};

uint8_t dest_ip[4] = {192, 168, 1, 190};

4、 W5500_Variable.h

#ifndef _W5500_Variable_H
#define _W5500_Variable_H

#include "stm32f10x.h"//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "wizchip_conf.h"

#define TCP_SOCKET0   0  //W5500使用SOCKET通道0作为TCP

extern wiz_NetInfo net_info;
extern uint16_t Local_Port;//W5500本地端口

#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
extern uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE];

extern uint8_t dest_ip[4];
#endif

5、Test_Ping.c

#include "Test_Ping.h"
#include <stdio.h>
#include <string.h>
#include "socket.h"
#include "wizchip_conf.h"
#include <stdlib.h>
#include "W5500_Variable.h"
#include "delay.h"
#include "utility.h"

static uint16_t PingCounter = 0;

void Ping_Init(uint8_t s);
void W5500_Ping_RemoteComputer(uint8_t sn, uint8_t *remote_ip,uint8_t *buf);
void RemoteComputer_Ping_W5500(uint8_t s, uint8_t *remote_ip,uint8_t *buf);

//函数功能:打印ethernet_buf[]的数据;
void Print_W5500_ethernet_buf(uint16_t len)
{
	uint16_t i;
  uint8_t temp;

		printf("\r\nW5500:");    //将"\r\nW5500:"发送到调试串口,由PC显示;
		for(i=0;i<len;i++)
		{
			temp=0;
			if( ( (ethernet_buf[i]==0x0D)||(ethernet_buf[i]==0x0A) ) )
			{
				printf("%c",ethernet_buf[i]);
				temp=1;
      }
			if(temp==0)
			{
				if( ( (ethernet_buf[i]>=' ')&&(ethernet_buf[i]<='~') ) ) printf("%c",ethernet_buf[i]);
				else
				{
//					printf(" ");
					printf("%02X",ethernet_buf[i]);
					printf(" ");
        }
      }
    }
		printf("\r\n");//将"\r\n"发送到调试串口,由PC显示;

}

//函数功能:发送PING请求
//s表示SOCKET通道s
//remote_ip[]为保存IP地址的数据
//buf[]用来保存发送数据
void W5500_ping_request(uint8_t s, uint8_t *remote_ip,uint8_t *buf,uint8_t PingCnt)
{
	uint16_t i;
	int32_t ret;
	PINGMSGR *PingRequest;
	uint16_t sum;

	PingRequest=(PINGMSGR*)buf;
	PingRequest->Type = PING_REQUEST;
	PingRequest->Code = CODE_ZERO;
	PingRequest->ID = htons(0x1000);//设置ID,可以随便设置
	PingRequest->SeqNum = htons(PingCnt);//设置序号
	for (i = 0; i < BUF_LEN; i++)
	{
		PingRequest->Data[i] = (i) % 8;
	}
	PingRequest->CheckSum = 0;

	sum=checksum((uint8_t *)PingRequest, sizeof(PINGMSGR));
	//计算校验和,Calculate the checksum
	PingRequest->CheckSum = htons(sum);

	ret=sendto(s, (uint8_t *)PingRequest, sizeof(PINGMSGR), remote_ip, Local_Port);
	//将PingRequest通过SOCKET通道s发送给远程IP地址为remote_ip,并指定远程端口为Local_Port
	if ( ret== 0)
	{
		printf("Fail to send ping-reply packet\r\n");
	}
	else
	{
		printf("Ping:%d.%d.%d.%d\r\n", (remote_ip[0]), (remote_ip[1]), (remote_ip[2]), (remote_ip[3]));
	}
}

/**
 * @brief Parse Ping replies
 * @param s:socket number
 * @param remote_ip:Ping address
 * @return none
 */
//函数功能:接收来自远程IP的PING应答
//s表示SOCKET通道s
//remote_ip[]为保存IP地址的数据
//buf[]用来保存接收到的数据
uint8_t W5500_Receive_PingReplay(uint8_t s, uint8_t *remote_ip, uint16_t rlen,uint8_t *buf)
{
	uint16_t tmp_checksum;
	uint16_t len;
	uint16_t i;
	PINGMSGR *PingReply;
  uint8_t tPingReplyReceivedFlag;
  //1表示收到来自远程IP的PING应答
  //0表示没有接收到来自远程IP的PING应答

	len = recvfrom(s, buf, rlen, remote_ip, &Local_Port);
	//接收来自IP地址为addr的数据,并将读到的端口数值保存到buf中
//  Print_W5500_ethernet_buf(len);

	PingReply=(PINGMSGR*)buf;
	if (buf[0] == PING_REPLY)
	{
		PingReply->Type = buf[0];
		PingReply->Code = buf[1];
		PingReply->CheckSum = (buf[3] << 8) + buf[2];
		PingReply->ID = (buf[5] << 8) + buf[4];
		PingReply->SeqNum = (buf[7] << 8) + buf[6];
		for (i = 0; i < len - 8; i++)
		{
			PingReply->Data[i] = buf[8 + i];
		}
		tmp_checksum = ~checksum(buf, len);//计算校验和,Calculate the checksum
		printf("\r\nCalcute CheckSum is 0x%04X", (tmp_checksum));

		if (tmp_checksum != 0xffff)//校验错误
		{
			tPingReplyReceivedFlag=0;
			printf("\r\ntmp_checksum = %x\r\n", tmp_checksum);
		}
		else//校验和正确
		{
			printf("\r\nReply from %d.%d.%d.%d ID=0x%X SeqNum=0x%04X Byte=%d\r\n\r\n",\
			(remote_ip[0]), (remote_ip[1]), (remote_ip[2]), (remote_ip[3]), htons(PingReply->ID),htons(PingReply->SeqNum), (rlen + 6));
			tPingReplyReceivedFlag = 1;//收到来自远程IP的PING应答
		}
	}

	return(tPingReplyReceivedFlag);
}



//函数功能:接收来自远程IP的PING请求
//s表示SOCKET通道s
//remote_ip[]为保存IP地址的数据
//buf[]用来保存接收到的数据
uint8_t W5500_Receive_PingRequest(uint8_t s, uint8_t *remote_ip, uint16_t rlen,uint8_t *buf)
{
	uint16_t tmp_checksum;
	uint16_t len;
	uint16_t i;
	PINGMSGR *PingReply;
  uint8_t tPingReplyReceivedFlag;
  //1表示收到来自远程IP的PING应答
  //0表示没有接收到来自远程IP的PING应答

	len = recvfrom(s, buf, rlen, remote_ip, &Local_Port);
	//接收来自IP地址为addr的数据,并将读到的端口数值保存到buf中
//  Print_W5500_ethernet_buf(len);

	PingReply=(PINGMSGR*)buf;
	if (buf[0] == PING_REQUEST)//接收来自远程IP的请求
	{
		PingReply->Type = buf[0];
		PingReply->Code = buf[1];
		PingReply->CheckSum = (buf[3] << 8) + buf[2];
		PingReply->ID = (buf[5] << 8) + buf[4];
		PingReply->SeqNum = (buf[7] << 8) + buf[6];
		for (i = 0; i < len - 8; i++)
		{
			PingReply->Data[i] = buf[8 + i];
		}
		tmp_checksum = ~checksum((uint8_t *)buf, len);//计算校验和,Calculate the checksum
		printf("\r\nCalcute CheckSum is 0x%04X", (tmp_checksum));
		if (tmp_checksum != 0xffff)//校验错误
		{
			tPingReplyReceivedFlag=0;
			printf("\r\n CheckSum is in correct %x shold be %x \n", (tmp_checksum), htons(PingReply->CheckSum));
		}
		else//校验和正确
		{
		  printf("\r\nRequest from %d.%d.%d.%d  ID:%x SeqNum:%x  :data size %d bytes\r\n",
			   (remote_ip[0]), (remote_ip[1]), (remote_ip[2]), (remote_ip[3]), (PingReply->ID), (PingReply->SeqNum), (rlen + 6));
		  tPingReplyReceivedFlag = 1;//收到来自远程IP的PING应答
		}
	}

	return(tPingReplyReceivedFlag);
}

//函数功能:发送PING请求
//s表示SOCKET通道s
//remote_ip[]为保存IP地址的数据
//buf[]用来保存发送数据
void W5500_Send_PingReplay(uint8_t s, uint8_t *remote_ip,uint8_t *buf,uint8_t len)
{
	int32_t ret;
	PINGMSGR *PingRequest;
	uint16_t sum;

	PingRequest=(PINGMSGR*)buf;
	PingRequest->Type = PING_REPLY;
	PingRequest->CheckSum = 0;

	sum=checksum(buf, len-6);
	//计算校验和,Calculate the checksum
	PingRequest->CheckSum = htons(sum);

//	Print_W5500_ethernet_buf(len-6);
	ret=sendto(s, buf, len-6, remote_ip, Local_Port);
	//将PingRequest通过SOCKET通道s发送给远程IP地址为remote_ip,并指定远程端口为Local_Port
	if ( ret== 0)
	{
		printf("Fail to send ping-reply packet\r\n");
	}
	else
	{
		printf("PingReplay:%d.%d.%d.%d\r\n", (remote_ip[0]), (remote_ip[1]), (remote_ip[2]), (remote_ip[3]));
	}
}

void Ping_Init(uint8_t s)
{
	close(s);
	IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP);//创建套接字,Create Socket
	if (socket(s, Sn_MR_IPRAW, Local_Port, 0) != 0)
	{//令SOCKET端口0工作在IPRAW模式,并设置TCP端口为Local_Port
	}
	while (getSn_SR(s) != SOCK_IPRAW)// Check socket register
	{
		;
	}
}

/**
 *@brief	Set the number of times to ping the public IP address
 *@param	s:socket number
 *@param	number_of_pings:The number of pings
 *@param	remote_ip:Public IP address
 *@return	none
 */
 //number_of_pings:表示PING的次数,The number of pings
void W5500_Ping_RemoteComputer(uint8_t sn, uint8_t *remote_ip,uint8_t *buf)
{
	uint16_t rlen, cnt;
	uint8_t  Sn_SR_Value;
	uint8_t NumberOfPingReplyReceived = 0; //NumberOfPingReplyReceived is the number of ping reply received
  uint8_t PingCnt; //PING计数器,每PING一次,则加1次
  uint8_t tPingReplyReceivedFlag;
  //1表示收到来自远程IP的PING应答
  //0表示没有接收到来自远程IP的PING应答

	Ping_Init(TCP_SOCKET0);//在PING其它设备时,要初始化PING功能
	cnt = 0;PingCnt = 0; //PING计数器,每PING一次,则加1次
	while(PingCnt<4)//发送4次PING请求
	{
		Sn_SR_Value=getSn_SR(sn);//获取W5500SOCKET通道sn的状态寄存器

		if(Sn_SR_Value== SOCK_CLOSED)Ping_Init(sn);

		if(Sn_SR_Value== SOCK_IPRAW)
		{
			PingCnt++;
			printf("No.%d  ", PingCnt);
			W5500_ping_request(sn, remote_ip,buf,PingCounter);//发送PING请求
			while (1)
			{
				rlen = getSn_RX_RSR(sn);
				//getSn_RX_RSR()读S0OCKET通道sn的Sn_RX_RSR寄存器,获取该端口的接收缓冲区的数据长度
				if ( rlen > 0)
				{
					tPingReplyReceivedFlag=W5500_Receive_PingReplay(sn, remote_ip, rlen,buf);
					//接收来自远程IP的PING应答
					NumberOfPingReplyReceived++;
					if (tPingReplyReceivedFlag==1)//收到来自远程IP的PING应答
						break;
				}

				if ((cnt > 10))//超时10次
				{
					printf("Request Time out\r\n\r\n");
					cnt = 0;
					break;
				}
				else
				{
					cnt++;
					delay_ms(5);
				}
			}
			PingCounter++;
		}
	}

	printf("Ping Request = %d, Ping Reply = %d, Lost = %d\r\n", \
	  PingCnt, NumberOfPingReplyReceived, PingCnt - NumberOfPingReplyReceived);
}

void RemoteComputer_Ping_W5500(uint8_t sn, uint8_t *remote_ip,uint8_t *buf)
{
	uint16_t rlen;
	uint8_t  Sn_SR_Value;
  uint8_t tPingReplyReceivedFlag;
  //1表示收到来自远程IP的PING应答
  //0表示没有接收到来自远程IP的PING应答
	uint8_t cnt;

	cnt=0;
	Ping_Init(sn);
	while(cnt<4)//接收4次远程IP请求
	{
		Sn_SR_Value=getSn_SR(sn);//获取W5500SOCKET通道sn的状态寄存器
		if(Sn_SR_Value== SOCK_CLOSED) Ping_Init(sn);

		if(Sn_SR_Value==SOCK_IPRAW)
		{
			rlen = getSn_RX_RSR(sn);
	    //getSn_RX_RSR()读S0OCKET通道s的Sn_RX_RSR寄存器,获取该端口的接收缓冲区的数据长度
	    if ( rlen > 0)
	    {
		    tPingReplyReceivedFlag=W5500_Receive_PingRequest(sn, remote_ip, rlen,buf);
		    if(tPingReplyReceivedFlag==1)
				{
					W5500_Send_PingReplay(sn, remote_ip, buf,rlen);
				  cnt++;
				}
	    }
    }
  }
}

6、Test_Ping.h

#ifndef _Test_Ping_H_
#define _Test_Ping_H_

#include <stdint.h>
#include "wizchip_conf.h"
#include "socket.h"

#define BUF_LEN 128
#define PING_REQUEST 8
#define PING_REPLY 0
#define CODE_ZERO 0

typedef struct pingmsg
{
  uint8_t Type;         // 0 - Ping Reply, 8 - Ping Request
  uint8_t Code;         // Always 0
  uint16_t CheckSum;    // Check sum
  uint16_t ID;          // Identification
  uint16_t SeqNum;      // Sequence Number
  int8_t Data[BUF_LEN]; // Ping Data  : 1452 = IP RAW MTU - sizeof(Type+Code+CheckSum+ID+SeqNum)
} PINGMSGR;

//#define SOCKET_ERROR 1
//#define TIMEOUT_ERROR 2
//// #define SUCCESS 3
//#define REPLY_ERROR 4
//extern uint8_t RequestNumber;

#define Sn_PROTO(N) (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))

extern void Ping_Init(uint8_t s);
extern void RemoteComputer_Ping_W5500(uint8_t s, uint8_t *remote_ip,uint8_t *buf);
extern void W5500_Ping_RemoteComputer(uint8_t sn, uint8_t *remote_ip,uint8_t *buf);

#endif

7、utility.c

#include "utility.h"
#include "wizchip_conf.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

/**
 * @brief Convert strings to 16-bit unsigned integers
 *
 * Converts a given string to a 16-bit unsigned integer according to the specified cardinality.
 *
 * @param str :String pointer
 * @param base :radix
 *
 * @return A converted 16-bit unsigned integer
 */
uint16_t atoi16(char *str, uint16_t base)
{
	unsigned int num = 0;
	while (*str != 0)
		num = num * base + c2d(*str++);
	return num;
}

/**
 * @brief Convert strings to 32-bit unsigned integers
 *
 * Converts a given string to a 32-bit unsigned integer in the specified base system and returns the result.
 *
 * @param str :String pointer
 * @param base :The base number can be 2~36
 *
 * @return A converted 32-bit unsigned integer
 */
uint32_t atoi32(char *str, uint16_t base)
{
	uint32_t num = 0;
	while (*str != 0)
		num = num * base + c2d(*str++);
	return num;
}

/**
 * @brief Convert unsigned 16-bit integers to strings
 *
 * Converts a given unsigned 16-bit integer to string form and stores it in a specified array of characters.
 *
 * @param n :An unsigned 16-bit integer to be converted
 * @param str :An array of characters that stores the result of the transformation
 * @param len :The length of the character array
 */
void itoa(uint16_t n, unsigned char str[5], unsigned char len)
{
	unsigned char i = len - 1;

	memset(str, 0x20, len);
	do
	{
		str[i--] = n % 10 + '0';

	} while ((n /= 10) > 0);

	return;
}

/**
 * @brief Converts a string to an integer in the specified base system
 *
 * Converts a given string to an integer in the specified base and stores the result in a specified variable.
 *
 * @param str :String pointer
 * @param base :The base number
 * @param ret :The converted integer stores the pointer
 *
 * @return If the conversion is successful, return 1; Otherwise, 0 is returned
 */
int validatoi(char *str, int base, int *ret)
{
	int c;
	char *tstr = str;
	if (str == 0 || *str == '\0')
		return 0;
	while (*tstr != '\0')
	{
		c = c2d(*tstr);
		if (c >= 0 && c < base)
			tstr++;
		else
			return 0;
	}

	*ret = atoi16(str, base);
	return 1;
}

/**
 * @brief Replaces the specified character in the string with another character
 *
 * In a given string, replace all occurrences of the specified character with another character.
 *
 * @param str :string pointer
 * @param oldchar :characters that need to be replaced
 * @param newchar :Replaced characters

 */
void replacetochar(char *str, char oldchar, char newchar)
{
	int x;
	for (x = 0; str[x]; x++)
		if (str[x] == oldchar)
			str[x] = newchar;
}

/**
 * @brief Convert hexadecimal characters to decimal numbers
 *
 * Convert a given hexadecimal character to the corresponding decimal number.
 *
 * @param c :hexadecimal characters
 *
 * @return Converted decimal digits, if the conversion fails, the original characters will be returned
 */
char c2d(unsigned char c)
{
	if (c >= '0' && c <= '9')
		return c - '0';
	if (c >= 'a' && c <= 'f')
		return 10 + c - 'a';
	if (c >= 'A' && c <= 'F')
		return 10 + c - 'A';

	return (char)c;
}

/**
 * @brief Swap endianness
 *
 * Swap the upper 8 bits and the lower 8 bits of the input 16-bit unsigned integer and return the result after the swap.
 *
 * @param i :A 16-bit unsigned integer entered
 *
 * @return 16-bit unsigned integer after swapping
 */
uint16_t swaps(uint16_t i)
{
	uint16_t ret = 0;
	ret = (i & 0xFF) << 8;
	ret |= ((i >> 8) & 0xFF);
	return ret;
}

/**
 * @brief Byte order for swapping 32-bit unsigned integers
 *
 * Byte order the given 32-bit unsigned integer is swapped and the result after the swap is returned.
 *
 * @param l:32-bit unsigned integers to be swapped for byte order
 *
 * @return 32-bit unsigned integer after swapping
 */
uint32_t swapl(uint32_t l)
{
	uint32_t ret = 0;
	ret = (l & 0xFF) << 24;
	ret |= ((l >> 8) & 0xFF) << 16;
	ret |= ((l >> 16) & 0xFF) << 8;
	ret |= ((l >> 24) & 0xFF);
	return ret;
}

/**
 * @brief Gets a substring between two strings
 *
 * In a given source string, find two specified substrings and get the substrings between them.
 *
 * @param src :source string pointer
 * @param s1 :first substring pointer
 * @param s2 :second substring pointer
 * @param sub :stores the pointer to the substring
 */
void mid(char *src, char *s1, char *s2, char *sub)
{
	char *sub1;
	char *sub2;
	uint16_t n;

	sub1 = strstr(src, s1);
	sub1 += strlen(s1);
	sub2 = strstr(sub1, s2);
	n = sub2 - sub1;
	strncpy(sub, sub1, n);
	sub[n] = 0;
}

/**
 * @brief Converts the IP address represented by the string into a byte array
 *
 * Converts the IP address represented by a given string into a byte array and stores it in the specified array.
 *
 * @param addr :IP address represented by the
 * @param ip :stores an array of bytes of the transformation result
 */
void inet_addr_(unsigned char *addr, unsigned char *ip)
{
	int i;
	char taddr[30];
	char *nexttok;
	char num;
	strcpy(taddr, (char *)addr);

	nexttok = taddr;
	for (i = 0; i < 4; i++)
	{
		nexttok = strtok(nexttok, ".");
		if (nexttok[0] == '0' && nexttok[1] == 'x')
			num = atoi16(nexttok + 2, 0x10);
		else
			num = atoi16(nexttok, 10);

		ip[i] = num;
		nexttok = NULL;
	}
}

/**
 * @brief Converts network addresses into dotted decimal strings
 *
 * Converts a given network address into a dotted decimal string form.
 *
 * @param addr:network address
 *
 * @return The pointer to the converted dotted decimal string
 */
char *inet_ntoa(uint32_t addr)
{
	static char addr_str[32];
	memset(addr_str, 0, 32);
	sprintf(addr_str, "%d.%d.%d.%d", (int)(addr >> 24 & 0xFF), (int)(addr >> 16 & 0xFF), (int)(addr >> 8 & 0xFF), (int)(addr & 0xFF));
	return addr_str;
}

/**
 * @brief Translates an IP address into a string with leading zeros
 *
 * Converts a given uint32_t integer IP address to a string format with leading zeros and returns the converted string.
 *
 * @param addr:An unsigned, long, integer representation of the addr IP address
 *
 * @return Converted string pointer
 */
char *inet_ntoa_pad(uint32_t addr)
{
	static char addr_str[16];
	memset(addr_str, 0, 16);
	printf(addr_str, "%03d.%03d.%03d.%03d", (int)(addr >> 24 & 0xFF), (int)(addr >> 16 & 0xFF), (int)(addr >> 8 & 0xFF), (int)(addr & 0xFF));
	return addr_str;
}

/**
 * @brief Verify IP address
 *
 * Based on the given IP address string, verify that it is valid and store the result in a specified IP address array.
 *
 * @param src : IP address string
 * @param ip : is used to store an array of verified IP addresses
 *
 * @return Verification result, 1 is returned for success and 0 is returned for failure
 */
char verify_ip_address(char *src, unsigned char *ip)
{
	int i;
	int tnum;
	char tsrc[50];
	char *tok = tsrc;

	strcpy(tsrc, src);

	for (i = 0; i < 4; i++)
	{
		tok = strtok(tok, ".");
		if (!tok)
			return 0;
		if (tok[0] == '0' && tok[1] == 'x')
		{
			if (!validatoi(tok + 2, 0x10, &tnum))
				return 0;
		}
		else if (!validatoi(tok, 10, &tnum))
			return 0;

		ip[i] = tnum;

		if (tnum < 0 || tnum > 255)
			return 0;
		tok = NULL;
	}
	return 1;
}

/**
 * @brief Converts 16-bit unsigned integers from host endian-order to network endian-order
 *
 * Converts 16-bit unsigned integers under host endianness to network endians. If the host endianism is little-endian order, the bytes are swapped;
 * Otherwise, the original value will be returned.
 *
 * @param hostshort:16-bit unsigned integer in host endianness
 *
 * @return A 16-bit unsigned integer in the converted network endianness
 */
uint16_t htons(uint16_t hostshort) //< A 16-bit number in host byte order.
{
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)//表示系统采用小端存储模式。
	return swaps(hostshort);
#else
	return hostshort;
#endif
}

/**
 * @brief Converts 32-bit host endian-order integers to network endian-order integers
 *
 * Converts a given 32-bit host endian-order integer to a network endian-order integer.
 *
 * @param hostlong: host endian-order integer
 *
 * @return Converted network endian-order integers
 */
uint32_t htonl(uint32_t hostlong) //< hostshort  - A 32-bit number in host byte order.
{
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
	return swapl(hostlong);
#else
	return hostlong;
#endif
}

/**
 * @brief Converts 16-bit unsigned integers of network endianness to host endianness
 *
 * Converts the 16-bit unsigned integer of a given network endianness to the corresponding host endian.
 *
 * @param netshort:16-bit unsigned integer of the netshort network endian
 *
 * @return A 16-bit unsigned integer in the converted host endianism
 */
uint32_t ntohs(uint16_t netshort) //< netshort - network odering 16bit value
{
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
	return htons(netshort);
#else
	return netshort;
#endif
}

/**
 * @brief Converts the long integer number of network endenies to host endians
 *
 * Converts the long integer number of network endenians to the corresponding host endianness according to the endianness of the current system.
 *
 * @param netlong:long integer number of the netlong network endeny
 *
 * @return The long integer number of the converted host endians
 */
uint32_t ntohl(uint32_t netlong)
{
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
	return htonl(netlong);
#else
	return netlong;
#endif
}

/**
 * @brief Calculate the checksum
 *
 * Calculate checksums based on a given data stream.
 *
 * @param src:stream pointer
 * @param len:stream size
 *
 * @return Checksum
 */
uint16_t checksum(unsigned char *src, unsigned int len)
{
	uint16_t sum, tsum, i, j;
	uint32_t lsum;

	j = len >> 1;

	lsum = 0;

	for (i = 0; i < j; i++)
	{
		tsum = src[i * 2];
		tsum = tsum << 8;
		tsum += src[i * 2 + 1];
		lsum += tsum;
	}

	if (len % 2)
	{
		tsum = src[i * 2];
		lsum += (tsum << 8);
	}

	sum = lsum;
	sum = ~(sum + (lsum >> 16));
	return (uint16_t)sum;
}

8、utility.h

#ifndef _UTILITY_H
#define _UTILITY_H
#include "stdio.h"
//#include "types.h"
#include <stdint.h>

/**
 * @brief Convert strings to 16-bit unsigned integers
 *
 * Converts a given string to a 16-bit unsigned integer according to the specified cardinality.
 *
 * @param str :String pointer
 * @param base :radix
 *
 * @return A converted 16-bit unsigned integer
 */
uint16_t atoi16(char *str, uint16_t base);

/**
 * @brief Convert strings to 32-bit unsigned integers
 *
 * Converts a given string to a 32-bit unsigned integer in the specified base system and returns the result.
 *
 * @param str :String pointer
 * @param base :The base number can be 2~36
 *
 * @return A converted 32-bit unsigned integer
 */
uint32_t atoi32(char *str, uint16_t base);

/**
 * @brief Convert unsigned 16-bit integers to strings
 *
 * Converts a given unsigned 16-bit integer to string form and stores it in a specified array of characters.
 *
 * @param n :An unsigned 16-bit integer to be converted
 * @param str :An array of characters that stores the result of the transformation
 * @param len :The length of the character array
 */
void itoa(uint16_t n, unsigned char *str, unsigned char len);

/**
 * @brief Converts a string to an integer in the specified base system
 *
 * Converts a given string to an integer in the specified base and stores the result in a specified variable.
 *
 * @param str :String pointer
 * @param base :The base number
 * @param ret :The converted integer stores the pointer
 *
 * @return If the conversion is successful, return 1; Otherwise, 0 is returned
 */
int validatoi(char *str, int base, int *ret);

/**
 * @brief Convert hexadecimal characters to decimal numbers
 *
 * Convert a given hexadecimal character to the corresponding decimal number.
 *
 * @param c :hexadecimal characters
 *
 * @return Converted decimal digits, if the conversion fails, the original characters will be returned
 */
char c2d(unsigned char c);

/**
 * @brief Swap endianness
 *
 * Swap the upper 8 bits and the lower 8 bits of the input 16-bit unsigned integer and return the result after the swap.
 *
 * @param i :A 16-bit unsigned integer entered
 *
 * @return 16-bit unsigned integer after swapping
 */
uint16_t swaps(uint16_t i);

/**
 * @brief Byte order for swapping 32-bit unsigned integers
 *
 * Byte order the given 32-bit unsigned integer is swapped and the result after the swap is returned.
 *
 * @param l:32-bit unsigned integers to be swapped for byte order
 *
 * @return 32-bit unsigned integer after swapping
 */
uint32_t swapl(uint32_t l);

/**
 * @brief Replaces the specified character in the string with another character
 *
 * In a given string, replace all occurrences of the specified character with another character.
 *
 * @param str :string pointer
 * @param oldchar :characters that need to be replaced
 * @param newchar :Replaced characters

 */
void replacetochar(char *str, char oldchar, char newchar);

/**
 * @brief Gets a substring between two strings
 *
 * In a given source string, find two specified substrings and get the substrings between them.
 *
 * @param src :source string pointer
 * @param s1 :first substring pointer
 * @param s2 :second substring pointer
 * @param sub :stores the pointer to the substring
 */
void mid(char *src, char *s1, char *s2, char *sub);

/**
 * @brief Converts the IP address represented by the string into a byte array
 *
 * Converts the IP address represented by a given string into a byte array and stores it in the specified array.
 *
 * @param addr :IP address represented by the
 * @param ip :stores an array of bytes of the transformation result
 */
void inet_addr_(unsigned char *addr, unsigned char *ip);

/**
 * @brief Converts network addresses into dotted decimal strings
 *
 * Converts a given network address into a dotted decimal string form.
 *
 * @param addr:network address
 *
 * @return The pointer to the converted dotted decimal string
 */
char *inet_ntoa(uint32_t addr);

/**
 * @brief Translates an IP address into a string with leading zeros
 *
 * Converts a given uint32_t integer IP address to a string format with leading zeros and returns the converted string.
 *
 * @param addr:An unsigned, long, integer representation of the addr IP address
 *
 * @return Converted string pointer
 */
char *inet_ntoa_pad(uint32_t addr);

/**
 * @brief Verify IP address
 *
 * Based on the given IP address string, verify that it is valid and store the result in a specified IP address array.
 *
 * @param src : IP address string
 * @param ip : is used to store an array of verified IP addresses
 *
 * @return Verification result, 1 is returned for success and 0 is returned for failure
 */
char verify_ip_address(char *src, unsigned char *ip); /* Verify dotted notation IP address string */

/**
 * @brief Converts 16-bit unsigned integers from host endian-order to network endian-order
 *
 * Converts 16-bit unsigned integers under host endianness to network endians. If the host endianism is little-endian order, the bytes are swapped;
 * Otherwise, the original value will be returned.
 *
 * @param hostshort:16-bit unsigned integer in host endianness
 *
 * @return A 16-bit unsigned integer in the converted network endianness
 */
uint16_t htons(uint16_t hostshort);

/**
 * @brief Converts 32-bit host endian-order integers to network endian-order integers
 *
 * Converts a given 32-bit host endian-order integer to a network endian-order integer.
 *
 * @param hostlong: host endian-order integer
 *
 * @return Converted network endian-order integers
 */
uint32_t htonl(uint32_t hostlong);

/**
 * @brief Converts 16-bit unsigned integers of network endianness to host endianness
 *
 * Converts the 16-bit unsigned integer of a given network endianness to the corresponding host endian.
 *
 * @param netshort:16-bit unsigned integer of the netshort network endian
 *
 * @return A 16-bit unsigned integer in the converted host endianism
 */
uint32_t ntohs(uint16_t netshort);

/**
 * @brief Converts the long integer number of network endenies to host endians
 *
 * Converts the long integer number of network endenians to the corresponding host endianness according to the endianness of the current system.
 *
 * @param netlong:long integer number of the netlong network endeny
 *
 * @return The long integer number of the converted host endians
 */
uint32_t ntohl(uint32_t netlong); /* ntohl function converts a uint32_t from TCP/IP network order to host byte order (which is little-endian on Intel processors). */

/**
 * @brief Calculate the checksum
 *
 * Calculate checksums based on a given data stream.
 *
 * @param src:stream pointer
 * @param len:stream size
 *
 * @return Checksum
 */
uint16_t checksum(unsigned char *src, unsigned int len);
#endif

9、main.c

#include "stm32f10x.h"//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "delay.h"
#include "USART4.h"
#include "LED.h"
#include "socket.h"
#include "Test_Ping.h"

/*
ping是Packet Internet Groper的缩写,中文意思是"因特网包探索器"。
ping用于确定本地主机能否与另一台主机成功交换(发送与接收)数据包,判断网络是否通畅。
Ping命令可以进行以下操作:
①通过将ICMP(Internet控制消息协议)回显(Echo)数据包发送到计算机,并侦听回显回复数据包来验证网络的物理连接。
②每个发送的数据包最多等待一秒。
③打印已传输和接收的数据包数。
ping成功只保证当前主机与目的主机间存在一条连通的物理路径。
IPRAW属于IP层的数据通信,它是比TCP、UDP低一层协议。
MACRAW是一个低于IP层的以太网MAC通信,它能够灵活使用目的主机的上层协议。
*/
//ioLibrary库下载地址
//下载地址:https://gitee.com/wiznet-hk/STM32F10x_W5500_Examples
//源文件下载地址:https://gitee.com/wiznet-hk
//密码生成工具:https://open.iot.10086.cn/doc/iot_platform/images/tools/token.exe
#include "wiz_platform.h"
#include "wizchip_conf.h"
#include "wiz_interface.h"
#include "W5500_Variable.h"
//#include "Do_DNS.h"

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{
  	
//	SCB->VTOR = 0x8000000;//中断向量表重定义

//	SystemInit();
	delay_init();//延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART4_Serial_Interface_Enable(115200);
	printf("%s",CPU_Reset_REG);//调试串口输出"\r\nCPU reset!\r\n"
	LED_Init();
	LED0_ON();

	wiz_timer_init();  //配置TIM2每毫秒中断一次
	wiz_spi_init();    //SPI1初始化
	wiz_rst_int_init();//初始化W5500的RST引脚和INT引脚
	printf("%s network install example\r\n",_WIZCHIP_ID_);

	wizchip_initialize();
  //1.注册SPI片选函数,单字节读写函数和多字节读写函数
  //2.W5500使用RST引脚复位
  //3.读取芯片版本号码,并检查是否正确
  //4.读PHY配置寄存器的bit[2:0],bit0=1表示W5500连接到局域网
  //bit1=1表示当前网速为100M,否则为10M
  //bit2=1表示当前以太网采用全双工通讯,否则为半双工通讯

	TCP_network_init(ethernet_buf, &net_info);
//设置本地网络信息
//1.使用"默认网络参数"设置本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式
//2.读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式,然后从串口输出

  socket(TCP_SOCKET0, Sn_MR_TCP, Local_Port, 0x00);
	//令SOCKET端口0工作在TCP模式,并设置TCP端口为Local_Port

	setSn_KPALVTR(TCP_SOCKET0, 6); // 30s keepalive
	//Socket在线时间寄存器,在线验证心跳包传输时间,他只在TCP模式下生效,在其他模式下将会被忽略,单位时间为5秒。
	//因此心跳包传输时间为6*5=30秒

  delay_ms(1000);
	W5500_Ping_RemoteComputer(TCP_SOCKET0, dest_ip,ethernet_buf);
	//PING计算机IP,看看能否收到数据
	delay_ms(1000);
	RemoteComputer_Ping_W5500(TCP_SOCKET0, dest_ip,ethernet_buf);

	delay_ms(1000);
  socket(TCP_SOCKET0, Sn_MR_TCP, Local_Port, 0x00);
	//令SOCKET端口0工作在TCP模式,并设置TCP端口为Local_Port
	setSn_KPALVTR(TCP_SOCKET0, 6); // 30s keepalive
	//Socket在线时间寄存器,在线验证心跳包传输时间,他只在TCP模式下生效,在其他模式下将会被忽略,单位时间为5秒。
	//因此心跳包传输时间为6*5=30秒
	while(1)
	{
		LED0=!LED0;
		delay_ms(500);
	}
}

找不到的函数,去前面的文章里去找。

10、测试结果

 

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐