W5500使用

更新时间:2025.5.19

前言

1.本文介绍使用STM32F103C8T6驱动W5500模块,采用硬件SPI(SPI2)控制W5500;本文介绍的是设置静态IP的方法。

2.因为对于计算机网络以及W5500模块不了解,这里不介绍知识点,只讲述使用方法。

3.详细的介绍及使用请参考官网w5500.com/w5500.html

1. 添加驱动文件

添加socket.c、wizchip_conf.c、W5500.c、BSP_W5500.c文件到工程中

img

2. 代码解析

socket.c、wizchip_conf.c、W5500.c这三个文件是官方写好的驱动文件这里不做解析,要想了解官方代码的含义,请参考官网介绍,这里主要解析自己写的驱动文件BSP_W5500.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#include "BSP_W5500.h"
#include "wizchip_conf.h"
#include "delay.h"
#include "string.h"
#include "stdio.h"

//初始化SPI2
void wiz_spi_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);


SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);

/* PB_12 -> CS 这个引脚可以换 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = WIZ_SCS_PIN;
GPIO_Init(WIZ_SCS_PORT, &GPIO_InitStructure);
GPIO_SetBits(WIZ_SCS_PORT, WIZ_SCS_PIN);
}
//初始化RST、INT引脚
void wiz_rst_int_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
/* PB_10 -> RST */
GPIO_InitStructure.GPIO_Pin = WIZ_RST_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(WIZ_RST_PORT, &GPIO_InitStructure);
GPIO_SetBits(WIZ_RST_PORT, WIZ_RST_PIN);

/* PB_11 -> INT */
GPIO_InitStructure.GPIO_Pin = WIZ_INT_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(WIZ_INT_PORT, &GPIO_InitStructure);
}

/*网关地址和板子IP地址在main.c中定义 */
extern uint8_t Gateway_ip[4]; /*网关地址*/
extern uint8_t local_ip[4]; /*板子IP地址*/
wiz_NetInfo gWIZNETINFO = { .mac = {0x78, 0x83, 0x68, 0x88, 0x56, 0x72},
.ip = {0}, /* 板子IP地址 */
.sn = {255,255,255,0},
.gw = {0}, /* 网关 */
.dns = {144,144,144,144},
.dhcp = NETINFO_STATIC}; //静态IP地址模式


//CS(片选)引脚拉低
void SPI_CS_Select(void)
{
W5500_CS_L;
}

//CS(片选)引脚拉高
void SPI_CS_Deselect(void)
{
W5500_CS_H;
}
/**
* 描述 : 向W5500写入1字节数据
* 参数 : TxData:要写入的数据
* 返回 : 无
*/
void wizchip_write_byte(uint8_t TxData)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{
}
SPI_I2S_SendData(SPI2, TxData);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
}
SPI_I2S_ReceiveData(SPI2);
}
/**
* 描述 : 从W5500读出1字节数据
* 参数 : 无
* 返回 : 读出的数据
*/
uint8_t wizchip_read_byte(void)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{
}
SPI_I2S_SendData(SPI2, 0xffff);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
}
return SPI_I2S_ReceiveData(SPI2);
}
/**
* 描述 : 向W5500写入len长度的数据
* 参数 : buf->要写入的数据
* 参数 : len->要写入的长度
* 返回 : 无
*/
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]);
}
}
/**
* 描述 : 从W5500读出len长度的数据
* 参数 : buf->存放读出的数据
* 参数 : 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();
}
}
/**
* 描述 : 打印以太网链路的参数(传输速度、模式)
*/
void wiz_print_phy_info(void)
{
uint8_t get_phy_conf;
get_phy_conf = getPHYCFGR();
printf("The current Mbtis speed : %dMbps\r\n", get_phy_conf & 0x02 ? 100 : 10); //打印传输速度
printf("The current Duplex Mode : %s\r\n", get_phy_conf & 0x04 ? "Full-Duplex" : "Half-Duplex");//打印工作模式
}
/**
* 描述 : 打印当前参数配置(MAC、IP等信息)
* 参数 : 无
* 返回 : 无
*/
void print_network_information(void)
{
wiz_NetInfo net_info;
wizchip_getnetinfo(&net_info); // 获取当前参数配置(MAC、IP等信息)

/* 判断是静态IP还是动态IP */
if (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");
}
//W5500芯片复位
void W5500_RESET(void)
{
W5500_REST_L;
delay_ms(50);
W5500_REST_H;
delay_ms(50);
}
//注册SPI函数
void wizchip_spi_cb_reg(void)
{
reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect); //注册SPI片选函数
reg_wizchip_spi_cbfunc(wizchip_read_byte, wizchip_write_byte); //注册SPI一个字节读写函数
reg_wizchip_spiburst_cbfunc(wizchip_read_buff, wizchip_write_buff); //注册SPI多字节读写函数
}
/**
* 描述 : 建立太网链路并检测
*/
void wiz_phy_link_check(void)
{
uint8_t phy_link_status;
do
{
delay_ms(1000);
ctlwizchip(CW_GET_PHYLINK, (void *)&phy_link_status);
if (phy_link_status == PHY_LINK_ON)
{
printf("PHY link\r\n");
wiz_print_phy_info(); //建立链路后打印链路信息
}
else
{
printf("PHY no link\r\n");
}
} while (phy_link_status == PHY_LINK_OFF);
}
//W5500初始化以及设置网络参数(MAC、IP等)
void W5500_ChipInit(void)
{
wizchip_spi_cb_reg(); //注册SPI函数
W5500_RESET(); //复位芯片
wiz_phy_link_check(); //建立太网链路并检测

memcpy(gWIZNETINFO.ip,local_ip,sizeof(local_ip)); //本地IP地址设置拷贝
memcpy(gWIZNETINFO.gw,Gateway_ip,sizeof(Gateway_ip)); //网关地址设置拷贝

wizchip_setnetinfo(&gWIZNETINFO); //初始化网络参数配置 MAC 静态IP配置等
print_network_information(); //打印初始化后的参数配置

}
#ifndef __BSP_W5500_H
#define __BSP_W5500_H
#include "sys.h"

#define W5500_REST_L GPIO_ResetBits(WIZ_RST_PORT,WIZ_RST_PIN); //复位引脚拉低
#define W5500_REST_H GPIO_SetBits(WIZ_RST_PORT,WIZ_RST_PIN); //复位引脚拉高

#define W5500_CS_L GPIO_ResetBits(WIZ_SCS_PORT,WIZ_SCS_PIN); //片选引脚拉低
#define W5500_CS_H GPIO_SetBits(WIZ_SCS_PORT,WIZ_SCS_PIN); //片选引脚拉高

#define WIZ_RST_PIN GPIO_Pin_10
#define WIZ_RST_PORT GPIOB
#define WIZ_INT_PIN GPIO_Pin_11
#define WIZ_INT_PORT GPIOB
#define WIZ_SCS_PIN GPIO_Pin_12
#define WIZ_SCS_PORT GPIOB
#define WIZ_SCK_PIN GPIO_Pin_13
#define WIZ_SCK_PORT GPIOB
#define WIZ_MISO_PIN GPIO_Pin_14
#define WIZ_MISO_PORT GPIOB
#define WIZ_MOSI_PIN GPIO_Pin_15
#define WIZ_MOSI_PORT GPIOB


void wiz_spi_init(void);
void wiz_rst_int_init(void);
void W5500_ChipInit(void);

#endif

3.使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**********************************************************************************
wizchip_SCS ---> STM32_GPIOB12
wizchip_SCLK ---> STM32_GPIOB13
wizchip_MISO ---> STM32_GPIOB14
wizchip_MOSI ---> STM32_GPIOB15
wizchip_RESET ---> STM32_GPIOB10
wizchip_INT ---> STM32_GPIOB11
**********************************************************************************/

#define SOCK_TCPC 1 /*Socket 端口选择, W5500一共8个端口:0-7 */

uint8_t Net_Status; //存放socket的状态
uint8_t W5500_RevBuf[1024]; //W5500接收缓存



/*远端IP地址(电脑IP地址)*/
uint8_t remote_ip[4] = {192,168,1,15};
/*远端端口(电脑端口)*/
uint16_t remote_port = 8888;

/*网关地址*/
uint8_t Gateway_ip[4] = {192,168,1,1};

/*本地IP(板子IP地址)*/
uint8_t local_ip[4] = {192,168,1,16};
/*本地端口(板子端口)*/
uint16_t local_port = 8899;

int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
delay_init();
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);

LED_init(); //LED初始化
uart1_init(115200); //串口1 用来打印参数信息

wiz_spi_init(); //SPI2初始化
wiz_rst_int_init(); //初始化RST、INT引脚
W5500_ChipInit(); //W5500初始化


while(1)
{

uint16_t Len;

Net_Status = getSn_SR(SOCK_TCPC);


switch(Net_Status) /*获取socket的状态*/
{
case SOCK_CLOSED: /*socket处于关闭状态*/
socket(SOCK_TCPC,Sn_MR_TCP,local_port,Sn_MR_ND);
break;
case SOCK_INIT: /*socket处于初始化状态*/
connect(SOCK_TCPC,remote_ip,remote_port);/*socket连接服务器*/
break;
case SOCK_ESTABLISHED: /*socket处于连接建立状态*/
if(getSn_IR(SOCK_TCPC) & Sn_IR_CON)
{
setSn_IR(SOCK_TCPC, Sn_IR_CON); /*清除接收中断标志位*/
}
Len=getSn_RX_RSR(SOCK_TCPC); /*获取接收的数据长度*/
if(Len>0) //接收到数据
{
recv(SOCK_TCPC,W5500_RevBuf,Len); /*接收来自Server的数据*/
send(SOCK_TCPC,W5500_RevBuf,Len); //返回给服务器
printf("%s",W5500_RevBuf);
}


break;
case SOCK_CLOSE_WAIT: /*socket处于等待关闭状态*/
close(SOCK_TCPC);
break;
}

}
}

4.电脑IP设置

因为步骤3中定义的电脑IP是固定的,所以必须把实际电脑IP设置成和步骤3中一样

/远端IP地址(电脑IP地址)/ uint8_t remote_ip[4] = {192,168,1,15};

操作下面步骤时候要把硬件通过网线连接到电脑

(1)搜索查看网络连接并点击

img

(2)右键点击属性

img

(3)双击协议版本4

img

(4)输入代码中定义的电脑IP地址、子网掩码、网关

img

(5)打开命令终端(按下Windows键和R键打开运行窗口,输入cmd并回车)并输入ipconfig查看配置是否成功

img

5.验证通信是否成功

(1)利用ping指令ping一下板子IP(每个人设置的可能不一样)

img

(2)打开串口调试助手并输入相关参数(注意本地IP和远端不要搞反)

img

(3)建立连接后,发送数据看是否能收发

img

总结

代码中只实现了数据的接收和发送,要想进行数据解析请自己编写代码。