测试W5500的第10步_使用W5500去PING计算机
本文主要介绍采用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、测试结果


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



所有评论(0)