---
title: "W5300 을 이용한 네트워크 카메라 구현 1, 2, 3/3"
url: "https://maker.wiznet.io/eric_g/projects/w5300-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B9%B4%EB%A9%94%EB%9D%BC-%EA%B5%AC%ED%98%84-3-3/"
markdown_url: "https://maker.wiznet.io/eric_g/projects/w5300-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B9%B4%EB%A9%94%EB%9D%BC-%EA%B5%AC%ED%98%84-3-3/md"
type: "UCC: User Created Content"
author: "nexp"
author_url: "https://nexp.tistory.com/3047"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "nexp"
original_url: "https://nexp.tistory.com/3047"
license: "Apache License 2.0 (Apache-2.0)"
published: "2023-01-03"
language: "ko"
hardware: ["WIZnet W5300"]
likes: 2
views: 819
comments: 2
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# W5300 을 이용한 네트워크 카메라 구현 1, 2, 3/3

> STM32 Board와 W5300 Ethernet module 을 이용한 카메라 이미지 출력 및 영상처리

Original author: nexp (source: https://nexp.tistory.com/3047)

## Components

- **WIZnet W5300** x 1 ([docs](https://docs.wiznet.io/Product/Chip/Ethernet/W5300))

## Article

## **W5300 을 이용한 네트워크 카메라 구현 1/3 - 기본 개발환경 구성하기Original link is **[**https://nexp.tistory.com/3043**](https://nexp.tistory.com/3043)

### MCU 선정

W5300의 인터페이스는 Address/Data Bus 방식 이므로 데이터 버스를 제공하고 카메라 인터페이스가 있는 STM32F4 시리즈중 144핀 패키지의 STM32F417Zx를 선정

하드웨어 회로도

![](https://blog.kakaocdn.net/dn/CJgjD/btq4YOt6MLw/tEkFWPAJ3FDXXbrNM2GzO1/img.png)

STM32의 클럭 설정은 8Mhz의 외부 크리스털로 설정하고 클럭스피드를 최대 168Mhz로 설정해 준다.

![](https://blog.kakaocdn.net/dn/c525IK/btq4WKUc0pH/j7kMZZGZjTsmFkJGHRd1B0/img.png)

설정이 끝나고 저장하면 자동으로 기본 동작 코드가 생성

![](https://blog.kakaocdn.net/dn/cdJMZK/btq4YI1PPsG/g4suKxqhVmUEDvPFmZpNXk/img.png)

## W5300제어용 FSMC 설정

W5300은 STM32의 FSMC를 통해 제어 되므로 FSMC 설정이 필요

![](https://blog.kakaocdn.net/dn/q07n4/btq4VCvtCJO/R48KrRpFAHBRdUUFcYb1T1/img.png)

W5300의 CS 핀은 PG9->FSMC_NE2에 연결되어 있고 0x64000000 어드레스 에서 제어

**FMC 어드레스 할당 핀맵**

(BANK1)CS1 -> PD7 : ((uint32_t)0x60000000)

(BANK2)CS2 -> PG9 : ((uint32_t)0x64000000)

(BANK3)CS3 -> PG10 : ((uint32_t)0x68000000)

(BANK4)CS4 -> PG12 : ((uint32_t)0x6C000000)

## **W5300 을 이용한 네트워크 카메라 구현 2/3 - TCP 전송률 테스트Original link is **[**https://nexp.tistory.com/3044**](https://nexp.tistory.com/3044)

Wiznet ioLibrary Driver 포팅 및 TCP Loopback 전송률 테스트

W5300 테스트를 위한 [\[STM32F4-RP\]](https://nexp.tistory.com/tag/STM32-RP) 보드의 [기본 개발환경 설정](https://nexp.tistory.com/3043)이 완료 되었다면 다운로드 받은 [ioLibrary](https://github.com/Wiznet/ioLibrary_Driver)의 Ethernet 폴더에 W5300관련 코드를 프로젝트에 복사 하고 컴파일

![](https://blog.kakaocdn.net/dn/bEdyQQ/btq4XgSDMZM/vUKsZEKraqyK8q5OIjTXg1/img.png)

헤더파일의 디렉토리를 찾을수 없다는 에러가 발생

![](https://blog.kakaocdn.net/dn/daU1GV/btq4YtjslK9/RzuzCMRzyJNHrIPFosC260/img.png)

컴파일이 완료 되었다면 ioLibrary를 보드에 맞게 포팅해 주어야 하는데 W5300의 리셋함수, W5300 레지스터 읽기 함수(W5300_read), 쓰기 함수(W5300_write)를 등록

```cpp
#define W5300_BANK_ADDR                 ((uint32_t)0x64000000)
#define _W5300_DATA(p)                  (*(volatile unsigned short*) (W5300_BANK_ADDR + (p<<1)))


void Reset_W5300()
{
  HAL_GPIO_WritePin(RESET_W5300_GPIO_Port, RESET_W5300_Pin,  GPIO_PIN_RESET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(RESET_W5300_GPIO_Port, RESET_W5300_Pin, GPIO_PIN_SET);
  HAL_Delay(100);
}

void W5300_write(uint32_t addr, iodata_t wd)
{
  _W5300_DATA(addr) = wd;
}

iodata_t W5300_read(uint32_t addr)
{
  return _W5300_DATA(addr);
}
```

W5300 TCP Loopback 전송속도 테스트

W5300을 이용하여 TCP loopback 테스트를 하기 위해 loopback.c 파일을 사용하면 된다.

먼저 네트워크 환경을 wiz_NetInfo 구조체에 할당하고 초기화 코드를 작성해 준다.

```c
wiz_NetInfo gWIZNETINFO = {
.mac = {0x00, 0x08, 0xdc, 0, 0, 0},
.ip = {172, 30, 1, 104},
.sn = {255, 255, 0, 0},
.gw = {172, 30, 1, 254},
.dns = {0, 0, 0, 0},
.dhcp = NETINFO_STATIC
};

void Reset_W5300()
{
  HAL_GPIO_WritePin(RESET_W5300_GPIO_Port, RESET_W5300_Pin, GPIO_PIN_RESET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(RESET_W5300_GPIO_Port, RESET_W5300_Pin, GPIO_PIN_SET);
  HAL_Delay(100);
}


void _InitW5300(void)
{
  unsigned int tmpaddr[4];

  Reset_W5300();
  reg_wizchip_bus_cbfunc(W5300_read, W5300_write);

  printf("getMR() = %04X\r\n", getMR());

  if (ctlwizchip(CW_INIT_WIZCHIP, (void*)wiznet_memsize) == -1)
  {
  	printf("W5300 memory initialization failed\r\n");
  }

  ctlnetwork(CN_SET_NETINFO, (void *)&gWIZNETINFO);

  print_network_information();
}
```

최적화

네트워크 전송 속도를 높이려면 W5300에 데이터를 최대한 빨리 읽고 써야 하는데 w5300.c 파일에 있는 WIZCHIP_WRITE(), WIZCHIP_READ() 함수를 수정

아래 코드와 같이 수정하면 함수 포인터를 거치는 지연없이 바로 메모리에 접근 할 수 있다.

이부분을 DMA를 사용하면 좀더 성능을 개선할 수 있을것 같다.

WIZCHIP_WRITE() 함수

![](https://blog.kakaocdn.net/dn/VXqsY/btq4VMSiiuC/Pwsb0y7FFvf7ukXnXVkSsK/img.png)

WIZCHIP_READ() 함수

![](https://blog.kakaocdn.net/dn/b5nGtS/btq4XyFH1um/0yp0JKpq7dFLVSbFT4cwJK/img.png)

## 최적화 전

![](https://blog.kakaocdn.net/dn/ccejp7/btq4XbRvSVd/py2IdU7nMokoMwa33hqnE1/img.png)

최적화 후

![](https://blog.kakaocdn.net/dn/oHUQY/btq4YKeis0j/IGW5jtfpod0xNB0l5gErIK/img.png)

## **W5300 을 이용한 네트워크 카메라 구현 3/3 - 카메라 이미지 출력 및 영상처리Original link is **[**https://nexp.tistory.com/3047**](https://nexp.tistory.com/3047)

STM32의 카메라 인터페이스 DCMI를 이용하여 카메라 영상을 얻어 네트워크로 이미지 영상을 보내고 PC 호스트 프로그램에서 영상을 받아서 간단히 영상 처리 할수 있는 프로그램을 작성

### 카메라 연결

STM32에서 카메라는 DCMI 장치에서 설정 할 수 있다. STM32CubeIDE 를 이용하여 DCMI설정을 해 준다.



![](https://blog.kakaocdn.net/dn/cMs6Yb/btq4YjbC71o/96zCvdEPLufTRu6GV9ZFj1/img.png)

인터럽트를 사용할 수 있도록 설정하고 DMA 설정도 해 준다.![](https://blog.kakaocdn.net/dn/cH2SPq/btq4YJ2eOHu/wXPXVwoUqBqkbmIvNiVSJk/img.png)

![](https://blog.kakaocdn.net/dn/bwVxiQ/btq4YO2ZTLx/oXpJPqwolqbvr9bRKMRfm0/img.png)

### FIRMWARE

카메라 제어 관련 코드는 STMicro에서 제공하는 ov2640.c 파일(<https://github.com/STMicroelectronics/stm32-ov2640>) 을 이용하였다.

카메라 관련 함수는 _user_code_cam.h 에 작성되어 있다.

카메라에서 라인데이터가 들어올 때 HAL_DCMI_LineEventCallback() 함수와 한프레임이 완료 되었을때 HAL_DCMI_VsyncEventCallback() 함수를 재 정의 해서 main 함수에 알려 주도록 했다.

```cpp
void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
{
	gCameraLineFlag++;
}

void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
{
	gCameraFrameFlag++;
}


void CamImagTransferLine(unsigned int Cmd, unsigned int Para)
{

  	int ret ;

	unsigned char data_buf[2048*_UDP_TX_BUF_RATE];
	unsigned int size = _IMAGE_SIZE_X*2*_UDP_TX_BUF_RATE;

  	data_buf[0] = Cmd;
  	data_buf[1] = 0;
  	data_buf[2] = Para>>8;
  	data_buf[3] = Para;

  	memcpy((uint8_t *)&data_buf[4], (uint8_t *)&FrameBuffer, size);

	if(gImgTransferFlag)
	{
		ret = send(_CAM_SOCK_NUM, (uint8_t *)data_buf, size+4);
	}
}

void CamImagTransferFrame(unsigned int Cmd, unsigned int Para)
{
	int ret ;
	unsigned char data_buf[2048*_UDP_TX_BUF_RATE];
	unsigned int size = _IMAGE_SIZE_X*2*_UDP_TX_BUF_RATE;


  	data_buf[0] = Cmd;
  	data_buf[1] = 0;
  	data_buf[2] = Para>>8;
  	data_buf[3] = Para;


	if(gImgTransferFlag)
	{
		HAL_Delay(1);
		ret = send(_CAM_SOCK_NUM, data_buf, size+4);
		HAL_Delay(1);
	}
}
```

메인 루프에서 라인 인터럽트 신호가 인식되면 카메라 버퍼에 저장되어 있는 영상 데이터를 TCP 로 전송하고 프레임 인터럽트 신호가 인식되면 PC 호스트 프로그램에 프레임 완료 신호를 전송해서 화면을 갱신하도록 했다.

```cpp
  while (1)
  {
	/* USER CODE END WHILE */
	ProcessCamTcps(_CAM_SOCK_NUM, ethBuf0, dDestport);

	if(gCameraFrameFlag>0)
	{
		gCameraFrameFlag = 0;
		CamImagTransferFrame(_CMD_CAM_FRAME, gLineCnt);

		printf(">%d, %d\r\n", gFrameCnt, gLineCnt);
		gFrameCnt++;
		gLineCnt = 0;
	}


	if(gCameraLineFlag>0)
	{
		gCameraLineFlag = 0;

		CamImagTransferLine(_CMD_CAM_LINE, gLineCnt);
		gLineCnt++;
	}
	/* USER CODE BEGIN 3 */
  }
```

---

Source: https://maker.wiznet.io/eric_g/projects/w5300-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B9%B4%EB%A9%94%EB%9D%BC-%EA%B5%AC%ED%98%84-3-3/
