이번에는 UART 통신 예제를 간단하게 만들어보도록 하자. 

     

    필자는 기존 프로젝트를 지우면서 다시 작성하는 형태로 그대로 진행하고 있다. 따라서 프로젝트 이름은 항상 같다. 그래야 샘플하고 차이가 나기 때문이다. 생각난데로 해보고 안되면 소스를 참조하여 수정하고 여러가지 실험해보는 것이 실력을 올려주는 방법이기 때문에.. 이런저런걸 많이 해본다. 그러다 한계도 보이고 실제 프로젝트에 적용할 때 어떻게 할 것인지를 미리 예측해서 코딩을 할 수 있기 때문에 말이다. 

     

    --- contents ---

    1. [ESP32] VS Code 개발환경 구성 : https://makeutil.tistory.com/303

    2. [ESP32] 첫 프로젝트 생성하기 : https://makeutil.tistory.com/304

    3. [ESP32] 멀티 테스크 예제 (2 Task) : https://makeutil.tistory.com/305

    4. [ESP32] Task간 데이터 공유 (Queue, Mutex) : https://makeutil.tistory.com/306

    5. [ESP32] 개발보드 별 형상 및 I/O (ESP32/ESP32-S3) : https://makeutil.tistory.com/307

    6. [ESP32] UART 통신 예제 #1 : 현재 글 

     

    A1. [ESP32] 오류 - Fatal Error : No such file or directory : https://makeutil.tistory.com/308

    ------------------

     

    1.  UART를 이용하여 1초에 한번씩 문자열을 출력하는 예제

    1.1. 디버그 시리얼(UART0)이용

    1.1.1. 소스 

      시리얼 포트를 위해서 driver/uart.h를 추가했다. 아래 예제는 Hello World from UART!! 라는 문자열 앞에 카운터를 붙혀서 시리얼 포트에 기록하는 예제이다. 

    // ESP32-S3의 UART 0, 1, 2 테스트 코드
    
    #include <stdio.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "driver/uart.h"
    #include "string.h"
    
    const char *str_data = "Hello World";
    
    // USB 디버그 포트와 UART 0번 포트는 공유됨.
    //#define UART_PORT_NUM      UART_NUM_0
    
    // UART 1번 포트는 Pin 15(RX)-16(TX), 17(TX)-18(RX) : 보드별로 과열 발생될 수 있음
    //#define UART_PORT_NUM      UART_NUM_1 
    
    // UART 2번 포트는 Pin 19(RX)-20(TX)
    #define UART_PORT_NUM      UART_NUM_2   // UART 2번 포트
    
    #define BUF_SIZE           1024         // 버퍼 크기
    
    void app_main(void)
    {
        unsigned int count=0;
        char data[128];
    
        // UART 설정: 115200 baud rate, 8 data bits, no parity, 1 stop bit
        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
        };
    
        memset(data,0,sizeof(data));
    
        // UART 드라이버 초기화
        uart_driver_install(UART_PORT_NUM, BUF_SIZE, BUF_SIZE, 0, NULL, 0);
        uart_param_config(UART_PORT_NUM, &uart_config);
        //uart_set_pin(UART_PORT_NUM, 44, 43, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART0
        //uart_set_pin(UART_PORT_NUM, 18, 17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART1
        //uart_set_pin(UART_PORT_NUM, 15, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART1
       uart_set_pin(UART_PORT_NUM, 19, 20, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);    // RX, TX 핀 설정 : UART2
        
    
        while (1) 
        {
            if(count>10000)
                count = 0;
            count++;
    
            sprintf(data,"[%d] %s\n",count,str_data);
            int len = strlen(data);
            data[len-1] = 0x0d;
            data[len] = 0x0a;
    
            uart_write_bytes(UART_PORT_NUM, data, strlen(data));   
            vTaskDelay(1000 / portTICK_PERIOD_MS);   
        }
    }

     

    1.1.2. 결과

     

    1.1.3. 정리

      uart_config는 uart의 통신 속도와 설정을 위해서 사용한다. 독자께서 특별히 흐름제어를 하지 않는다면 비사용으로 설정하면된다. 다만 통신장비나 모뎀을 연결하는 경우라면, 해당 모뎀의 데이터 시트를 통해서 사용할지 말지 결정해야된다.

    양측간 데이터 통신이라면 일반적으로 패리티비트를 사용하진 않는다.  

     

      설정된 시리얼포트 정보는 uart_param_config()와 uart_driver_install() 함수를 통해서 FreeRTOS에 등록하여 사용할 수 있도록 한다. 

     

      sprintf()를 통해서 원하는 문자열을 생성한 다음 uart_write_bytes()를 이용해서 시리얼 포트로 만들어진 문자열 데이터를 전송한다. 

     

    [주의사항!!]

      필자가 버퍼의 크기를 64바이트로 줄였더니, 드라이버 오류가 발생된다. 그래서 128로 설정했더니 정상적으로 동작화는것을 확인하였다. 현재로서는 왜 그런지는 잘 모르겠지만 어쨋든, 제약사항이 있는것으로 보인다. 생성할 버퍼가 SRAM에서 제공받은 메모리보다 크면 문제겠지만, 일부러 작게 설정했는데 오류가 날 거라고는 생각하지 못했다. 이유는 뭐 필요할 때 찾아보도록 하겠다.

     

     

    1.2. 다른 포트(UART1) 이용하기

    1.2.1. 소스

    기존 소스에서 일부 만 변경하면된다. 앞서 개발보드의 형상에 대해서 언급했었다. 거기에 보면 하나 이상의 UART를 사용할 수 있다는 것을 알수 있겠다. 이전의 소스는 우리가 다운로드 하고 난 다음 디버그 포트를 이용해서 시리얼 출력을 확인할 수 있었다. 우리가 소스에서 printf()를 이용하면 나오는 것과 동일하게 말이다. 물론, ESP32의 printf는 설정된 디버그포트(시리얼, 표준입출력)으로 출력하는게 맞으니 뭐 시리얼 포트에 출력한것과 같지만, 개발하다보면 여러 시리얼 포트로 데이터를 주고 받고 한단 말이다. 그러므로 다른 포트를 UART로 설정해서 전송 정도는 미리 해봐야되지 않겠나...

      * 참조 : [ESP32] 개발보드 별 형상 및 I/O (ESP32/ESP32-S3) : https://makeutil.tistory.com/307

     

    기존 소스코드에서 uart_set_pin()을 호출하여 설정할 수 있다. 

        // UART 드라이버 설치 및 초기화
        uart_driver_install(UART_PORT_NUM, BUF_SIZE, BUF_SIZE, 0, NULL, 0);
        uart_param_config(UART_PORT_NUM, &uart_config);
        //uart_set_pin(UART_PORT_NUM, 44, 43, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART0
        //uart_set_pin(UART_PORT_NUM, 18, 17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART1
        //uart_set_pin(UART_PORT_NUM, 15, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));  // RX, TX 핀 설정 : UART1
        // GPIO19 (U0TXD)와 GPIO20 (U0RXD)를 UART2의 TX, RX 핀으로 설정
        uart_set_pin(UART_NUM, 20, 19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); 
    
        memset(buffer,0,sizeof(buffer));

     

      테스트를 위해서 아래와 같은 USB 2 Serial (TTL) 케이블이 필요하다. 이 장치를 PC에 꼽고, 위의 소스를 기준으로 ESP32-S3 개발보드의 19과 20번 핀에 핀 헤더를 연결하면된다. 

     

      독자들이 구매한 케이블과 필자의 케이블의 형상이나 핀 색상이 다를 수 있다. 하지만 대부분의 케이블은 붉은 색은 VCC(전원), 검정색은 (GND)이다. 그럼 남은 두 선이 RX와 TX가 된다. 필자의 경우 녹색이 RX고, 흰색이 TX였다. 

     

      USB케이블 이므로 이는 호스트 PC의 기준이다. 따라서 보드의 RX핀에는 USB 점퍼 TX가 연결되고 보드의 TX핀에는 USB의 RX핀이 연결되어야 시리얼로 통신이 가능하다. 

     

    정리하면 다음과 같다.

     

       (보드쪽 RX:pin 20) ------ USB 케이블의 흰색(TX)

       (보드쪽 TX:pin 19) ------ USB 케이블의 녹색(RX) 

     

     

     

    1.2.3. 결과

      연결이 완료되고 USB케이블을 호스트에 연결한 다음 테라텀등 시리얼 프로그램을 실행하여 생성된 포트를 열면 아래의 그램과 같이 문자열이 출력됨을 확인할 수 있다. 

     

     

    지금까지 시리얼포트를 이용하여 메시지를 출력하는 예제를 간단하게 작성해 보았다. 

     

    다음은 사용자가 입력한 정보를 출력하는 예제를 작성해보도록 하자. 

     

     

    반응형
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기