---
title: "W5500 TCP 소켓통신 오류 문제"
url: "https://maker.wiznet.io/forum/16076"
markdown_url: "https://maker.wiznet.io/forum/16076/md"
type: "Forum topic"
category: "Ethernet Chips"
author: "namdori"
created: "2026-05-08T11:55:19+09:00"
last_activity: "2026-05-12T17:56:40+09:00"
language: "ko"
views: 6
replies: 5
source: "WIZnet Makers forum (https://maker.wiznet.io/forum/)"
---

# W5500 TCP 소켓통신 오류 문제

## Question

Asked by namdori on 2026-05-08 in Ethernet Chips.

W5500 TCP 서버 모드로 사용중입니다.

소켓 0 (포트번호 61103)으로 OPEN 하여 통신 시 데이터 수신이 잘 이루어집니다.

같은 코드에 소켓만 1로 바꾸었을 뿐인데 데이터 수신이 엉뚱한 데이터가 들어옵니다.

이럴 경우 어느 부분을 디버깅 해야 하나요??

void xxx(uint8_t Sn){

control = (Sn &lt;&lt; 5) | 0x0C; // Socket buffer Write 0x1C

Write_5500(h_add, l_add, control, Data);

control = (Sn &lt;&lt; 5) | 0x08; // Socket buffer Read 0x18

temp = Read_5500(h_add, l_add, control);

}

이런 식으로 사용하고 있습니다.

## Replies

### Reply 1 by Grace_Koo, 2026-05-11

안녕하세요.

제공해주신 코드에서는 Socket n Register Block과 RX Buffer Block 접근이 혼동된 것으로 보입니다.

(Sn &lt;&lt; 5) | 0x08 은 Socket n Register Read입니다.
따라서 Socket 1에서는 0x28이 되며, 이는 Socket 1의 레지스터 영역을 읽는 값입니다.

실제 수신 데이터(payload)는 RX Buffer Block에서 읽어야 하므로, Socket 0은 0x18, Socket 1은 0x38 control byte를 사용해야 합니다.

즉 Sn_RX_RSR, Sn_RX_RD 같은 레지스터를 읽을 때는 0x28이 맞지만, 수신 payload를 읽을 때는 0x38이어야 합니다.

데이터 시트를 다시 참고 부탁드리며,

SPI 파형 또는 디버그 로그로 수신 데이터 read 구간의 control byte가 Socket 1에서 0x38로 나가는지 확인 부탁드립니다.

감사합니다.

### Reply 2 by namdori, 2026-05-11 (in reply to reply 1)

우선 답변 달아주신 점 감사드립니다.

맞습니다. 소켓 레지스터는 Read 시에 0x08, 0x28

버퍼는 0x18, 0x38 .. 로 컨트롤 값이 이루어집니다. 소스에 주석 부분에 그렇게 적었습니다.

문제는 같은 함수를 사용하고 Sn 값만 0, 1을 넣어주었을 뿐이라는 겁니다....

소켓 0에서는 제대로 된 값이 수신이 되는데 Sn 값만 1 ~ 7을 넣으면 엉뚱한 데이터가 수신된다는 점입니다.

소켓 버퍼는 8개 2kbyte 씩 설정해 주었습니다.

이상입니다. 감사합니다.

### Reply 3 by Grace_Koo, 2026-05-12 (in reply to reply 1)

추가 설명 감사합니다.

Control byte가 정상적으로 설정되어 있다면, 다음 확인 포인트는 Read_5500(h_add, l_add, control)에서 사용하는 h_add/l_add 값입니다.

W5500은 control byte의 BSB로 Socket n RX Buffer Block을 선택하므로, RX payload read 시 address phase에는 Socket별 base offset을 더하지 않고
해당 Socket의 Sn_RX_RD 값을 그대로 사용해야 합니다.

예를 들어 Socket 1에서 Sn_RX_RD가 0x0123이면, payload read SPI header는 아래와 같이 나가야 합니다.

```plaintext
address high = 0x01
address low  = 0x23
control      = 0x38
```

즉 주소 계산은 아래와 같은 형태가 되어야 합니다.

```plaintext
uint16_t rx_rd;
uint8_t h_add;
uint8_t l_add;
uint8_t control;

rx_rd = getSn_RX_RD(Sn);
h_add = (uint8_t)(rx_rd >> 8);
l_add = (uint8_t)(rx_rd & 0xFF);
control = (Sn << 5) | 0x18;   // Socket n RX Buffer Read

Read_5500(h_add, l_add, control);
```

그리고 수신 데이터를 읽은 후에는 읽은 길이만큼 Sn_RX_RD를 증가시켜 갱신하고, Sn_CR에 RECV command를 써주어야 합니다.

반대로 아래와 같이 2KB buffer 할당을 고려하여 Socket offset을 더하면 문제가 될 수 있습니다.

```plaintext
address = Sn_RX_RD + (Sn * 0x0800);  //error
```

Socket 0에서는 offset이 0이므로 정상처럼 보일 수 있지만, Socket 1부터는 잘못된 위치를 읽게 되어 엉뚱한 데이터가 수신될 수 있습니다.

따라서 Socket 1 수신 시 실제 SPI header의 address high/low 값이
Sn_RX_RD와 동일한지, 그리고 control byte가 0x38인지 확인 부탁드립니다.

감사합니다.

### Reply 4 by namdori, 2026-05-12 (in reply to reply 1)

답변 감사드립니다.

답변상으로 보면 아래와 같이 계산하면 안된다는 말씀이신가요??

get_offset = S1_RX_RD & S1_RX_MASK;

get_start_address = S1_RX_BASE + get_offset; &lt;-- 이 부분에서 S1_RX_BASE 값을 더해주지 말란 말씀이신거죠??

S1_RX_MASK = 0x07FF(2KB), S1_RX_BASE = 0x0800

예를 들어 S1_RX_RD 값이 0x44 일 경우 get_start_address = 0x844 부터 시작 아닌지요??

h_add = 0x08, l_add = 0x44 가 아니라는 말씀이신데....

UDP 모드로 사용할 때는 위 코드를 사용하여 데이터 수신하였습니다.

물론 그땐 데이터 수신이 정상 동작 하였습니다. 헷갈리네요..

S1_RX_BASE 값을 더해주지 않고 해보았으나 같은 동작입니다. ㅠㅠ

### Reply 5 by Grace_Koo, 2026-05-12 (in reply to reply 1)

제 설명이 혼동을 드린것같습니다.

공식 ioLibrary 내 함수를 참조 드리면 다음과 같습니다.

<https://github.com/Wiznet/ioLibrary_Driver/blob/f6406a7fd2e9e527f702320929dc751ecd5b707a/Ethernet/W5500/w5500.c#L240>

```plaintext
// ioLibrary_Driver/Ethernet/W5500 /w5500.h
#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block
```

```plaintext
// ioLibrary_Driver/Ethernet/W5500 /w5500.c
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint16_t ptr = 0;
uint32_t addrsel = 0;

if(len == 0) return;
ptr = getSn_RX_RD(sn);
//M20140501 : implict type casting -> explict type casting
//addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
//
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;

setSn_RX_RD(sn,ptr);
}
```

---

Source: https://maker.wiznet.io/forum/16076
