본문 바로가기
Embedded SW/[Infineon] TC275 Lite Project

UART 통신 정리, UART 통신 MCU 설계 (인피니언 MCU)

by 방구석 임베디드 2021. 11. 27.
반응형

안녕하세요. 

오늘은 UART 통신에 대해서 정리하고, 

인피니언 MCU(TC275)를 이용하여 UART 통신을 수행해 보는 시간을 가지도록 하겠습니다.

 

참고로 이 글은 개발의 전체적인 내용을 연재하고 있는 글이 중에 하나입니다.

그래서, 앞에쓴 글을 보시면 더욱 도움이 되실것 같습니다.

아래 글을 링크 걸어둘께요. 필요하신 분은 한번 읽어 보세요.

(물론 이 글만 보셔도 크게 문제는 없습니다.)

 

1) 임베디드 SW, MCU에 대한 정리 (feat. 임베디드 SW 비전)

https://embeddedchallenge.tistory.com/210

2) MCU 개발 장비 구매 방법 정리 (인피니언 MCU TC275 Lite)

https://embeddedchallenge.tistory.com/211

3) 임베디드 SW 개발 환경 세팅 방법 정리 (소스코드 편집기, 컴파일러, 디버거 환경 설정 방법)

https://embeddedchallenge.tistory.com/212

4) 인피니언 IDE Tool 사용방법 정리 (프로젝트 생성 및 다운로드 수행)

https://embeddedchallenge.tistory.com/219

5) 인피니언 MCU LED Blinking (TC275 GPIO 설정)

https://embeddedchallenge.tistory.com/225

6) 인피니언 MCU Clock, 오실레이터 에 대한 이해 (TC275 보드에서 확인)

https://embeddedchallenge.tistory.com/226

7) 인피니언 MCU PLL 설정 및 주변기기 Clock 설정 (TC275)

https://embeddedchallenge.tistory.com/227

8) 인피니언 MCU 인터럽트/Interrupt 설정 (TC275 동작 확인)

https://embeddedchallenge.tistory.com/228

9) 스케줄링(scheduling)에 대한 정리, 인피니언 MCU Scheduler 설계 정리

https://embeddedchallenge.tistory.com/229

10) PWM이란 무엇인가? 인피니언 MCU를 이용한 PWM 설계 수행

https://embeddedchallenge.tistory.com/232

11) Motor Driver L298N 사용법 정리 (인피니언 MCU 개발)

https://embeddedchallenge.tistory.com/235

12) DC모터 드라이버 설계, RC카 전진,후진,회전 설계 (인피니언 MCU PWM, GPIO 설정)

https://embeddedchallenge.tistory.com/236

 

그렇다면 UART 통신을 알기전에 임베디드 SW에서 이야기하는 통신이란 무엇을 의미한는 것일까요?

우리는 다른 사람들과 어떻게 정보를 교환하나요?

우리는 말이라는 것을 통해 정보를 교환합니다.

말을 통해 공기의 진동을 일으켜 상대방에게 전달을 합니다.

우리의 생각과 감정을 다른사람에게 전달할수 있는 것이죠.

우리는 다른 사람들의 말을 듣고 공감하고, 결정을 내리는 요소로도 사용을 합니다.

그렇다면 제가 저 RC카에 탑재된, MCU에게 이야기를 하고 싶습니다.

MCU가 알아들을 수 있는 정보를 주고 싶습니다.

어떻게 해야지 MCU가 알아 들을 수 있을까요?

전압을 MCU에게 정보를 전달 할 수 있습니다.

 

무선통신이든, 유선통신이는 결국 기계가 알아 들을수 있는 것은 전압입니다.

5V으면 1, 0V면 0 이라고 MCU는 인식하게 되는 것이지요.

 

사실 Ditigal Input을 가지고도 정보를 전달할수 있습니다.

우리가 구매한 보드에서 아래 초록색 박스의 버튼을 누르면

MCU Port P00.7번 라인으로 전압이 다르게 들어갑니다.

회로도를 살펴보면 버튼을 누르면 Ground 전압인 0V가 포트로들어가게 됩니다.

버튼을 누르지 않으면 5V의 전압이 들어가게 됩니다.

결국 이 버튼을 누르고 안누르고를 통해서도 MCU는 제가 의도하는 바라 알아차리를 수 있습니다.

예를 들으면 버턴을 누르면 0이라는 값이 들어오게 되고,

0일때 어떠한 동작을 하라고 제가 코딩을 할수 있습니다.

가령, LED에 불을 키라고 이야기할수 있지요.

1일때는 약속된 어떠한 행위를 미리 코딩으로 넣어줄수 있습니다.

엄연히 저와 MCU간의 통신을 수행하는 것입니다.

Digital Input을 통해서요.

 

이것은 아기가, 아빠 이거

저거 하는 것과 같은 단순한 형태의 통신방법입니다.

 

그런데 우리는 말을 통해서 논리를 전달합니다.

그래서 인간들은 조금더 특별한 통신방법을 개발하였습니다.

 

바로, 전압을 변경하는 시간을 약속하는 것입니다.

빠르게 전압을 변경하는 방법을 개발한 것입니다.

그리고 그 전압이 변경되는 것에 약속을 부여한것입니다.

그것을 '프로토콜'이라고 부릅니다.

 

97이라는 값을 전달하고 싶습니다.

97을 이진수로 표현하면 아래와 같습니다.

0110 0001 

여기서 빨갱식으로 칠한 부분이 가장 낮은 비트이면 이 비트부터 전송을 한다고 가정해 보겠습니다.

그렇다면 전압은 아래와 같은 순으로 전달될 것입니다.

1 0 0 0 0 1 1 0 

1은 5V 저압을 의미하고, 0 은 0V전압을 의미합니다.

그리고 하나의 비트를 표현하는 시간(전압을 유지하는 시간)은 8.667us로 약속하였습니다.

아래 실제 전압이 변경되는 것을 캡처한 그림입니다.

10000110 이라는 정보가 전압라인을 타고 흘러가는 것이 보이지요?

저 전압라인은 97이라는 정보를 MCU에게 전달한 것이고

97을 아스키코드로 표현하면 'a' 라는 정보를 MCU에게 전달한 것입니다.

그런데 처음 1이라는 정보를 보내기전에 한번 아래로 내려가죠?

이것은 MCU에게 이제 정보를 보낼게라는 시작 약속입니다.

Data만 보낸것이 아니라, 시작을 알아들을 수 있도록 미리 정보를 준것이고

MCU는 알아들었습니다.

즉, 미리 짜고 친 약속입니다.

프로토콜입니다.

 

위의 프로토콜은 바로 UART 프로토콜을 설명한 것입니다.

 

이제 UART의 정의를 위키백과를 통해서 알아 보도록 해요!

UART(범용 비동기화 송수신기: Universal asynchronous receiver/transmitter)는 병렬 데이터의 형태를 직렬 방식으로 전환하여 데이터를 전송하는 컴퓨터 하드웨어의 일종이다. UART는 일반적으로 EIA RS-232, RS-422, RS-485와 같은 통신 표준과 함께 사용한다. UART의 U는 범용을 가리키는데 이는 자료 형태나 전송 속도를 직접 구성할 수 있고 실제 전기 신호 수준과 방식(이를테면 차분 신호)이 일반적으로 UART 바깥의 특정한 드라이버 회로를 통해 관리를 받는다는 뜻이다.
통신 데이터는 메모리 또는 레지스터에 들어 있어 이것을 차례대로 읽어 직렬화 하여 통신한다. 최대 8비트가 기본 단위이다.
UART는 일반적으로 컴퓨터나 주변 기기의 일종으로 병렬 데이터를 직렬화 하여 통신하는 개별 집적 회로이다. 비동기 통신이므로 동기 신호가 전달되지 않는다. 따라서 수신 쪽에서 동기신호를 찾아내어 데이터의 시작과 끝을 시간적으로 알아 처리할 수 있도록 약속되어 있다. 디지털 회로는 자체의 클럭 신호를 추가로 사용하여 정해진 속도로 수신 데이터로 부터 비트 구간을 구분하고 그 비트의 논리 상태를 결정하여 데이터 통신을 하는 USRT(범용 동기화 송수신기: Universal synchronous receiver/transmitter)도 사용한다.
UART는 보통 마이크로컨트롤러에도 포함되어 있다. 듀얼 UART, 곧 DUART는 두 개의 UART를 하나의 칩에 합친 것이다. 수많은 현대의 집적 회로(IC)는 동기화 통신인 USRT도 함께 지원한다. 이러한 장치들은 'USARTs'(범용 동기화/비동기화 송수신기: universal synchronous/asynchronous receiver/transmitter) 또는 'USART/UART'로도 부른다.

내용이 복잡해보입니다.

하지만 핵심만 잡으시면 됩니다.

 

직렬형태의 통신방식이다.

최대 8비트가 기본 단위이다.

 

다시 위의 예제를 정리해 보도록 하겠습니다.

a(97) 이라는 정보를 보내려고 합니다.

1) 시작비트 : 먼저 아래로 0으로 내려가면서 시작을 알려야 합니다.

2) 데이터 비트 : 5~8비트의 데이터 전송을 합니다. 몇 비트를 사용할 것인지는 해당 레지스터 설정에 따라 결정됩니다.

보통은 8비트를 사용합니다.

3) 패리티 비트 : 오류 검증을 하기 위한 패리티 값을 생성하여 송신하고 수신쪽에 오류 판단합니다.

패리티 비트는 사용자가 원하지 않으면 설정을 하지 않을 수 있습니다.

4) 끝 비트 : 통신 종료를 알립니다.

아까 위에서 전달할때 프레임을 보면

시작비트가 보이지요? 그리고 바로 데이터비트 8개가 보입니다.

패리티 비트는 설정하지 않아서 없습니다.

그리고 끝 비트가 보입니다. 다시 위로 올라갔습니다.

 

아래와 같이 MCU안에는 UART 통신 모듈이 들어가 있습니다.

그리고 Tx라인을 통해서 위와 같은 0~3.3V 또는 0~5V 전압레벨로 정보를 전달하고, Rx 라인을 통해 동일한 전압레벨로 정보를 전달 받습니다.

하지만 위의 전압레벨은 장거리 전송에 있어서 노이즈에 취약합니다.

따라서 -12V~12V의 전압레벨을 가지는 RS232 통신방식으로 전압레벨을 변경하여 전달합니다.

아까 위키에서 아래 내용이 있었지요?

'UART는 일반적으로 EIA RS-232RS-422RS-485와 같은 통신 표준과 함께 사용한다.'

이유는 장거리통신을 위해서 전압레벨을 바꾸어 사용하기 위함입니다.

아래는 TTL에서 RS232로 변환하는 모듈은 쉽게 소자를 구매할수 있습니다.

 

 

이제부터 제가 하려는 설계 내용을 정리 하도록 하겠습니다.
저는 컴퓨터를 통해서 MCU에게 정보를 전달할 것입니다.
방금 a라는 정보를 노트북을 통해서 전달할 것입니다.
그리고 MCU가 전달하는 정보를 노트북의 프로그램을 이용하여 띄울것입니다.
노트북과 MCU 사이에 통신을 수행할 것입니다.
 
그렇기 하기 위해서는 USB to TTL이 필요합니다.
USB to TTL은
3.3V 및 5V TTL 신호를 USB 프로토콜로 변환하여 주는 제품입니다.
다시말해서 UART 통신에서 사용하는 전압레벨을 USB전압레벨로 변경하고
노트북에서 이를 인지할수 있도록 변환해 주는 모듈입니다.

그리고 저는 노트북의 Tera Term이라는 프로그램을 이용하여 UART 통신을 수행할 것입니다.

Tera Term을 다운받고 싶으시면 인터넷에서 직접 입력을 하시고 다운받으시면 됩니다.

무료입니다.

 

그렇다면 이제 MCU안에 UART기능을 우리가 원하는데로 설정하기 위해서

Device Driver를 설계해야합니다.

그렇다면 인피니언을 통해서 어떻게 UART 기능을 설계해야 하는 것일까?

 

Infineon Aurix MCU에는 ASCLIN 모듈이 있고, 이 모듈에서 UART를 지원해 줍니다.

이 모듈의 Block Diagram을 나타내고 있습니다.

우리는 Clock설정에서 fspb Clock을 100MHz로 설정 하였습니다.

 

그리고 fclc clock을 사용할것이다.

uart 통신에 있어서, 확인해야할 설정 값은 무엇일까?

우선 인피니언에서 제공하는 초기화 코드를 살펴 보도록 하겠습니다.

static void DrvAsc0Init(void)
{
    /* create module config */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);

    /* set the desired baudrate */
    ascConfig.baudrate.prescaler    = 1;
    ascConfig.baudrate.baudrate     = 9600; /* FDR values will be calculated in initModule */
    ascConfig.baudrate.oversampling = IfxAsclin_OversamplingFactor_4;

    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority    = ISR_PRIORITY_ASC_0_TX;
    ascConfig.interrupt.rxPriority    = ISR_PRIORITY_ASC_0_RX;
    ascConfig.interrupt.erPriority    = ISR_PRIORITY_ASC_0_EX;
    ascConfig.interrupt.typeOfService = (IfxSrc_Tos)IfxCpu_getCoreIndex();

    /* FIFO configuration */
    ascConfig.txBuffer     = g_AsclinAsc.ascBuffer.tx;
    ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;

    ascConfig.rxBuffer     = g_AsclinAsc.ascBuffer.rx;
    ascConfig.rxBufferSize = ASC_RX_BUFFER_SIZE;

    /* pin configuration */    
    const IfxAsclin_Asc_Pins pins = {
        NULL_PTR,                     IfxPort_InputMode_pullUp,        // CTS pin not used
        &IfxAsclin0_RXB_P15_3_IN, IfxPort_InputMode_pullUp,        // Rx pin
        NULL_PTR,                     IfxPort_OutputMode_pushPull,     //RTS pin not used
        &IfxAsclin0_TX_P15_2_OUT, IfxPort_OutputMode_pushPull,     // Tx pin
        IfxPort_PadDriver_cmosAutomotiveSpeed1
    };        
    ascConfig.pins = &pins;

    /* initialize module */
    IfxAsclin_Asc_initModule(&g_AsclinAsc.drivers.asc0, &ascConfig);

    g_AsclinAsc.count = 1;    
}

위의 코드를 보면 ascConfig 구조체에 설정값을 넣고

IfxAsclin_Asc_initModule 함수를 통하여 UART의 레지스터값을 입력하여 넣고 있는 것을 볼수 있습니다.

 

UART에서 가장 중요한 부분은 baudrate을 설정하는 부분입니다.

위의 코드는 9600bps 설정하고 있습니다. 이것은 1초에 9600개의 비트를 전송한다는 의미입니다.

 

UART통신 규격을 살펴보면 아래와 같은 통신 속도를 설정할수 있는것을 확인할수 있습니다.

결국 저 ILLD를 통해서 레지스터 Setting이 이루어 지고 있는 것입니다.

그렇다면 한번 살펴 보도록 하자!

이렇게 나타나고 있는것을 확인할수 있습니다.

그렇다면 계산을 해보도록 하자!

PRESACLER = 0

NUMERATOR = 1

DENOMINATOR = 0xA2C = 2604

OVERSAMPLING = 4

 

BaudRate = (100Mhz * 1) / (1*2604*4)

= 9600

이 나오는 것을 볼수 있습니다.

인피니언은 저렇게 ILLD를 제공하여 파라미터값만 넣어서 손쉽게 레지스터값을 변경할수 있습니다.

또 중요한 Spec 가운데 아래 정보를 살펴볼 필요가 있습니다.

이것의 의미는 무엇일까?

예를들어 5바이트 정보를 보내면  FIFO 버퍼에 5개를 넣어서 한번에 보낼수 있습니다.

16바이트 정보까지도 16개를 한번에 보낼수 있는 Hardware를 가지고 있습니다.

하지만 16개를 보낸다면

16개를보내고, 

그대음에 나머지 1개를 보냅니다.

 

하지만 ILLD Code를 분석하면

최초 1개를 먼저 보내고 그다음부터 16개씩 정보를 보내는 것을 알수 있습니다.

void DrvAsc_Test1(void)
{
    int i;
    
    g_AsclinAsc.count = 17;

    for(i=0;i<17;i++)
    {
        g_AsclinAsc.txData[i] = i;
    }
    
    /* Transmit data */
    IfxAsclin_Asc_write(&g_AsclinAsc.drivers.asc0, g_AsclinAsc.txData, &g_AsclinAsc.count, TIME_INFINITE);
}

1개를 보내고 아래와 같은 ISR이 뜨고,

나머지 16개를 보내는 구조라는 것을 알 수 있습니다.

void ASCTxInt0Handler(void)
{
    IfxAsclin_Asc_isrTransmit(&g_AsclinAsc.drivers.asc0);
}

 

구현하는 방식은 DMA, 인터럽트, 폴링 여러가지가 있지만

16개의 FIFO 버퍼를 가지고 있다는 의미는 이렇게 해석할수 있습니다.

 

그렇다면 한번 움직임을 살펴 보도록 하겠습니다.

17게의 데이터까 쭉 나오고 있는 것을 확인 할 수 있습니다.

다음 포스팅에서는 조금더 설계를 세밀하게 해보고

Tera Term을 통해서 노트북과 MCU간의 정보전달을 수행해 보도록 하겠습니다.

 

오늘 UART 통신 정리, UART 통신 MCU 설계 포스팅은 이것으로 마치도록 하겠습니다.

감사합니다.

반응형

댓글