[Aurix TC275] UART

사이킷·2025년 1월 19일

AURIX MCU

목록 보기
9/13

Aurix TC275의 ASCLIN 모듈을 사용하여 UART를 통해 컴퓨터와 시리얼 통신을 구현해보겠다.

ASCLIN

ASCLIN (Asynchronous/Synchronous Interface for LIN) 모듈은 UART, LIN, SPI와 같은 직렬 통신을 지원하는 다목적 통신 모듈이다.

ADC와 마찬가지로 fspb와 같은 클럭을 사용하고 이는 100Mhz이다.

UART

UART는 직렬 통신 방식의 하나로, 데이터를 비동기(asynchronous) 방식으로 송신(TX) 및 수신(RX)하는 역할을 한다.

데이터 프레임의 구조는 다음과 같다.
**Start Bit -> Data Bits -> Parity Bit(Optional) -> Stop Bit

Start Bit : 송신이 시작되었음을 알리는 신호(1비트).항상 LOW(0)로 설정.

Data Bits : 실제 전송되는 데이터 비트. 최대 8비트

Parity Bit : 데이터의 오류를 확인하기 위한 검증 비트. 짝수 패리티(Even Parity) 또는 홀수 패리티(Odd Parity)로 설정 가능.

Stop Bit : 데이터 전송 종료 신호.

UART 초기화 코드

void Driver_Asc0_Init(void)
{
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);

    /* set the desired baudrate */
    ascConfig.baudrate.prescaler = 1;
    ascConfig.baudrate.baudrate = 115200;
    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,
            &IfxAsclin0_RXA_P14_1_IN, IfxPort_InputMode_pullUp,
            NULL_PTR,   IfxPort_OutputMode_pushPull,
            &IfxAsclin0_TX_P14_0_OUT, IfxPort_OutputMode_pushPull,
            IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;

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

    g_AsclinAsc.count = 1;
}

ASCLIN 모듈 초기 설정 불러오기

    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);

어느 모듈과 마찬가지로 초기 Configuration 값을 IfxAsclin_Asc_initModuleConfig() 함수를 통해 불러온다.

초기값은 다음과 같다.

void IfxAsclin_Asc_initModuleConfig(IfxAsclin_Asc_Config *config, Ifx_ASCLIN *asclin)
{
    config->asclin = asclin;

    /* loop back disabled */
    config->loopBack = FALSE;                                                  /* no loop back*/

    /* Default values for baudrate */
    config->clockSource           = IfxAsclin_ClockSource_kernelClock;         /* kernel clock, fclc*/
    config->baudrate.prescaler    = 1;                                         /* default prescaler*/
    config->baudrate.baudrate     = 115200;                                    /* default baudrate (the fractional dividier setup will be calculated in initModule*/
    config->baudrate.oversampling = IfxAsclin_OversamplingFactor_4;            /* default oversampling factor*/

    /* Default Values for Bit Timings */
    config->bitTiming.medianFilter        = IfxAsclin_SamplesPerBit_one;       /* one sample per bit*/
    config->bitTiming.samplePointPosition = IfxAsclin_SamplePointPosition_3;   /* sample point position at 3*/
    /* Default Values for Frame Control */
    config->frame.idleDelay               = IfxAsclin_IdleDelay_0;             /* no idle delay*/
    config->frame.stopBit                 = IfxAsclin_StopBit_1;               /* one stop bit*/
    config->frame.frameMode               = IfxAsclin_FrameMode_asc;           /* ASC mode*/
    config->frame.shiftDir                = IfxAsclin_ShiftDirection_lsbFirst; /* shift diection LSB first*/
    config->frame.parityBit               = FALSE;                             /* disable parity*/
    config->frame.parityType              = IfxAsclin_ParityType_even;         /* even parity (if parity enabled)*/
    config->frame.dataLength              = IfxAsclin_DataLength_8;            /* number of bits per transfer 8*/

    /* Default Values for Fifo Control */
    config->fifo.inWidth              = IfxAsclin_TxFifoInletWidth_1;          /* 8-bit wide write*/
    config->fifo.outWidth             = IfxAsclin_RxFifoOutletWidth_1;         /* 8-bit wide read*/
    config->fifo.txFifoInterruptLevel = IfxAsclin_TxFifoInterruptLevel_0;      /* txFifoInterruptLevel = 0. optimised to write upto 16 bytes at a time */
    config->fifo.rxFifoInterruptLevel = IfxAsclin_RxFifoInterruptLevel_1;
    config->fifo.buffMode             = IfxAsclin_ReceiveBufferMode_rxFifo;    /* RxFIFO*/

    /* Default Values for Interrupt Config */
    config->interrupt.rxPriority    = 0;                                       /* receive interrupt priority 0*/
    config->interrupt.txPriority    = 0;                                       /* transmit interrupt priority 0*/
    config->interrupt.erPriority    = 0;                                       /* error interrupt priority 0*/
    config->interrupt.typeOfService = IfxSrc_Tos_cpu0;                         /* type of service CPU0*/

    /* Enable error flags */
    config->errorFlags.ALL = ~0;                                               /* all error flags enabled*/

    /* init pointers */
    config->pins           = NULL_PTR;                                         /* pins to null pointer*/
    config->rxBuffer       = NULL_PTR;                                         /* Rx Fifo buffer*/
    config->txBuffer       = NULL_PTR;                                         /* Tx Fifo buffer*/

    config->txBufferSize   = 0;                                                /* Rx Fifo buffer size*/
    config->rxBufferSize   = 0;                                                /* Rx Fifo buffer size*/

    config->dataBufferMode = Ifx_DataBufferMode_normal;
}

Baudrate 설정

    ascConfig.baudrate.prescaler = 1;
    ascConfig.baudrate.baudrate = 115200;
    ascConfig.baudrate.oversampling = IfxAsclin_OversamplingFactor_4;

설정이라고 하지만 초기값이다.
prescaler 값은 보드레이트 계산 시 사용하는 클럭 소스의 분주비(Prescaler)를 설정한다. 이 값이 1이면 클럭 소스를 그대로 사용하며, 값이 증가하면 클럭이 느려진다.

baudrate 값은 UART 통신에서 사용하는 보드레이트(Baud Rate)를 설정한다.
보드레이트는 1초 동안 전송할 수 있는 신호의 수(비트 단위)를 나타낸다.
여기서는 115200bps(bit per second)로 설정되었으며, 이는 1초에 115200개의 비트를 송수신할 수 있음을 의미한다.

oversampling은 오버샘플링 비율(Oversampling Factor)을 설정한다.
오버샘플링은 데이터 전송 시 신호의 정확성을 높이기 위해 1비트를 여러 번 샘플링하는 방식이라고 한다. 여기서는 4배 오버샘플링이 설정되었다. 즉, 1비트를 전송할 때 샘플링을 4번 수행한다고한다. (GPT)

Interrupt 설정

    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();

tx rx er 의 인터럽트 우선순위를 설정한다.
마지막은 인터럽트를 어떤 코어에 넘길지 설정한다.

FIFO 설정

    /* 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;

tx rx 의 버퍼로 사용할 변수 및 크기를 할당한다.

Pin 할당

    /* pin configuration */
    const IfxAsclin_Asc_Pins pins = {
            NULL_PTR,   IfxPort_InputMode_pullUp, //cts
            &IfxAsclin0_RXA_P14_1_IN, IfxPort_InputMode_pullUp, //RX
            NULL_PTR,   IfxPort_OutputMode_pushPull, //rts
            &IfxAsclin0_TX_P14_0_OUT, IfxPort_OutputMode_pushPull, //TX
            IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;

TX 와 RX 로 사용할 핀을 설정해주고 각각 전압모드를 설정해준다.

어떤 핀을 사용해야 USB로 컴퓨터와 통신할 수 있을까..

User manual를 보면 다음과 같이 나와있다.
PC와 MCU간 USB연결을 통해 ASCLIN0 모듈을 통해 부트로더 기능을 수행할 수 있게 P14.0 과 P14.1 을 기본적으로 사용한다고 한다.
즉 14.0과 14.1이 USB와 연결된 핀인거 같다.

따라서 14.1을 RX 14.0을 TX핀으로 설정해 준것이다.

모듈 초기화

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

해준 설정을 토대로 초기화를 진행한다.

ISR

IFX_INTERRUPT(ASC_Tx0IntHandler, 0, ISR_PRIORITY_ASC_0_TX);
IFX_INTERRUPT(ASC_Rx0IntHandler, 0, ISR_PRIORITY_ASC_0_RX);
IFX_INTERRUPT(ASC_Err0IntHandler, 0, ISR_PRIORITY_ASC_0_EX);

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

void ASC_Rx0IntHandler(void)
{
    IfxAsclin_Asc_isrReceive(&g_AsclinAsc.drivers.asc0);
    IfxAsclin_Asc_read(&g_AsclinAsc.drivers.asc0, g_AsclinAsc.rxData, &g_AsclinAsc.count, TIME_INFINITE);

    g_AsclinAsc.txData[0] = g_AsclinAsc.rxData[0];
    IfxAsclin_Asc_write(&g_AsclinAsc.drivers.asc0, g_AsclinAsc.txData, &g_AsclinAsc.count, TIME_INFINITE);
}

void ASC_Err0IntHandler(void)
{
    IfxAsclin_Asc_isrError(&g_AsclinAsc.drivers.asc0);
}

데이터 송수신을 위한 인터럽트 핸들러 함수 및 인터럽트 선언을 해준다.

데이터 전송

void Driver_Asc0_TxTest(void)
{
    g_AsclinAsc.count = 1;

    g_AsclinAsc.txData[0] = 'a';

    IfxAsclin_Asc_write(&g_AsclinAsc.drivers.asc0, g_AsclinAsc.txData, &g_AsclinAsc.count, TIME_INFINITE);
}
static void AppTask10ms(void)
{
    
    stTestCnt.u32nuCnt10ms++;
    Unit_Mode();  
    Driver_Asc0_TxTest();

}

a 하나만 10ms 마다 전송시켜보았다.

profile
공부한거 정리, 잘못된 정보 태클은 언제나 환영입니다.

0개의 댓글