ESP32 IDF

ESP32 IDF UART

임베디드 친구 2024. 11. 13. 09:19
반응형

이번 포스팅에서는 ESP32의 UART 기능에 대해 설명하고, 다른 장치와 시리얼 통신을 구현하는 방법을 소개하겠습니다. UART는 ESP32와 외부 장치 간의 데이터를 주고받을 수 있는 기본적인 통신 방식 중 하나입니다. 예제를 통해 ESP32 IDF 개발 환경에서 UART 통신을 설정하고 테스트하는 방법을 알아보겠습니다.

UART란?

UART(Universal Asynchronous Receiver/Transmitter)는 데이터를 직렬로 송수신하는 통신 프로토콜입니다. UART를 사용하면 두 장치 간에 데이터를 직렬로 송신하고, 이 데이터는 수신 측에서 비동기적으로 수신합니다. ESP32는 최대 3개의 UART 포트를 지원하며, 각각의 UART는 송신 및 수신 핀을 통해 시리얼 통신을 수행할 수 있습니다.

UART는 일반적으로 다음과 같은 상황에서 사용됩니다:

  • 마이크로컨트롤러와 센서 또는 액추에이터 간의 통신
  • 두 개의 ESP32 간의 통신
  • ESP32와 PC 간의 디버깅 및 데이터 전송

ESP32의 UART 포트를 사용하여 데이터를 송수신하기 위해서는 핀 설정, 보드레이트(baud rate) 설정, 데이터 비트, 패리티 비트, 정지 비트 등을 설정해야 합니다.

VS Code 개발 환경 설정

이번 포스팅에서는 VS Code와 ESP32 IDF 개발 환경을 사용하여 예제를 진행합니다. VS Code 개발 환경이 이미 설정되어 있다고 가정하고, ESP32의 UART 통신을 설정하고 사용하는 방법을 자세히 설명드리겠습니다.

ESP32 UART 설정

ESP32에는 총 3개의 UART 인터페이스(UART0, UART1, UART2)가 있습니다. 기본적으로 UART0는 ESP32의 부트로더 및 디버깅 용도로 사용되며, UART1 및 UART2는 자유롭게 사용 가능합니다. UART를 설정하기 위해서는 esp_system.hdriver/uart.h 헤더 파일이 필요합니다.

UART 핀 매핑

먼저 UART를 사용할 핀을 설정해야 합니다. UART의 TX(송신)와 RX(수신) 핀을 사용하려는 핀 번호에 매핑해야 합니다. 일반적으로 UART 핀은 사용자 설정에 따라 자유롭게 매핑이 가능합니다.

#define UART_PORT_NUM      UART_NUM_1  // 사용할 UART 포트 번호
#define UART_TX_PIN        17          // TX 핀 번호
#define UART_RX_PIN        16          // RX 핀 번호
#define BUF_SIZE           1024        // 버퍼 크기

위 코드에서는 UART1을 사용하고 TX는 GPIO 17, RX는 GPIO 16에 매핑합니다. 버퍼 크기는 1024로 설정하였습니다.

UART 초기화 코드 작성

ESP-IDF에서 UART를 초기화하는 기본적인 코드는 다음과 같습니다.

#include "driver/uart.h"
#include "esp_log.h"

static const char *TAG = "UART_Example";

void init_uart() {
    // UART 설정 구조체
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };

    // UART 드라이버 설치 및 파라미터 설정
    uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_PORT_NUM, &uart_config);
    uart_set_pin(UART_PORT_NUM, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    ESP_LOGI(TAG, "UART initialized successfully");
}

위 코드에서 uart_config_t 구조체를 통해 UART 설정을 구성합니다. 보드레이트는 115200으로 설정하고, 데이터 비트, 패리티, 정지 비트를 설정합니다. 이후 uart_driver_install() 함수를 사용해 UART 드라이버를 설치하고, uart_param_config()uart_set_pin()을 통해 UART 파라미터와 핀을 설정합니다.

UART 데이터 송수신 예제

다음으로, UART를 사용하여 데이터를 송수신하는 간단한 예제를 작성해 보겠습니다. 이 예제에서는 UART1을 통해 데이터를 송신하고, 수신된 데이터를 그대로 다시 송신하는 에코 기능을 구현합니다.

void uart_echo_task() {
    uint8_t data[BUF_SIZE];
    while (1) {
        // UART로부터 데이터 수신
        int len = uart_read_bytes(UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS);
        if (len > 0) {
            // 수신된 데이터를 터미널에 출력
            uart_write_bytes(UART_PORT_NUM, (const char *) data, len);
        }
    }
}

위 코드에서는 uart_read_bytes() 함수를 사용하여 UART로부터 데이터를 읽어오고, 수신된 데이터를 uart_write_bytes() 함수를 사용해 다시 송신합니다. 이 예제는 UART 포트에 연결된 장치로부터 데이터를 읽고, 해당 데이터를 그대로 에코해주는 역할을 합니다.

전체 예제 코드

이제 UART 초기화 함수와 에코 태스크를 메인 함수에 통합한 전체 코드를 작성해 보겠습니다.

#include <stdio.h>
#include "driver/uart.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define UART_PORT_NUM      UART_NUM_1
#define UART_TX_PIN        17
#define UART_RX_PIN        16
#define BUF_SIZE           1024

static const char *TAG = "UART_Example";

void init_uart() {
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };

    uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_PORT_NUM, &uart_config);
    uart_set_pin(UART_PORT_NUM, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    ESP_LOGI(TAG, "UART initialized successfully");
}

void uart_echo_task() {
    uint8_t data[BUF_SIZE];
    while (1) {
        int len = uart_read_bytes(UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS);
        if (len > 0) {
            uart_write_bytes(UART_PORT_NUM, (const char *) data, len);
        }
    }
}

void app_main() {
    // UART 초기화
    init_uart();

    // UART 에코 태스크 생성
    xTaskCreate(uart_echo_task, "uart_echo_task", 2048, NULL, 10, NULL);
}

위의 전체 코드는 UART1을 초기화하고, 데이터를 송수신하는 에코 태스크를 생성하는 예제입니다. app_main() 함수에서 UART 초기화 함수 init_uart()를 호출하고, UART 에코 기능을 수행하는 태스크 uart_echo_task를 생성합니다.

UART 통신 테스트

ESP32 보드와 PC를 USB-시리얼 어댑터로 연결하여 UART 통신을 테스트할 수 있습니다. 예제 코드를 빌드하고 ESP32에 업로드한 후, 터미널 프로그램(예: PuTTY, Tera Term 등)을 사용하여 ESP32와 시리얼 통신을 테스트할 수 있습니다. 터미널 프로그램에서 데이터 입력 시, ESP32가 해당 데이터를 그대로 에코하는 것을 확인할 수 있습니다.

마무리

이번 포스팅에서는 ESP32의 UART 기능을 이용해 다른 장치와 시리얼 통신을 설정하고 데이터를 송수신하는 방법에 대해 설명했습니다. UART는 외부 장치와의 통신을 위한 강력한 도구이며, 특히 센서나 다른 마이크로컨트롤러와 데이터를 주고받을 때 유용합니다. VS Code와 ESP-IDF 개발 환경을 활용하여 직접 예제를 따라 해 보시길 권장드립니다.

반응형

'ESP32 IDF' 카테고리의 다른 글

ESP32 IDF 파일 시스템 - SPIFFS, FATFS  (0) 2024.11.15
ESP32 IDF Sleep  (0) 2024.11.14
ESP32 IDF SPI  (0) 2024.11.12
ESP32 IDF I2C  (0) 2024.11.11
ESP32 IDF DAC  (0) 2024.11.10