STM32103 MCU에서 UART DMA 사용하기

UART 송수신은 blocking 방식을 쓰거나 인터럽트를 이용한 nonblocking 방식을 사용할 수 있다. Blocking 방식은 UART 송수신이 완료될 때까지 다른 작업을 할 수 없는 반면에 nonblocking 방식을 사용하면 UART 송수신을 메인 루틴과 독립적으로 사용할 수 있기 때문에 리얼타임을 보장하는 데 도움이 된다. UART DMA는 기본적으로 nonblocking의 일종이면서 인터럽트 발생의 횟수를 줄여서 더 리얼타임성을 높일 수 있다.

본 포스팅에서는 STM32103 MCU에서 UART DMA를 사용하는 방법을 설명한다.

Hardware Configuration

이전 포스팅에서와 같이 하드웨어 환경은 WIZnet WIZ145SR을 사용한다.

UART DMA를 사용하기 위한 포트는 UART4 를 사용할 것이다.

STM32CubeIDE에서 “Pinout & Configuration”을 선택한 후, 다음과 같이 설정한다.

  • “Configuration”->”DMA Setting”에서 “Add” 버튼을 클릭해서 UART_TX를 선택한다.
  • “Mode” 는 “Normal”을 선택한다. “Normal” 모드는 DMA TX/RX를 한번만 수행한다. 사용자의 개입없이 무한 반복이 필요한 경우라면 “Circular”를 선택하면 된다. 여기서는 “Normal” 모드를 사용할 것이다.
  • “NVIC Settings”에서 “UART4 global interrupt”가 “Enabled” 되어 있는 지 확인한다.
    • “UART4 global interrupt”가 “Enabled”되어 있지 않으면 DMA operation은 다음 명령을 내려도 수행되지 않는다.

Coding

위와 같이 하드웨어 설정을 한 후에 “Generate Code”를 하면, main.c에 “MX_DMA_Init()”이 추가된 것을 확인할 수 있다.

다음은 while() 문 내에서 1초 단위로 HAL_UART_Transmit_DMA를 호출하도록 구성한다.

UART1은 DMA를 사용하지 않고 Data를 송신하고 UART4는 DMA를 사용해서 Data를 송신한다.

HAL_UART_Transmit_DMA()를 호출하는 것으로 DMA 송신을 위한 코딩은 끝났다.

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if(onesecondElapsed)
	  {
		  onesecondElapsed = 0;
		  count++;	// increment count

		  memset(msg, 0, 200);
		  sprintf((char *)msg, "UART1,[%d],%s\r\n", count, message);
		  HAL_UART_Transmit(&huart1, msg, strlen((const char*)msg), 20);

		  memset(dma_buf, 0, 200);
		  sprintf((char *)dma_buf, "UART4 DMA,[%d],%s\r\n", count, message);
		  HAL_UART_Transmit_DMA(&huart4, dma_buf, strlen((const char*)dma_buf));

	  }
	  loopback_tcps(0, ethBuf0, 5000);
  }

Build and Run

Build한 후에 STM32CubeProgrammer 로 생성된 바이너리를 다운로드 한다.

다음으로 STM32F103이 전송한 데이터를 수신하는 프로그램을 Putty를 실행한다.

여기까지의 전체 코드는 다음 링크에서 확인할 수 있다.

https://github.com/javakys/WIZ14xSR_Proj/releases/tag/Ver0.6

1 Comment

Leave a Comment