본문 바로가기
Embedded/STM32

[STM32] USART / UART를 통한 데이터 송수신

by Gordon_ 2025. 4. 6.

- 개발 환경

개발 보드 : NUCLEO-F103RB

개발 프로그램

- STM32 CubeMX : 6.12.0

- STM32 CubeIDE : 1.16.0


1. 서론

  USART(Universal Synchronous Asynchronous Receiver Transmitter)는 MCU으로 통신을 하려고 할때 가장 처음 배우는 통신 방법일 것입니다. 그 이유는 대부분의 개발보드에서 USART으로 PC와 통신할 수 있도록 하는 기능을 제공하고 있기 때문이며, 만약 없더라고 하더라도 USB to TTL을 사서 쉽게 해당 기능을 사용할 수 있기 때문입니다. 또한 그 외 다양한 장점이 있지만, 이번에는 STM32으로 USART를 사용해 PC와 통신하는 기능을 사용해보도록 하겠습니다.

 

2. 프로젝트 생성

  STM32 CubeIDE를 사용하셔도 상관없으며, 저의 경우는 VS code를 사용하여 개발할 것이므로 VS code로 개발하시고 싶은 분은 아래 포스트를 참고 하셔서 프로젝트를 생성해주시면 됩니다.

https://littlebitodd-developer.tistory.com/8

 

STM32위한 vscode 개발 환경 구축

STM32을 개발하기 위해서 STmicronics 회사에서 제공하는 "STM32 CubeIDE"를 사용하였습니다. 하지만, 기존 Visual studio code를 자주 사용하는 저에게 있어 Eclipse 기반의 STM32 CubeIDE는 사용하기 매우 불편하

littlebitodd-developer.tistory.com

 

2. IOC 파일을 수정하여 USART 기능 활성화

  Nucleo-F103RB는 기본적으로 USART2가 PC와 통신하기 위해 미리 활성화 되어 있습니다. 그러므로 따로 수정해야할 필요는 없습니다.

 

 

  주의1) 개발 하고 있는 Nucleo 보드마다 기본 설정되어 있는 USART가 다를 수 있습니다.

  주의2) 기본적으로 활성화된 USART는 PC와 통신하기 위한 부품들이 연결되어 있습니다.

              만약 꼭 해당 USART를 사용해야한다면, TX Pin과 RX Pin을 변경하여 사용해야합니다.

USART2를 사용하기위해 추가적인 부품이 연결되어 있음

 

 

 

이대로 저장하고 Generate Code를 통해 프로젝트에 적용합니다.

3. USART 관련 함수 소개

3.1. HAL_UART_Receive 함수

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

- 매개변수

  • UART_HandleTypeDef *huart
      사용하려는 USART의 구조체의 주소 전달
  • uint8_t *pData
      수신된 데이터를 저장하기 위한 배열 시작 주소 전달
  • uint16_t Size
      수신하려는 데이터의 수를 전송
  • uint32_t Timeout
      모든 데이터를 수신 받을 때까지 기다릴 시간(ms)

- 리턴 값

  • HAL_StatusTypeDef
    HAL_OK : 정상적으로 데이터 수신
    HAL_ERROR : 수신 도중 에러 발생
    HAL_BUSY : 이미 수신중인 데이터가 있는 경우
    HAL_TIMEOUT : 시간내 데이터를 모두 수신 하지 못한 경우

3.2. HAL_UART_Transmit 함수

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

- 매개변수

  • UART_HandleTypeDef *huart
      사용하려는 USART의 구조체의 주소 전달
  • const uint8_t *pData
      송신하기 위한 데이터을 저장한 배열 시작 주소 전달
  • uint16_t Size
      송신하려는 데이터의 수를 전송
  • uint32_t Timeout
      모든 데이터를 송신할 때까지 기다릴 시간(ms)

- 리턴 값

  • HAL_StatusTypeDef
    HAL_OK : 정상적으로 데이터 송신
    HAL_ERROR : 송신 도중 에러 발생
    HAL_BUSY : 이미 송신중인 데이터가 있는 경우
    HAL_TIMEOUT : 시간내 데이터를 모두 송신 하지 못한 경우

4. 실습 코드 작성

실습으로서 PC으로 부터 수신 받은 데이터를 다시 PC로 송신하는 에코(메아리) 기능을 구현해보도록 하겠습니다.

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  char Message[100] = "";
  int cnt = 0;

  while (1)
  {
    HAL_UART_Receive(&huart2, &Message[cnt], 1, HAL_MAX_DELAY); // Wait for a byte to be received
    ++cnt;

    if (Message[cnt - 1] == '\n') // Check for end of line character
    {
      Message[cnt] = '\0'; // Null-terminate the string
      HAL_UART_Transmit(&huart2, (uint8_t*)Message, cnt, HAL_MAX_DELAY); // Send the message to USART2
      cnt = 0; // Reset the counter for the next message
    }

    /* USER CODE END WHILE */

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

 

1 바이트씩 입력 받다가 '\n'가 송신 되면 지금까지 송신 받은 데이터를 한번에 PC에 출력하는 코드입니다.

물론, 송신된 데이터을 저장하는 배열의 크기가 100이니 100이상 넘어서는 안됩니다.

 

실행 결과

5. 후기

  STM32을 처음 접하는 사람들이 가장 힘들어 하는 부분이 USART일 것입니다. 몇몇 코드는 생각했던 것과 다르게 동작하며, 또 데이터가 생략될 수 있습니다. 특히, 가장 힘든 것이 데이터를 송수신 하기 위해 미리 데이터의 크기를 매개변수로 전달해야 한다는 것입니다. 

  이러한 문제점을 해결하기 위해 관련 포스트를 업로드 할 예정입니다.

 

6. 관련 포스트

https://littlebitodd-developer.tistory.com/9

 

[STM32] UART통신에서 printf() 함수 사용

1. printf()를 사용하고자 하는 이유1.1. 코드 길이 축소  UART 통신은 데이터를 송수신 할때 자주 사용하는 통신으로 디버깅이나 현재 로그를 출력하기 위해 자주 사용된다.기본적으로 STM32에서 UART

littlebitodd-developer.tistory.com

https://littlebitodd-developer.tistory.com/11

 

[STM32] C++에서 printf() 함수 사용

#ifdef __cplusplusextern "C" {#endifint __io_putchar(int ch){ // UART3에 ch에 있는 문자 1개를 1ms내 전송 if(HAL_UART_Transmit(&huart3, (uint8_t*)&ch, 1 ,1) != HAL_OK) return 0; //출력 실패 시 0 리턴 return ch; //출력 성공 시 출력

littlebitodd-developer.tistory.com

https://littlebitodd-developer.tistory.com/12

 

[STM32] 인터럽트를 이용한 echo UART 통신

1. STM32의 UART 통신의 문제점   STM32의 가장 큰 문제점은 아두이노에 비해 UART를 사용하기 매우 힘들기에 배우기 힘들어 한다고 생각한다. 내가 경험한 바로 크게 2가지 정도 UART를 사용하는데 힘

littlebitodd-developer.tistory.com