---
title: "STM Lesson 91. LAN. W5500. HTTP Server. Part 2"
url: "https://maker.wiznet.io/teddy/projects/stm-lesson-91-lan-w5500-http-server-part-2/"
markdown_url: "https://maker.wiznet.io/teddy/projects/stm-lesson-91-lan-w5500-http-server-part-2/md"
type: "UCC: User Created Content"
author: "Narod stream"
author_url: "https://narodstream.ru/stm-urok-91-lan-w5500-http-server-chast-2/"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "Narod stream"
original_url: "https://narodstream.ru/stm-urok-91-lan-w5500-http-server-chast-2/"
published: "2023-08-02"
language: "en"
likes: 0
views: 350
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# STM Lesson 91. LAN. W5500. HTTP Server. Part 2

> STM Lesson 91. LAN. W5500. HTTP Server. Part 2

Original author: Narod stream (source: https://narodstream.ru/stm-urok-91-lan-w5500-http-server-chast-2/)

## Article

**Part 2**

## **LAN. W5500. HTTP server**

B [**previous part**](https://narodstream.ru/stm-urok-91-lan-w5500-http-server-chast-1/) we got acquainted with the W5500 module, studied the organization of memory and data exchange of the W5500 chip, created and configured the project.

Initialization begins with a reboot of the module. I took this from an example written for an assessment fee and posted on an official website, I did not find this in the technical documentation.

So let's start writing the initialization function in the file **w5500.c**

`**//-----------------------------------------------**`

`**void**``** w5500_ini(**``**void**``**)**`

`**{**`

`** uint8_t**``** dtt=0;**`

`** uint8_t**``** opcode=0;**`

`** //Hard Reset**`

`** HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, **``***GPIO_PIN_RESET***``**);**`

`** HAL_Delay(70);**`

`** HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, **``***GPIO_PIN_SET***``**);**`

`** HAL_Delay(70);**`

`**}**`

`**//-----------------------------------------------**`

We will write a prototype for this function and connect our module in a file **net.h**

`#include``<stdint.h>`

`**#include**````**"w5500.h"**`

In the net.c file in the corresponding function, call our initialization function

`void``net_ini(``void``)`

`{`

`** w5500_ini();**`

`}`

After a hardware reboot using the RESET leg, we will restart the software.

To do this, first write some macros in the file **w5500.h**

`#define``MAC_ADDR {0x00,0x15,0x42,0xBF,0xF0,0x51}`

`**//--------------------------------------------------**`

`**#define**``** BSB_COMMON 0x00**`

`**#define**``** BSB_S0 0x01**`

`**#define**``** BSB_S0_TX 0x02**`

`**#define**``** BSB_S0_RX 0x03**`

`**//--------------------------------------------------**`

`**#define**``** RWB_WRITE 1**`

`**#define**``** RWB_READ 0**`

`**//--------------------------------------------------**`

`**#define**``** OM_FDM0 0x00**``**//режим передачи данных переменной длины**`

`**#define**``** OM_FDM1 0x01**``**//режим передачи данных по одному байту**`

`**#define**``** OM_FDM2 0x02**``**//режим передачи данных по два байта**`

`**#define**``** OM_FDM3 0x03**``**//режим передачи данных по четыре байта**`

`**//--------------------------------------------------**`

`**#define**``** MR 0x0000**``**//Mode Register**`

`**//--------------------------------------------------**`

Above the initialization function in the w5500.c file we write the function of writing the byte in the register

`**//-----------------------------------------------**`

`**void**``** w5500_writeReg(**``**uint8_t**``** op, **``**uint16_t**``** addres, **``**uint8_t**``** data)**`

`**{**`

`** uint8_t**``** buf[] = {addres >> 8, addres, op|(RWB_WRITE<<2), data};**`

`** SS_SELECT();**`

`** HAL_SPI_Transmit(&hspi1, buf, 4, 0xFFFFFFFF);**`

`** SS_DESELECT();**`

`**}**`

`**//-----------------------------------------------**`

We sequentially write to the 4-byte buffer the address of the register ( memory cells ), then the operation code with the one attached to it using the operation **OR** a bit of recording and a actually byte of data. Then we lower the selection leg, pass these 4 bytes using the corresponding function of the HAL library, and then lift the device selection leg.

Now write the code for the software reboot of the module into the initialization function

`HAL_Delay(70);`

`**//Soft Reset**`

`**opcode = (BSB_COMMON<<3)|OM_FDM1;**`

`**w5500_writeReg(opcode, MR, 0x80);**`

`**HAL_Delay(100);**`

Register we use a common **Mr, **and the mode of fixed transmission of one byte

![image21](https://narodstream.ru/wp-content/uploads/2017/09/image21-1.png)

We only take the 7th bit in it. After that, you need to wait in theory when this bit drops. Thus, we find out that the reboot has occurred. But it’s enough just to wait a few milliseconds, not often we initialize the chip.

Next, we configure all the addresses for our chip, entering them also in certain registers. Before that, we will add macros to the header file for this **w5500.h**

`#define``MR 0x0000``//Mode Register`

`**//--------------------------------------------------**`

`**#define**``** SHAR0 0x0009**``**//Source Hardware Address Register MSB**`

`**#define**``** SHAR1 0x000A**`

`**#define**``** SHAR2 0x000B**`

`**#define**``** SHAR3 0x000C**`

`**#define**``** SHAR4 0x000D**`

`**#define**``** SHAR5 0x000E**``**// LSB**`

`**#define**``** GWR0 0x0001**``**//Gateway IP Address Register MSB**`

`**#define**``** GWR1 0x0002**`

`**#define**``** GWR2 0x0003**`

`**#define**``** GWR3 0x0004**``**// LSB**`

`**#define**``** SUBR0 0x0005**``**//Subnet Mask Register MSB**`

`**#define**``** SUBR1 0x0006**`

`**#define**``** SUBR2 0x0007**`

`**#define**``** SUBR3 0x0008**``**// LSB**`

`**#define**``** SIPR0 0x000F**``**//Source IP Address Register MSB**`

`**#define**``** SIPR1 0x0010**`

`**#define**``** SIPR2 0x0011**`

`**#define**``** SIPR3 0x0012**``**// LSB**`

`**//--------------------------------------------------**`

Which register is responsible for what is visible from the comments on it.

Let's move to the initialization function to a file **w5500.c** and configure register data

`HAL_Delay(100);`

`**//Configute Net**`

`**w5500_writeReg(opcode, SHAR0,macaddr[0]);**`

`**w5500_writeReg(opcode, SHAR1,macaddr[1]);**`

`**w5500_writeReg(opcode, SHAR2,macaddr[2]);**`

`**w5500_writeReg(opcode, SHAR3,macaddr[3]);**`

`**w5500_writeReg(opcode, SHAR4,macaddr[4]);**`

`**w5500_writeReg(opcode, SHAR5,macaddr[5]);**`

`**w5500_writeReg(opcode, GWR0,ipgate[0]);**`

`**w5500_writeReg(opcode, GWR1,ipgate[1]);**`

`**w5500_writeReg(opcode, GWR2,ipgate[2]);**`

`**w5500_writeReg(opcode, GWR3,ipgate[3]);**`

`**w5500_writeReg(opcode, SUBR0,ipmask[0]);**`

`**w5500_writeReg(opcode, SUBR1,ipmask[1]);**`

`**w5500_writeReg(opcode, SUBR2,ipmask[2]);**`

`**w5500_writeReg(opcode, SUBR3,ipmask[3]);**`

`**w5500_writeReg(opcode, SIPR0,ipaddr[0]);**`

`**w5500_writeReg(opcode, SIPR1,ipaddr[1]);**`

`**w5500_writeReg(opcode, SIPR2,ipaddr[2]);**`

`**w5500_writeReg(opcode, SIPR3,ipaddr[3]);**`

Since data registers are also common, the opcode does not change.

Now set up a port for socket 0.

To do this, add registers for port numbers to a file **w5500.h**

`#define``SIPR3 0x0012``// LSB`

`//--------------------------------------------------`

`**#define**``** Sn_PORT0 0x0004 **``**// Socket 0 Source Port Register MSB**`

`**#define**``** Sn_PORT1 0x0005 **``**// Socket 0 Source Port Register LSB**`

`**//--------------------------------------------------**`

Now in the initialization function in the file **w5500.h** enter the data of our port in the registers

`w5500_writeReg(opcode, SIPR3,ipaddr[3]);`

`**//Настраиваем сокет 0**`

`**opcode = (BSB_S0<<3)|OM_FDM1;**`

`**w5500_writeReg(opcode, Sn_PORT0,local_port>>8);**`

`**w5500_writeReg(opcode, Sn_PORT1,local_port);**`

Here, the type of register is already changing, so we will initialize the opcode again.

In principle, at this step we can already collect the code and pass the controller.

And we will already have our module to ping. That is, ICMP and ARP will work.

Let's do it.

Before stitching the controller, let's see our ( scheme, click on the image to enlarge the image )

[![image03_0500](https://narodstream.ru/wp-content/uploads/2017/09/image03_0500.jpg)](https://narodstream.ru/wp-content/uploads/2017/09/image03.jpg)

We will open the controller and check the availability of our module

![image23](https://narodstream.ru/wp-content/uploads/2017/09/image23.png)

Everything is working! You can continue further.

In file **w5500.h** add a structure for the properties of the connection

`#define``be16toword(a) ((((a)>>8)&0xff)|(((a)<<8)&0xff00))`

`**//--------------------------------------------------**`

`**typedef**````**struct**````**tcp_prop**``** {**`

`**volatile**````**uint8_t**````**cur_sock**``**;**``**//активный сокет**`

`**} **``**tcp_prop_ptr**``**;**`

`**//--------------------------------------------------**`

Add a global variable of the type of our structure in the file **w5500.c**

`extern``char``str1[60];`

`**tcp_prop_ptr**``** tcpprop;**`

In the initialization pound, we initialize the active ( current ) socket

`w5500_writeReg(opcode, Sn_PORT1,local_port);`

`**//инициализируем активный сокет**`

`**tcpprop.cur_sock = 0;**`

After the register write function, add the function of reading data from the register

`**//-----------------------------------------------**`

`**uint8_t**``** w5500_readReg(**``**uint8_t**``** op, **``**uint16_t**``** addres)**`

`**{**`

`** uint8_t**``** data;**`

`** uint8_t**``** wbuf[] = {addres >> 8, addres, op, 0x0};**`

`** uint8_t**``** rbuf[4];**`

`** SS_SELECT();**`

`** HAL_SPI_TransmitReceive(&hspi1, wbuf, rbuf, 4, 0xFFFFFFFF);**`

`** SS_DESELECT();**`

`** data = rbuf[3];**`

`** return**``** data;**`

`**}**`

`**//-----------------------------------------------**`

Here we work somewhat differently. We type the same thing into the buffer, only we don’t include the bit of the record, and you can use any data by writing to buffer 0. Then we organize another buffer and call up the function of ring data exchange on the SPI bus, which will return to us in the last element of the array the byte we need from the register.

In the w5500.h file, we will add a few more macros with register addresses and some parameters and conditions that we will meet later

`#define``Sn_PORT1 0x0005 ``// Socket 1 Source Port Register 1 LSB`

`**//--------------------------------------------------**`

`**#define**``** Sn_MR 0x0000 **``**// Socket 0 Mode Register**`

`**#define**``** Sn_CR 0x0001 **``**// Socket 0 Command Register**`

`**#define**``** Sn_SR 0x0003 **``**// Socket 0 Status Register**`

`**//--------------------------------------------------**`

`**//Socket mode**`

`**#define**``** Mode_CLOSED 0x00**`

`**#define**``** Mode_TCP 0x01**`

`**#define**``** Mode_UDP 0x02**`

`**#define**``** Mode_MACRAV 0x04**`

`**//--------------------------------------------------**`

`**//Socket states**`

`**#define**``** SOCK_CLOSED 0x00**`

`**#define**``** SOCK_INIT 0x13**`

`**#define**``** SOCK_LISTEN 0x14**`

`**#define**``** SOCK_ESTABLISHED 0x17**`

`**//-------------------------------------------**`

`**#define**``** Sn_MSSR0 0x0012**`

`**#define**``** Sn_MSSR1 0x0013**`

`**#define**``** Sn_TX_FSR0 0x0020**`

`**#define**``** Sn_TX_FSR1 0x0021**`

`**#define**``** Sn_TX_RD0 0x0022**`

`**#define**``** Sn_TX_RD1 0x0023**`

`**#define**``** Sn_TX_WR0 0x0024**`

`**#define**``** Sn_TX_WR1 0x0025**`

`**#define**``** Sn_RX_RSR0 0x0026**`

`**#define**``** Sn_RX_RSR1 0x0027**`

`**#define**``** Sn_RX_RD0 0x0028**`

`**#define**``** Sn_RX_RD1 0x0029**`

`**//--------------------------------------------------**`

Let's go to the file **w5500.c** and add two more functions to initialize and wait for the end of socket initialization

`**//-----------------------------------------------**`

`**void**``** OpenSocket(**``**uint8_t**``** sock_num, **``**uint16_t**``** mode)**`

`**{**`

`** uint8_t**``** opcode=0;**`

`** opcode = (((sock_num<<2)|BSB_S0)<<3)|OM_FDM1;**`

`** w5500_writeReg(opcode, Sn_MR, mode);**`

`** w5500_writeReg(opcode, Sn_CR, 0x01);**`

`**}**`

`**//-----------------------------------------------**`

`**void**``** SocketInitWait(**``**uint8_t**``** sock_num)**`

`**{**`

`** uint8_t**``** opcode=0;**`

`** opcode = (((sock_num<<2)|BSB_S0)<<3)|OM_FDM1;**`

`** while**``**(1)**`

`** {**`

`** if**``**(w5500_readReg(opcode, Sn_SR)==SOCK_INIT)**`

`** {**`

`** break**``**;**`

`** }**`

`** }**`

`**}**`

`**//-----------------------------------------------**`

Add prototypes for these functions.

In the first function, we enter the type of operating mode in the socket mode register corresponding to the socket with the number that came in the incoming parameter, which will also come in the incoming parameter. Then we install a bit in the control register of the socket corresponding to the socket opening command. This sign will immediately tell us about all this and tell us

![image24](https://narodstream.ru/wp-content/uploads/2017/09/image24.png)

And in the second function, we interrogate the register of the state of the socket, and wait there for a value of 0x13 corresponding to the state of "INIT"

![image25](https://narodstream.ru/wp-content/uploads/2017/09/image25.png)

Call function data in initialization function

`tcpprop.cur_sock = 0;`

`**//Открываем сокет 0**`

`**OpenSocket(0,Mode_TCP);**`

`**SocketInitWait(0);**`

Now we will have to serve this socket, that is, monitor when some TCP packet from the client comes to us. To do this, we will also write two functions

`**//-----------------------------------------------**`

`**void**``** ListenSocket(**``**uint8_t**``** sock_num)**`

`**{**`

`** uint8_t**``** opcode=0;**`

`** opcode = (((sock_num<<2)|BSB_S0)<<3)|OM_FDM1;**`

`** w5500_writeReg(opcode, Sn_CR, 0x02); **``**//LISTEN SOCKET**`

`**}**`

`**//-----------------------------------------------**`

`**void**``** SocketListenWait(**``**uint8_t**``** sock_num)**`

`**{**`

`** uint8_t**``** opcode=0;**`

`** opcode = (((sock_num<<2)|BSB_S0)<<3)|OM_FDM1;**`

`** while**``**(1)**`

`** {**`

`** if**``**(w5500_readReg(opcode, Sn_SR)==SOCK_LISTEN)**`

`** {**`

`** break**``**;**`

`** }**`

`** }**`

`**}**`

`**//-----------------------------------------------**`

We also add prototypes in the title file for these functions.

Here we have a similar situation. In the first function, we transfer the command 0x02, which transfers the socket to the state "**Listen**"

![image26](https://narodstream.ru/wp-content/uploads/2017/09/image26.png)

And the second function waits for this state to be established by reading the status register byte

![image27](https://narodstream.ru/wp-content/uploads/2017/09/image27.png)

Call function data in initialization function

`SocketInitWait(0);`

`**//Начинаем слушать сокет**`

`**ListenSocket(0);**`

`**SocketListenWait(0);**`

Just in case, we’ll wait a bit and see the state of the ( chip, although this is not necessary ). I heard about cases that the programma still waited for the desired state in the function, and then this state was reset by itself. This is what we will control

`SocketListenWait(0);`

`** HAL_Delay(500);**`

`** //Посмотрим статусы**`

`** opcode = (BSB_S0<<3)|OM_FDM1;**`

`** dtt = w5500_readReg(opcode, Sn_SR);**`

`** sprintf(str1,**``**"First Status Sn0: 0x%02X\r\n"**``**,dtt);**`

`** HAL_UART_Transmit(&huart2,(uint8_t*)str1,strlen(str1),0x1000);**`

`}`

`//-----------------------------------------------`

We collect the code, send the controller and see the output in the terminal program

![image28](https://narodstream.ru/wp-content/uploads/2017/09/image28.png)

On this, initialization can be considered completed.

Now we will need to try to accept some package from the network.

Below the initialization function, create a package acceptance function

`**//-----------------------------------------------**`

`**void**``** w5500_packetReceive(**``**void**``**)**`

`**{**`

`** uint16_t**``** point;**`

`** uint16_t**``** len;**`

`**}**`

`**//-----------------------------------------------**`

We create a prototype for this function in the header file and call it in the corresponding function in the file **net.c**

`void``packet_receive(``void``)`

`{`

`**w5500_packetReceive();**`

`}`

In file** w5500.c** over the initialization function, add the function for determining the current state of the socket

`**//-----------------------------------------------**`

`**uint8_t**``** GetSocketStatus(**``**uint8_t**``** sock_num)**`

`**{**`

`** uint8_t**``** dt;**`

`** uint8_t**``** opcode=0;**`

`** opcode = (((sock_num<<2)|BSB_S0)<<3)|OM_FDM1;**`

`** dt = w5500_readReg(opcode, Sn_SR);**`

`** return**``** dt;**`

`**}**`

`**//-----------------------------------------------**`

To find out the state of the socket, we interrogate the register of the state of the socket, the number of which we pass in the incoming argument.

Now we create a condition for the state of the current socket in the function of receiving the package. It must be in the status of "United"

`uint16_t``len;`

`**if**``**(GetSocketStatus(tcpprop.cur_sock)==SOCK_ESTABLISHED)**`

`**{**`

`**}**`

B [**next part**](https://narodstream.ru/stm-urok-91-lan-w5500-http-server-chast-3/) lesson we explore the HTTP request that came from the client and begin to form an answer to it.

[Embedded media](https://www.youtube.com/embed/xO88OrJqK3s)

---

Source: https://maker.wiznet.io/teddy/projects/stm-lesson-91-lan-w5500-http-server-part-2/
