본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] UDP Client, lwIP Raw API

by eteo 2022. 10. 3.

 

 

2022.10.03 - [DSP, MCU/STM32 (ARM Cortex-M)] - STM32 ] TCP Client

 

STM32 ] TCP Client

CubeMX 설정 클라이언트가 서버에게 1초마다 한번씩 데이터를 전송하게끔 하기 위해 TIM1을 쓸 예정이다. TIM1은 APB2에서 클락소스를 공급받는다. 아래 헤더파일과 소스파일을 포함한다. main.c /* Priva

eteo.tistory.com

이전 글과 CubeMx 설정은 같다.

 

 

 

아래 헤더파일과 소스파일을 포함시킨다.

udpClientRAW.h
0.00MB
udpClientRAW.c
0.00MB

출처 : https://www.youtube.com/watch?v=Kc7OHc7JfRg&list=PLfIJKC1ud8ggZKVtytWAlOS63vifF5iJC&index=4

 

 

 

main.c

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "udpClientRAW.h"
/* USER CODE END Includes */

//...

/* USER CODE BEGIN PV */
extern struct netif gnetif;
/* USER CODE END PV */

//...

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_RTC_Init();
  MX_LWIP_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  udpClient_connect();
  HAL_TIM_Base_Start_IT(&htim1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  MX_LWIP_Process();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 

 

 

 

 

 

void udpClient_connect(void) 함수

/* IMPLEMENTATION FOR UDP CLIENT :   source:https://www.geeksforgeeks.org/udp-server-client-implementation-c/

1. Create UDP socket.
2. Send message to server.
3. Wait until response from server is received.
4. Process reply and go back to step 2, if necessary.
5. Close socket descriptor and exit.
*/


void udpClient_connect(void)
{
	err_t err;

	/* 1. Create a new UDP control block  */
	upcb = udp_new();

	/* Bind the block to module's IP and port */
	ip_addr_t myIPaddr;
	IP_ADDR4(&myIPaddr, 192, 168, 0, 111);
	udp_bind(upcb, &myIPaddr, 8);


	/* configure destination IP address and port */
	ip_addr_t DestIPaddr;
	IP_ADDR4(&DestIPaddr, 192, 168, 0, 102);
	err= udp_connect(upcb, &DestIPaddr, 7);

	if (err == ERR_OK)
	{
		/* 2. Send message to server */
		udpClient_send ();

		/* 3. Set a receive callback for the upcb */
		udp_recv(upcb, udp_receive_callback, NULL);
	}
}

1. 먼저 udp_new()로 UDP 컨트롤 블락을 만든다.

2. Local IP, Port와 생성된 udp 블락을 bind 한다.

3. udp_connect() 함수를 통해 서버의 Remote IP, Port 와 연결한다.

4. udpClient_send () 함수로 서버에 메시지를 보낸다.

5. 서버의 응답을 기다리기 위해 해당 upcb의 receive 콜백 함수를 지정한다.

 

 

 

 

static void udpClient_send(void) 함수

static void udpClient_send(void)
{
  struct pbuf *txBuf;
  char data[100];

  int len = sprintf(data, "sending UDP client message %d", counter);

  /* allocate pbuf from pool*/
  txBuf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);

  if (txBuf != NULL)
  {
    /* copy data to pbuf */
    pbuf_take(txBuf, data, len);

    /* send udp data */
    udp_send(upcb, txBuf);

    /* free pbuf */
    pbuf_free(txBuf);
  }
}

송신을 위한 패킷버퍼를 먼저 생성한다.

패킷 버퍼에 메모리를 할당하고, pbuf에 데이터를 카피한다. 그디로 udp_send() 함수를 통해 데이터를 송신하고 패킷 버퍼의 메모리를 해제한다.

 

 

 

 

void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) 함수

void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
	/* Copy the data from the pbuf */
	strncpy (buffer, (char *)p->payload, p->len);

	/*increment message count */
	counter++;

	/* Free receive pbuf */
	pbuf_free(p);
}

서버로부터 데이터를 수신 시 콜백된다. 서버로부터 수신된 pbuf를 전역변수 buffer에 카피한다. counter 변수를 ++하고 수신한 pbuf를 해제한다.

 

 

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 함수에서는 1초마다 udpClient_send();를 호출한다.

struct udp_pcb *upcb;
char buffer[100];
int counter = 0;

extern TIM_HandleTypeDef htim1;

//...

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	udpClient_send();