임베디드 보드/STM32

STM32 H743 1.LwIP_TCP_Echo_Client

ZEROWIN.TECH 2020. 7. 16. 14:48
728x90

에코서버란?

클라이언트가 전송해주는 데이터를 그대로 전송해 주시는 기능을 하는 서버입니다.

 

stm32 보드를 에코클라이어트로 설정합니다.

 

참조 사이트

https://www.waveshare.com/wiki/OpenH743I-C#Examples_24._ETH

 

OpenH743I-C - Waveshare Wiki

Instruction This developer Kit is the new member of Open series, its core board is based on STM32H743IIT6.Interfaces are expended for easy using. About the examples We provide demo code for you to follow.The demo codes use HAL libraries, generated by STM32

www.waveshare.com

데모소스코드

www.waveshare.com/wiki/File:OpenH743I-C_code.7z

 

File:OpenH743I-C code.7z - Waveshare Wiki

Click on a date/time to view the file as it appeared at that time. Date/TimeDimensionsUserComment current03:22, 8 October 2019 (26.4 MB)Eng10 (Talk | contribs)MsUpload 09:23, 13 July 2019 (17.21 MB)Waveshare-eng11 (Talk | contribs)MsUpload There are no pag

www.waveshare.com

기능구현

방향키와 CONTROL키, WAKE UP키를 누를 때 에코서버에 데이터를 전송하고 데이터를 재수신합니다.

OpenH743I-C 회로도 Joystick schematic

프로그래밍

JOYSTICK GPIO 설정

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOI_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();

  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);


  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /* EXTI interrupt init*/
  /*
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);
  HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI3_IRQn);
  HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);
  //HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  //HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

*/
}

JOYSTICK 버튼을 누르면 ECHO 데이터를 서버로 송신합니다.

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

  /* USER CODE END 1 */

  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();

  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();

  /* 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 */
  __HAL_RCC_D2SRAM3_CLK_ENABLE();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  printf("ETH LwIP TCP_Client DP83848 Test \r\n");
	
  /* USER CODE END 2 */

  uint32_t startTime = 0;
  uint32_t elapsedTime = 0;

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

    	/* USER CODE BEGIN 3 */
		MX_LWIP_Process();

		elapsedTime = HAL_GetTick();

		if(800 < (elapsedTime - startTime)) {
			keyKinds = KEY_UNDEFINED;
			keyKindsOld = KEY_UNDEFINED;
		}
		
		  if (HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_11) == 0)
		  {
			 keyKinds = KEY_ENTER;
		  }

		    if (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_2) == 0)
		  {
			 	keyKinds = KEY_UP;
		  }
		    if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == 0)
		  {
			 	keyKinds = KEY_RIGHT;
		  }
			
		    if (HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_4) == 0)
		  {
			 	keyKinds = KEY_LEFT;
		  }
		    if (HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_5) == 0)
		  {
			 	keyKinds = KEY_DOWN;
		  }

			if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1)
		  {
			 	keyKinds = KEY_WAKEUP;
		  }

			

		if(keyKinds == KEY_UNDEFINED || keyKinds != keyKindsOld)
		{
			
			  switch(keyKinds)
			  {
			  		// case KEY_UNDEFINED: printf("JOY_KEY_UNDEFINED # \r\n"); break;
					case KEY_ENTER: 	printf("JOY_KEY_ENTER # \r\n");  break;
					case KEY_LEFT: 		printf("JOY_KEY_LEFT # \r\n");  break;
					case KEY_RIGHT: 	printf("JOY_KEY_RIGHT # \r\n");  break;
					case KEY_UP: 		printf("JOY_KEY_UP # \r\n");  break;
					case KEY_DOWN: 		printf("JOY_KEY_DOWN # \r\n");  break;
					case KEY_WAKEUP: 	printf("JOY_KEY_WAKEUP # \r\n");  break;
			  }

				if(keyKinds != KEY_UNDEFINED)
				{
			  		tcp_echoclient_connect();

			  		keyKindsOld = keyKinds;
					
					startTime = elapsedTime;
				}
		}


  }
  /* USER CODE END 3 */
}

 

키정보를 포함하여 데이터를 서버로 송신합니다.

/**
  * @brief Function called when TCP connection established
  * @param tpcb: pointer on the connection contol block
  * @param err: when connection correctly established err should be ERR_OK 
  * @retval err_t: returned error 
  */
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
  struct echoclient *es = NULL;
  
  if (err == ERR_OK)   
  {
    /* allocate structure es to maintain tcp connection informations */
    es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));
  
    if (es != NULL)
    {
      es->state = ES_CONNECTED;
      es->pcb = tpcb;

	  switch(getKeyKinds())
	  {
	  		case KEY_UNDEFINED: sprintf((char*)data, "sending tcp client message KEY_UNDEFINED %d", (int)message_count); break;
			case KEY_ENTER: sprintf((char*)data, "sending tcp client message KEY_ENTER %d", (int)message_count); break;
			case KEY_LEFT: sprintf((char*)data, "sending tcp client message KEY_LEFT %d", (int)message_count); break;
			case KEY_RIGHT: sprintf((char*)data, "sending tcp client message KEY_RIGHT %d", (int)message_count); break;
			case KEY_UP: sprintf((char*)data, "sending tcp client message KEY_UP %d", (int)message_count); break;
			case KEY_DOWN: sprintf((char*)data, "sending tcp client message KEY_DOWN %d", (int)message_count); break;
			case KEY_WAKEUP: sprintf((char*)data, "sending tcp client message KEY_WAKEUP %d", (int)message_count); break;
	  }
          
        
      /* allocate pbuf */
      es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);
         
      if (es->p_tx)
      {       
        /* copy data to pbuf */
        pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
        
        /* pass newly allocated es structure as argument to tpcb */
        tcp_arg(tpcb, es);
  
        /* initialize LwIP tcp_recv callback function */ 
        tcp_recv(tpcb, tcp_echoclient_recv);
  
        /* initialize LwIP tcp_sent callback function */
        tcp_sent(tpcb, tcp_echoclient_sent);
  
        /* initialize LwIP tcp_poll callback function */
        tcp_poll(tpcb, tcp_echoclient_poll, 1);
    
        /* send data */
        tcp_echoclient_send(tpcb,es);
        
        return ERR_OK;
      }
    }
    else
    {
      /* close connection */
      tcp_echoclient_connection_close(tpcb, es);
      
      /* return memory allocation error */
      return ERR_MEM;  
    }
  }
  else
  {
    /* close connection */
    tcp_echoclient_connection_close(tpcb, es);
  }
  return err;
}

 

서버로부터 데이터를 수신합니다. 수신한 데이터를 디버그표시합니다.

static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{ 
  struct echoclient *es;
  err_t ret_err; 

  LWIP_ASSERT("arg != NULL",arg != NULL);
  
  es = (struct echoclient *)arg;
  
  /* if we receive an empty tcp frame from server => close connection */
  if (p == NULL)
  {
    /* remote host closed connection */
    es->state = ES_CLOSING;
    if(es->p_tx == NULL)
    {
       /* we're done sending, close connection */
       tcp_echoclient_connection_close(tpcb, es);
    }
    else
    {    
      /* send remaining data*/
      tcp_echoclient_send(tpcb, es);
    }
    ret_err = ERR_OK;
  }   
  /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
  else if(err != ERR_OK)
  {
    /* free received pbuf*/
    if (p != NULL)
    {
      pbuf_free(p);
    }
    ret_err = err;
  }
  else if(es->state == ES_CONNECTED)
  {
    /* increment message count */
    message_count++;
         
    /* Acknowledge data reception */
    tcp_recved(tpcb, p->tot_len);  

	{
	      /* allocate pbuf */
		  	char * temp = (char *)mem_malloc(p->tot_len + 1 );
				  memcpy(temp, (char *)p->payload, p->tot_len);
				  temp[p->tot_len] = 0x00;

			printf("p->tot_len= %d %s\r\n", p->tot_len, temp); // zwintest 

			mem_free(temp);
	}
    
    pbuf_free(p);
    tcp_echoclient_connection_close(tpcb, es);
    ret_err = ERR_OK;
  }

  /* data received when connection already closed */
  else
  {
    /* Acknowledge data reception */
    tcp_recved(tpcb, p->tot_len);
    
    /* free pbuf and do nothing */
    pbuf_free(p);
    ret_err = ERR_OK;
  }
  return ret_err;
}

테스트영상

조이스틱 버튼을 눌러 에코 클라이언트 보드에서 에코 서버로 데이터를 송신합니다.

 

소스코드 구매

주요내용은 윗글에 포함되어 있습니다.

부득이하게 설명이나 소스코드가 필요하면 구입부탁드립니다.

https://smartstore.naver.com/taklive/products/5018347050

 

STM32 H743 1.LwIP_TCP_Echo_Client 소스코드 : 제로윈마트

[제로윈마트] 제로윈텍 쇼핑몰

smartstore.naver.com