当前位置: 首页 > news >正文

测试W5500的第3步_使用ioLibrary库创建TCPServer

W5500是一款具有8个Socket的网络芯片,支持TCP Server模式,最多可同时连接8个客户端。本文介绍了基于STM32F10x和W5500的TCP Server实现,包括SPI初始化、W5500复位、网络参数配置、Socket状态管理等功能,适用于需要多客户端连接的嵌入式网络应用场景。

w5500具有8个Socket,TCPserver模式下最多支持8个客户端同时访问。

文件下载地址:https://gitee.com/wiznet-hk/STM32F10x_W5500_Examples
源文件下载地址:https://gitee.com/wiznet-hk

1、wiz_platform.c有改动

#include "wiz_platform.h"
#include <stdio.h>
#include <stdint.h>
#include "wizchip_conf.h"
#include "wiz_interface.h"
#include "stm32f10x.h"
#include "delay.h"//函数功能:SPI1初始化
void wiz_spi_init(void)
{GPIO_InitTypeDef 	GPIO_InitStructure;SPI_InitTypeDef   SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);  //使能SPI1的外设时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;         //选择PIN5,是SPI1的SCLGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	  //选择引脚为复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的最高工作速率为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);  //根据GPIO_InitStructure结构指针所指向的参数配置PA5引脚	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;         //选择PIN6,是SPI1的MISOGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //选择引脚为输入悬浮GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的最高工作速率为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);  //根据GPIO_InitStructure结构指针所指向的参数配置PA6引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;         //选择PIN7,是SPI1的MOSIGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	  //选择引脚为复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的最高工作速率为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);  //根据GPIO_InitStructure结构指针所指向的参数配置PA7引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;         //选择PIN3,是W5500的片选脚CSGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //选择引脚为推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的最高工作速率为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);  //根据GPIO_InitStructure结构指针所指向的参数配置PA3引脚//设置SPI1的工作模式SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI发送接收为8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //设置SCK空闲时钟为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;      //数据捕获于第1个时钟沿//SCK空闲时钟为低电平,数据捕获于第1个时钟沿,这样就设置了SPI从机在下降沿采集数据了//SPI从机在下降沿采集数据,这要求CPU必须在SCK上升沿输出位值,在SCK为高电平时达到稳定,为数据采集做好准备SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;  //设置NSS输出由SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//设置波特率预分频值为2SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  //设置数据传输先从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;            //使用CRC7校验SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE); //使能SPI外设
}//函数功能:初始化W5500的RST引脚和INT引脚
void wiz_rst_int_init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOC, ENABLE ); //使能GPIOC外设的高速时钟/* W5500_RST引脚初始化配置(PC5) */GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5;	//选择PC5为W5500的RST引脚GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_ResetBits(GPIOC, GPIO_Pin_5);RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOC, ENABLE ); //使能GPIOC外设的高速时钟/* W5500_INT引脚初始化配置(PC4) */	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;	//选择PC4为W5500的INT引脚GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOC, &GPIO_InitStructure);
}//函数功能:使能SPI片选
void wizchip_select(void)
{GPIO_ResetBits(GPIOA,GPIO_Pin_4);//输出低电平表示选择W5500
}//函数功能:不使能SPI片选
void wizchip_deselect(void)
{GPIO_SetBits(GPIOA,GPIO_Pin_4);//输出高电平表示不选择W5500
}//函数功能:通过SPI,将dat的值发送给W5500
void wizchip_write_byte(uint8_t dat)
{while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){//检查SPI1的发送完成标志是否建立}SPI_I2S_SendData(SPI1, dat);//通过SPI,将dat发送给W5500while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){//检查SPI1的接收完成标志是否建立}SPI_I2S_ReceiveData(SPI1);//读SPI接收数据寄存器
}//函数功能:通过SPI读取1个字节,并返回
uint8_t wizchip_read_byte(void)
{while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){//检查SPI1的发送完成标志是否建立}SPI_I2S_SendData(SPI1,0xffff);//发送16个移位时钟,为接收数据作准备while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){//检查SPI1的接收完成标志是否建立}return SPI_I2S_ReceiveData(SPI1);//读SPI接收数据寄存器
}//函数功能:通过SPI,将buf[]中的前len个字节发送给W5500
void wizchip_write_buff(uint8_t *buf, uint16_t len)
{uint16_t idx = 0;for (idx = 0; idx < len; idx++){wizchip_write_byte(buf[idx]);//通过SPI,将buf[idx]的值发送给W5500}
}//函数功能:通过SPI读取len个字节,保存到buf[]中
void wizchip_read_buff(uint8_t *buf, uint16_t len)
{uint16_t idx = 0;for (idx = 0; idx < len; idx++){buf[idx] = wizchip_read_byte();//通过SPI读取1个字节,保存到buf[idx]中}
}//函数功能:W5500使用RST引脚复位
void wizchip_reset(void)
{GPIO_SetBits(GPIOC, GPIO_Pin_5);//复位引脚拉高delay_ms(10);GPIO_ResetBits(GPIOC, GPIO_Pin_5);//复位引脚拉低delay_ms(10);GPIO_SetBits(GPIOC, GPIO_Pin_5);//复位引脚拉高delay_ms(10);
}//函数功能:注册SPI片选函数,单字节读写函数和多字节读写函数
//1.注册SPI片选信号函数
//2.注册SPI读写单一字节函数
//3.注册SPI读写多字节函数
void wizchip_spi_cb_reg(void)
{reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);//注册SPI片选信号函数reg_wizchip_spi_cbfunc(wizchip_read_byte, wizchip_write_byte);//注册SPI读写单一字节函数reg_wizchip_spiburst_cbfunc(wizchip_read_buff, wizchip_write_buff);//注册SPI读写多字节函数
}//函数功能:配置TIM2每毫秒中断一次
void wiz_timer_init(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructure.TIM_Period = 1000 - 1;TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ClearFlag(TIM2, TIM_FLAG_Update);TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM2, ENABLE);
}//函数功能:使能TIM2中断
void wiz_tim_irq_enable(void)
{TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}//函数功能:不使能TIM2中断
void wiz_tim_irq_disable(void)
{TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
}//函数功能:TIM2每毫秒中断一次
void TIM2_IRQHandler(void)
{static uint32_t wiz_timer_1ms_count = 0;if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){wiz_timer_1ms_count++;if (wiz_timer_1ms_count >= 1000){wiz_timer_1ms_count = 0;}TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

2、wiz_platform.h

#ifndef __WIZ_PLATFORM_H__
#define __WIZ_PLATFORM_H__#include <stdint.h>/*** @brief   wiz spi init* @param   none* @return  none*/
void wiz_spi_init(void);/*** @brief   wiz rst and int pin init* @param   none* @return  none*/
void wiz_rst_int_init(void);/*** @brief   hardware reset wizchip* @param   none* @return  none*/
void wizchip_reset(void);/*** @brief   Register the WIZCHIP SPI callback function* @param   none* @return  none*/
void wizchip_spi_cb_reg(void);/*** @brief   wiz timer init* @param   none* @return  none*/
void wiz_timer_init(void);/*** @brief   Turn on wiz timer interrupt* @param   none* @return  none*/
void wiz_tim_irq_enable(void);/*** @brief   Turn off wiz timer interrupt* @param   none* @return  none*/
void wiz_tim_irq_disable(void);
#endif

3、wiz_interface.c有改动

#include "wiz_interface.h"
#include "wiz_platform.h"
#include "wizchip_conf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "delay.h"void wizchip_initialize(void);
void Server_network_init(uint8_t *ethernet_buff, wiz_NetInfo *conf_info);void wizchip_version_check(void);
void print_network_information(void);
void wiz_phy_link_check(void);
void wiz_print_phy_info(void);#define W5500_VERSION 0x04
//函数功能:读取芯片版本号码,并检查是否正确
void wizchip_version_check(void)
{uint8_t error_count = 0;while (1){delay_ms(1000);if (getVERSIONR() != W5500_VERSION){//读取芯片版本号码error_count++;if (error_count > 5){printf("error, %s version is 0x%02x, but read %s version value = 0x%02x\r\n", _WIZCHIP_ID_, W5500_VERSION, _WIZCHIP_ID_, getVERSIONR());while (1);}}else{break;}}
}/*** @brief Print PHY information*/
//函数功能:
//1.读PHY配置寄存器的bit1和bit2
//2.串口输出当前网速为100M/10M
//3.串口输出当前以太网采用全双工通讯/半双工通讯
void wiz_print_phy_info(void)
{uint8_t get_phy_conf;get_phy_conf = getPHYCFGR();//读PHY配置寄存器printf("The current Mbtis speed : %dMbps\r\n", get_phy_conf & 0x02 ? 100 : 10);//PHY配置寄存器,bit1=1表示网速为100M,bit1=0表示网速为10Mprintf("The current Duplex Mode : %s\r\n", get_phy_conf & 0x04 ? "Full-Duplex" : "Half-Duplex");//PHY配置寄存器,bit2=1表示以太网采用全双工通讯,bit2=0表示以太网采用半双工通讯
}//函数功能:
//读PHY配置寄存器的bit[2:0]
//bit0=1表示W5500连接到局域网
//bit1=1表示当前网速为100M,否则为10M
//bit2=1表示当前以太网采用全双工通讯,否则为半双工通讯
void wiz_phy_link_check(void)
{uint8_t phy_link_status;do{delay_ms(1000);ctlwizchip(CW_GET_PHYLINK, (void *)&phy_link_status);//读PH配置寄存器的bit0,保存到phy_link_status中,为1表示连接到局域网if (phy_link_status == PHY_LINK_ON){//W5500连接到局域网printf("PHY link\r\n");wiz_print_phy_info();//1.读PHY配置寄存器的bit1和bit2//2.串口输出当前网速为100M/10M//3.串口输出当前以太网采用全双工通讯/半双工通讯}else{printf("PHY no link\r\n");}} while (phy_link_status == PHY_LINK_OFF);
}//1.注册SPI片选函数,单字节读写函数和多字节读写函数
//2.W5500使用RST引脚复位
//3.读取芯片版本号码,并检查是否正确
//4.读PHY配置寄存器的bit[2:0],bit0=1表示W5500连接到局域网
//bit1=1表示当前网速为100M,否则为10M
//bit2=1表示当前以太网采用全双工通讯,否则为半双工通讯
void wizchip_initialize(void)
{wizchip_spi_cb_reg();//注册SPI片选函数,单字节读写函数和多字节读写函数wizchip_reset();//W5500使用RST引脚复位wizchip_version_check();//读取芯片版本号码,并检查是否正确//Read version registerwiz_phy_link_check();//读PHY配置寄存器的bit[2:0]//bit0=1表示W5500连接到局域网//bit1=1表示当前网速为100M,否则为10M//bit2=1表示当前以太网采用全双工通讯,否则为半双工通讯
}//函数功能:读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP,然后从串口输出
void print_network_information(void)
{wiz_NetInfo net_info;wizchip_getnetinfo(&net_info);// Get chip configuration information//读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCPif (net_info.dhcp == NETINFO_DHCP){printf("====================================================================================================\r\n");printf(" %s network configuration : DHCP\r\n\r\n", _WIZCHIP_ID_);}else{printf("====================================================================================================\r\n");printf(" %s network configuration : static\r\n\r\n", _WIZCHIP_ID_);}printf(" MAC         : %02X:%02X:%02X:%02X:%02X:%02X\r\n", net_info.mac[0], net_info.mac[1], net_info.mac[2], net_info.mac[3], net_info.mac[4], net_info.mac[5]);printf(" IP          : %d.%d.%d.%d\r\n", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3]);printf(" Subnet Mask : %d.%d.%d.%d\r\n", net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3]);printf(" Gateway     : %d.%d.%d.%d\r\n", net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3]);printf(" DNS         : %d.%d.%d.%d\r\n", net_info.dns[0], net_info.dns[1], net_info.dns[2], net_info.dns[3]);printf("====================================================================================================\r\n\r\n");
}//函数功能:TCP Server设置本地网络信息
//1.使用"默认网络参数"设置本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP
//2.读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP,然后从串口输出
void Server_network_init(uint8_t *ethernet_buff, wiz_NetInfo *conf_info)
{wizchip_setnetinfo(conf_info);//设置本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式print_network_information();//读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式,然后从串口输出
}

4、wiz_interface.h

#ifndef __WIZ_INTERFACE_H__
#define __WIZ_INTERFACE_H__#include "wizchip_conf.h"extern void wizchip_initialize(void);
extern void Server_network_init(uint8_t *ethernet_buff, wiz_NetInfo *conf_info);
#endif

5、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 default_net_info = {{0x00, 0x08, 0xdc,0x11, 0x11, 0x11},{192, 168, 1, 199},{255,255,255,0},{192, 168, 1, 1},{8,8,8,8},NETINFO_STATIC}; //静态IP,程序固化IP地址
wiz_NetInfo net_info;uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};uint8_t destip[8][4];//存放8个端口的远程IP地址
uint16_t destport[8];//存放8个远程端口值

6、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"extern wiz_NetInfo default_net_info;
extern wiz_NetInfo net_info;#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
extern uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE];extern uint8_t destip[8][4];
extern uint16_t destport[8];
#endif

7、TestTcpServer.c

#include "TestTcpServer.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "w5500.h"
#include "W5500_Variable.h"
#include "socket.h"//w5500具有8个Socket,TCPserver模式下最多支持8个客户端同时访问int32_t loop_TestTcpServer(uint8_t sn, uint8_t* buf, uint16_t port);/*** @brief   tcp server loopback test* @param   sn:    socket number* @param   buf:   Data sending and receiving cache* @param   port:  Listen port* @return  value for SOCK_ERRORs,return 1:no error 
*/
//sn为SOCKET端口
//buf为接收数据缓冲区
//port为本地端口
int32_t loop_TestTcpServer(uint8_t sn, uint8_t* buf, uint16_t port)
{int32_t ret;uint16_t size = 0, sentsize=0;switch(getSn_SR(sn))//获取W5500端口sn的状态寄存器{case SOCK_ESTABLISHED ://W5500端口sn已经连接成功if(getSn_IR(sn) & Sn_IR_CON){//读端口sn的Sn_IR中断标志寄存器的bit0
#ifdef _LOOP_TestTcpServer_DEBUG_getSn_DIPR(sn, destip[sn]);destport[sn] = getSn_DPORT(sn);printf("Socket%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[sn][0], destip[sn][1], destip[sn][2], destip[sn][3], destport[sn]);
#endifsetSn_IR(sn,Sn_IR_CON);//回写端口sn的Sn_IR中断标志寄存器的bit0,清除中断标志}if((size = getSn_RX_RSR(sn)) > 0)//读端口sn的Sn_RX_RSR寄存器,获取该端口的接收缓冲区的数据长度{if(size > ETHERNET_BUF_MAX_SIZE) size = ETHERNET_BUF_MAX_SIZE;ret = recv(sn, buf, size);//读"W5500端口sn"的数据,长度为size个字节,保存到bufbuf[ret]='\0';//添加字符串结束符printf("Socket%d recv: %s\n",sn,buf); //print the receive data.if(ret <= 0) return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.size = (uint16_t) ret;sentsize = 0;while(size != sentsize){ret = send(sn, buf+sentsize, size-sentsize);//将(buf+sentsize)为首地址的存储单元的前len个字节通过"W5500端口sn"发送出去if(ret < 0){close(sn);//关闭端口sn的连接, socket closereturn ret;}sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.}}break;case SOCK_CLOSE_WAIT ://W5500端口sn处于等待关闭状态
#ifdef _LOOP_TestTcpServer_DEBUG_printf("Socket%d:CloseWait\r\n",sn);
#endifif((ret = disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOP_TestTcpServer_DEBUG_printf("Socket%d:Socket Closed\r\n", sn);
#endifbreak;case SOCK_INIT ://W5500端口sn已经初始化
#ifdef _LOOP_TestTcpServer_DEBUG_printf("Socket%d:Listen port [%d]\r\n", sn, port);
#endifif( (ret = listen(sn)) != SOCK_OK)//监听SOCKET端口snreturn ret;break;case SOCK_CLOSED://W5500端口sn处于关闭状态
#ifdef _LOOP_TestTcpServer_DEBUG_printf("Socket%d:TCP server start\r\n",sn);
#endifif((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
#ifdef _LOOP_TestTcpServer_DEBUG_printf("Socket%d:Socket opened\r\n",sn);
#endifbreak;default:break;}return 1;
}

8、TestTcpServer.h

#ifndef _TestTcpServer_H
#define _TestTcpServer_H#include "stm32f10x.h"//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t#define TCPServerSOCEKET0        0     //W5500使用端口0作为TCP Server
#define TCPServerSOCEKET1        1     //W5500使用端口1作为TCP Server
#define TCPServerSOCEKET2        2     //W5500使用端口2作为TCP Server
#define TCPServerSOCEKET3        3     //W5500使用端口3作为TCP Server
#define TCPServerSOCEKET4        4     //W5500使用端口4作为TCP Server
#define TCPServerSOCEKET5        5     //W5500使用端口5作为TCP Server
#define TCPServerSOCEKET6        6     //W5500使用端口6作为TCP Server
#define TCPServerSOCEKET7        7     //W5500使用端口7作为TCP Server#define	_LOOP_TestTcpServer_DEBUG_  //允许串口跟踪extern int32_t loop_TestTcpServer(uint8_t sn, uint8_t* buf, uint16_t port);#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"//文件下载地址:https://gitee.com/wiznet-hk/STM32F10x_W5500_Examples
//源文件下载地址:https://gitee.com/wiznet-hk
#include "wiz_platform.h"
#include "wizchip_conf.h"
#include "wiz_interface.h"
#include "W5500_Variable.h"
#include "TestTcpServer.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);//设置系统中断优先级分组4USART4_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表示当前以太网采用全双工通讯,否则为半双工通讯Server_network_init(ethernet_buf, &default_net_info);
//TCP Server设置本地网络信息
//1.使用"默认网络参数"设置本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式
//2.读本地网络参数:MAC地址,GW网关,SN子网掩码,本地IP地址,DNS服务器IP地址,DHCP模式,然后从串口输出setSn_KPALVTR(TCPServerSOCEKET0, 6); // 30s keepalive//Socket在线时间寄存器,在线验证心跳包传输时间,他只在TCP模式下生效,在其他模式下将会被忽略,单位时间为5秒。//因此心跳包传输时间为6*5=30秒setSn_KPALVTR(TCPServerSOCEKET1, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET2, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET3, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET4, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET5, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET6, 6); // 30s keepalivesetSn_KPALVTR(TCPServerSOCEKET7, 6); // 30s keepalivewhile(1){loop_TestTcpServer(TCPServerSOCEKET0,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET1,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET2,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET3,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET4,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET5,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET6,ethernet_buf,5000);loop_TestTcpServer(TCPServerSOCEKET7,ethernet_buf,5000);LED0=!LED0;delay_ms(1000);}
}

10、工程样板

11、串口仿真结果

12、TCP Client客户机

 

相关文章:

测试W5500的第3步_使用ioLibrary库创建TCPServer

W5500是一款具有8个Socket的网络芯片&#xff0c;支持TCP Server模式&#xff0c;最多可同时连接8个客户端。本文介绍了基于STM32F10x和W5500的TCP Server实现&#xff0c;包括SPI初始化、W5500复位、网络参数配置、Socket状态管理等功能&#xff0c;适用于需要多客户端连接的嵌…...

Python训练营打卡——DAY31(2025.5.20)

目录 一、机器学习项目的流程 二、文件的组织 1. 项目核心代码组织 2. 配置文件管理 3. 实验与探索代码 4. 项目产出物管理 三、注意事项 if name "main" 编码格式 类型注解 四、通俗解释 1. 拆分文件和目录&#xff1a;整理房间一样管理代码​​ 2. 导…...

P1152 欢乐的跳

P1152 欢乐的跳 - 洛谷 使用map映射来解 #include<bits/stdc.h> using namespace std; int n,a[1005],c[1005]; map<int,int>b;//因为要记录1~n-1是否都出现了 int main(){cin>>n;cin>>a[1];for(int i2;i<n;i){cin>>a[i];//c[i-1]a[i]-a[…...

基于 STM32 的蔬菜智能育苗系统硬件与软件设计

一、系统总体架构 蔬菜智能育苗系统通过单片机实时采集温湿度、光照等环境数据,根据预设阈值自动控制灌溉、补光、通风等设备,实现育苗环境的智能化管理。系统主要包括以下部分: 主控芯片:STM32F103C8T6(32 位 ARM Cortex-M3 单片机,性价比高,适合嵌入式控制)传感器模…...

数论:数学王国的密码学

在计算机科学的世界里&#xff0c;数论就像是一把神奇的钥匙&#xff0c;能够解开密码学、算法优化、随机数生成等诸多领域的谜题。作为 C 算法小白&#xff0c;今天我就带大家一起走进数论的奇妙世界&#xff0c;探索其中的奥秘。 什么是数论&#xff1f; 数论是纯粹数学的分…...

软考软件评测师——黑盒测试测试方法

以下为优化后的博客内容&#xff1a; 软件测试方法论精要 第一部分 核心知识点解析 一、等价类划分法 基本概念 将测试对象的输入域划分为若干子集&#xff0c;每个子集选取代表性样本作为测试用例。分为有效等价类&#xff08;合法输入&#xff09;和无效等价类&#xff0…...

python训练 60天挑战-day31

知识点回顾 规范的文件命名规范的文件夹管理机器学习项目的拆分编码格式和类型注解 昨天我们已经介绍了如何在不同的文件中&#xff0c;导入其他目录的文件&#xff0c;核心在于了解导入方式和python解释器检索目录的方式。 搞清楚了这些&#xff0c;那我们就可以来看看&#x…...

2025年电工杯新规发布-近三年题目以及命题趋势

电工杯将于2025.5.23 周五早八正式开赛&#xff0c;该竞赛作为上半年度竞赛规模最大的竞赛&#xff0c;因免报名费、一级学会承办等因素&#xff0c;被众多高校认可。本文将在从2025年竞赛新规、历史赛题选题分析、近年优秀论文分享、竞赛模板分析等进行电工杯备赛&#xff0c;…...

四元数中 w xyz 的含义及应用

四元数是一种用于表示三维空间中旋转的数学工具&#xff0c;形式通常为 qwxiyjzk&#xff0c;其中w 是实部&#xff0c;x,y,z 是虚部。它们的含义如下&#xff1a; 1. w&#xff08;实部&#xff09; 2. x,y,z&#xff08;虚部/向量部分&#xff09; 3. 单位四元数的条件 四元…...

CSS 样式表的四种应用方式详解以及css注释的应用

一、外部 CSS&#xff08;推荐方式&#xff09; 定义&#xff1a;将 CSS 代码保存为独立的 .css 文件&#xff0c;通过 <link> 标签引入 HTML。 优点&#xff1a; 实现内容与样式完全分离多个页面可共享同一 CSS 文件浏览器可缓存 CSS 文件&#xff0c;提升加载速度 …...

IntentUri页面跳转

android browser支持支持Intent Scheme URL语法的可以在wrap页面加载或点击时&#xff0c;通过特定的intent uri链接可以打开对应app页面&#xff0c;例如 <a href"intent://whatsapp/#Intent;schememyapp;packagecom.xiaoyu.myapp;S.help_urlhttp://Fzxing.org;end&qu…...

蓝桥杯2114 李白打酒加强版

问题描述 话说大诗人李白, 一生好饮。幸好他从不开车。 一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱: 无事街上走&#xff0c;提显去打酒。 逢店加一倍, 遇花喝一斗。 这一路上, 他一共遇到店 N 次, 遇到花 M 次。已知最后一次遇到的是花, 他正好把酒喝光了。…...

[ 计算机网络 ] 深入理解OSI七层模型

&#x1f389;欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨ &#x1f389;感谢各位读者在百忙之中抽出时间来垂阅我的文章&#xff0c;我会尽我所能向的大家分享我的知识和经验&#x1f4d6; &#x1f389;希望我们在一篇篇的文章中能够共同进步&#xff01;&#xff01;&…...

实战:基于Pangolin Scrape API,如何高效稳定采集亚马逊BSR数据并破解反爬虫?

引言&#xff1a;BSR数据——亚马逊运营的"指南针" 在竞争激烈的亚马逊市场&#xff0c;BSR (Best Sellers Rank) 数据已经成为卖家们不可或缺的"指南针"。这一数字化指标不仅反映商品在特定品类中的销售表现&#xff0c;更直接影响平台的流量分配和消费者…...

电子制造企业智能制造升级:MES系统应用深度解析

在全球电子信息产业深度变革的2025年&#xff0c;我国电子信息制造业正经历着增长与转型的双重考验。据权威数据显示&#xff0c;2025年一季度行业增加值同比增长11.5%&#xff0c;但智能手机等消费电子产量同比下降1.1%&#xff0c;市场竞争白热化趋势显著。叠加关税政策调整、…...

lambda架构和kappa架构区别

Lambda架构与Kappa架构是大数据处理领域的两种核心架构模式&#xff0c;主要差异体现在数据处理逻辑、系统复杂度和适用场景等方面。以下是二者的详细对比分析&#xff1a; 一、核心设计差异 ‌Lambda架构 包含三层&#xff1a;批处理层&#xff08;Batch Layer&#xff09;、…...

【css知识】flex-grow: 1

目录 一、基本概念&#xff1a;二、工作原理&#xff1a;多个元素的情况&#xff1a; 三、实际应用示例&#xff1a;常见使用场景&#xff1a;注意事项&#xff1a; 四、最佳实践&#xff1a;五、与其他 flex 属性配合&#xff1a; &#x1f680;写在最后 flex-grow: 1是什么&a…...

六足连杆爬行机器人的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序 4.系统原理简介 5.完整工程文件 1.课题概述 六足连杆爬行机器人的simulink建模与仿真。通过simulink&#xff0c;对六足机器人的六足以及机身进行simulink建模&#xff0c;模拟其行走&#xff0c;仿真输出机器人行走时六足的坐…...

软考软件测评师——系统安全设计(防火墙技术)

目录 一、核心概念解析 二、技术联动体系 三、技术局限认知 四、网络架构设计 五、防护系统测试规范 一、核心概念解析 1. 防火墙技术 网络安全基础防护体系&#xff0c;通过软硬件结合方式在内外部网络间建立隔离屏障。核心作用包括流量监控、访问控制、日志记录三大模块…...

漏洞检测与渗透检验在功能及范围上究竟有何显著差异?

漏洞检测与渗透检验是确保系统安全的重要途径&#xff0c;这两种方法各具特色和功效&#xff0c;它们在功能上有着显著的差异。 目的不同 漏洞扫描的主要任务是揭示系统内已知的安全漏洞和隐患&#xff0c;这就像是对系统进行一次全面的健康检查&#xff0c;看是否有已知的疾…...

探秘「4+3原型驱动的交付模式」如何实现软件快速定制

软件行业长期受困于需求沟通难题&#xff1a;客户需求表达不清、频繁变更及真伪需求混杂难辨&#xff1b;终端业务部门参与度低加剧后期确认困难&#xff0c;加之调研结果传递失真引发功能实现偏差——"需求黑洞"始终是甲乙双方的共同痛点。 然而&#xff0c;NC科技…...

C语言入门

一、认识C语言 什么是C语言 C语言是一门通用计算机编程语言&#xff0c;广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。 尽管C语言提供了许多低级处理的功能&#xff0c…...

java 异常验证框架validation,全局异常处理,请求验证

1、依赖 异常验证框架validation<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>${spring-boot.version}</version></dependency> 当鼠标放在依…...

如何使用VH6501进行CAN采样点测试

Vector 的 VH6501 是一种专为 CAN 和 CAN FD 网络设计的干扰测试设备&#xff0c;集成了干扰生成和 CANoe 网络接口功能&#xff0c;支持通过 CAPL 脚本实现测试自动化。 硬件规格如下&#xff1a; VH6501采样点测试原理是&#xff1a;干扰一帧报文中某一位的采样点附近的总线电…...

QT6 源(113)篇二:阅读与注释工具栏 QToolBar,给出源码

&#xff08;9&#xff09;本源码来自于头文件 qtoolbar . h &#xff1a; #ifndef QDYNAMICTOOLBAR_H #define QDYNAMICTOOLBAR_H#include <QtWidgets/qtwidgetsglobal.h> #include <QtGui/qaction.h> #include <QtWidgets/qwidget.h>QT_REQUIRE_CONFIG(to…...

编程日志5.13

邻接表的基础代码 #include<iostream> using namespace std; //邻接表的类声明 class Graph {private: //结构体EdgeNode表示图中的边结点,包含顶点vertex、权重weight和指向下一个边结点的指针next struct EdgeNode { int vertex; int weight; …...

Java 08集合

集合 Collection 接口&#xff0c;不可以创建对象add clear remove contains(Object obj);判断是否存在 isEmpty 空返回为true sizeArrayList Collection<String> cnew ArraryList<>(); 以多态的方法创建集合对象&#xff0c;调用单列集合中的共有方法 编译看…...

CSS 背景全解析:从基础属性到视觉魔法

CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: background-color background-image background-repeat background-attachment background-position 一、background-color&#xff1a;背景颜色 作用&#xff1a;设置元素的背景色&#xff0c;支持所有合法…...

2025华为OD机试真题+全流程解析+备考攻略+经验分享+Java/python/JavaScript/C++/C/GO六种语言最佳实现

华为OD全流程解析&#xff0c;备考攻略 快捷目录 华为OD全流程解析&#xff0c;备考攻略一、什么是华为OD&#xff1f;二、什么是华为OD机试&#xff1f;三、华为OD面试流程四、华为OD薪资待遇及职级体系五、ABCDE卷类型及特点六、题型与考点七、机试备考策略八、薪资与转正九、…...

中小型制造业信息化战略规划指南

1 引言 在当今技术飞速发展和全球竞争日趋激烈的时代&#xff0c;信息化建设对于中小型制造企业&#xff08;SME&#xff09;而言&#xff0c;已不再是可有可无的选项&#xff0c;而是关乎生存、发展和保持持续竞争力的核心要素。在数字化浪潮席卷全球的背景下&#xff0c;制造…...

PowerBI 矩阵实现动态行内容(如前后销售数据)统计数据,以及过滤同时为0的数据

我们有一张活动表 和 一张销售表 我们想实现如下的效果&#xff0c;当选择某个活动时&#xff0c;显示活动前后3天的销售对比图&#xff0c;如下&#xff1a; 实现方法&#xff1a; 1.新建一个表&#xff0c;用于显示列&#xff1a; 2.新建一个度量值&#xff0c;用SELECTEDVA…...

在QT中栅格布局里套非栅格布局的布局会出现父布局缩放子布局不跟随的问题

这个是 Qt Designer 设计界面中的一个“常见陷阱”。 &#x1f9e0; 结论先说&#xff1a; 在 Qt Designer 中使用栅格布局&#xff08;Grid Layout&#xff09;嵌套其他栅格布局&#xff0c;一般不会出问题&#xff0c;但如果嵌套的是水平布局&#xff08;HBox&#xff09;或垂…...

Pydantic数据验证实战指南:让Python应用更健壮与智能

导读&#xff1a;在日益复杂的数据驱动开发环境中&#xff0c;如何高效、安全地处理和验证数据成为每位Python开发者面临的关键挑战。本文全面解析了Pydantic这一革命性数据验证库&#xff0c;展示了它如何通过声明式API和类型提示系统&#xff0c;彻底改变Python数据处理模式。…...

深度解析 HDFS与Hive的关系

1. HDFS 和 Hive 如何协同 我们将从 HDFS&#xff08;Hadoop Distributed File System&#xff09; 的架构入手&#xff0c;深入剖析其核心组成、工作机制、内部流程与高可用机制。然后详细阐述 Hive 与 HDFS 的关系&#xff0c;从执行流程、元数据管理、文件读写、计算耦合等…...

ArrayList源码分析

1. ArrayList默认初始化容量 首先编写一个简单的初始化ArrayList的代码 List<String> li new ArrayList<>();然后进入ArrayList中&#xff0c;在无参数构造方法中可以查看到上面的绿色注释中写了构造一个空的集合并且初始化容量为10。接下来继续查看源码&#x…...

文件操作和IO-2 使用Java操作文件

Java操作文件的API 1、针对文件系统的操作。包括但不限于&#xff1a;创建文件、删除文件、重命名文件、列出目录内容…… 2、针对文件内容的操作。读文件/写文件 Java中针对文件的操作&#xff0c;使用File类来进行操作&#xff0c;这个类被存储在java.io这个包里面。 i&a…...

day 31

文件的拆分 1. 项目核心代码组织 src/&#xff08;source的缩写&#xff09;&#xff1a;存放项目的核心源代码。 2. 配置文件管理 config/ 目录&#xff1a;集中存放项目的配置文件&#xff0c;方便管理和切换不同环境&#xff08;开发、测试、生产&#xff09;的配置。 …...

基于Python批量删除文件和批量增加文件

一、为什么写这么一个程序 其实原因也是很简单的&#xff0c;我去网上下载了一个文件夹&#xff0c;里面太多别人的文件了&#xff0c;我不喜欢&#xff0c;所以我就写了这么一个代码。 二、安装Python和vscode 先安装Python在安装vscode Python安装 vscode的安装 三、源码…...

【信息系统项目管理师】第12章:项目质量管理 - 26个经典题目及详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第…...

ShenNiusModularity项目源码学习(27:ShenNius.Admin.Mvc项目分析-12)

订单列表页面用于浏览、检索、维护商城模块的订单信息。订单列表页面的后台控制器类OrderController位于ShenNius.Admin.Mvc项目的Areas\Shop\Controllers内&#xff0c;页面文件位于同项目的Areas\Shop\Views\Order内&#xff0c;其中Index.cshtml页面为主页面&#xff0c;Det…...

(T_T),不小心删掉RabbitMQ配置文件数据库及如何恢复

一、不小心删除 今天是2025年5月15日&#xff0c;非常沉重的一天&#xff0c;就在今早8点左右的时候我打算继续做我的毕业设计&#xff0c;由于开机的过程十分缓慢&#xff08;之前没有&#xff09;&#xff0c;加上刚开机电脑有卡死的迹象&#xff0c;再加上昨天晚上关电脑前…...

【Python装饰器深度解析】从语法糖到元编程实战

目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选型对比🛠️ 二、实战演示⚙️ 环境配置要求💻 核心代码实现案例1:基础计时装饰器案…...

操作系统学习笔记第5章 (竟成)

目录 第 5 章 输入 / 输出 (I/O) 管理 5.1 I/O 管理基础 5.1.1 I/O 设备 1.I/O 设备的基本概念 2.I/O 设备的分类 3.I/O 接口 4.I/O 端口 (1) I/O 端口的概念 (2) I/O 端口的编址 ① 独立编址方式 ② 统一编址方式 5.1.2 I/O 控制方式 1. 程序查询方式 2. 程序中断方式 3. DMA …...

【DCGMI专题1】---DCGMI 在 Ubuntu 22.04 上的深度安装指南与原理分析(含架构图解)

目录 一、DCGMI 概述与应用场景 二、Ubuntu 22.04 系统准备 2.1 系统要求 2.2 环境清理(可选) 三、DCGMI 安装步骤(详细图解) 3.1 安装流程总览 3.2 分步操作指南 3.2.1 系统更新与依赖安装 3.2.2 添加 NVIDIA 官方仓库 3.2.3 安装数据中心驱动与 DCGM 3.2.4 服务…...

C# 使用 OpenCV 基础

一、C#安装OpenCV 安装上面两个模块 二、使用 导入 using OpenCvSharp;加载图片 // 导入图片 Mat image Cv2.ImRead("C:\x5.bmp"); // 拷贝 Mat image2 image.Clone();// 打开窗口 Cv2.NamedWindow("image", WindowFlags.AutoSize); // 显示图片 Cv2…...

如何解决全局或静态变量被修改的bug

问题卡死 程序原来设置Firware name 时N32G475&#xff0c;在程序运行时&#xff0c;程序崩溃&#xff0c;发现输出的固件名称没有了&#xff0c;这里说明固件名称被程序修改了 程序在开机时都是对的 打开map文件查找fw_name的内存地址&#xff0c;他的值被更改&#xff0c;就…...

[Java实战]Spring Boot整合Sentinel:流量控制与熔断降级实战(二十九)

[Java实战]Spring Boot整合Sentinel&#xff1a;流量控制与熔断降级实战&#xff08;二十九&#xff09; 一、Sentinel简介 Sentinel是阿里开源的分布式系统流量防卫组件&#xff0c;核心功能包括&#xff1a; 流量控制&#xff1a;根据QPS、线程数等指标限制资源访问熔断降…...

Linux系统中,Ctrl+C的运行过程是什么?

文章目录 前言1.终端驱动捕获键盘输入2.信号发送到前台进程组3. 进程处理信号4. 信号传递的详细流程5. Shell 的后续处理关键机制说明扩展&#xff1a;其他相关信号总结 前言 今天看到有个小伙伴面试问到这个问题&#xff0c;感觉挺有意思&#xff0c;我们后端开发者相信都用过…...

101个α因子#9

((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ? delta(close, 1) : (-1 * delta(close, 1))))worldquant brain平台上调整后的语法&#xff1a; ((0 < min(close-ts_delay(close, 1), ts_delay(close, 1)-ts_delay(c…...

DAY28 超大力王爱学Python

知识点回顾&#xff1a; 类的定义pass占位语句类的初始化方法类的普通方法类的继承&#xff1a;属性的继承、方法的继承 作业 题目1&#xff1a;定义圆&#xff08;Circle&#xff09;类 import mathclass Circle:def __init__(self, radius1):self.radius radius # 半径属性…...