[Aurix TC275] ADC with Interrupt

사이킷·2025년 1월 18일

AURIX MCU

목록 보기
7/13

기존에는 App 단에서 IfxVadc_Adc_startScan(&g_VadcAutoScan.adcGroup); 하면 설정한 그룹내 채널들을 자동으로 돌면서 아날로그 값을 디지털 값으로 변환을 수행하고 값을 바로 가져오는 형식이었다.

이번장에서는 App단에서는
IfxVadc_Adc_startScan(&g_VadcAutoScan.adcGroup);
을 통해 ADC 작업 요청을 하지만 값을 가져오는건 Interrupt를 통해 가져오는 코드를 분석해 보겠다.

Group Configuration 변경점

adcGroupConfig.scanRequest.autoscanEnabled = FALSE;

autoscanEnabled를 TRUE에서 FALSE로 변경한다.

Channel Configuration 변경점

/* channel init */
    for (chnIx = 0; chnIx < 5; ++chnIx) {
        IfxVadc_Adc_initChannelConfig(&adcChannelConfig[chnIx], &g_VadcAutoScan.adcGroup);

        adcChannelConfig[chnIx].channelId = (IfxVadc_ChannelId)(chnIx);
        adcChannelConfig[chnIx].resultRegister = (IfxVadc_ChannelResult)(chnIx);
        adcChannelConfig[chnIx].resultSrcNr = IfxVadc_SrcNr_group1;

        /* initialize the channel*/
        IfxVadc_Adc_initChannel(&adcChannel[chnIx], &adcChannelConfig[chnIx]);

        /* add to scan */
        unsigned channels = ( 1 << adcChannelConfig[chnIx].channelId);
        unsigned mask = channels;
        IfxVadc_Adc_setScan(&g_VadcAutoScan.adcGroup,channels,mask);
    }

adcChannelConfig[chnIx].resultSrcNr = IfxVadc_SrcNr_group1; 가 추가되었다.

resultSrcNr 는

	IfxVadc_SrcNr                resultSrcNr;               /**< \brief Service node of the result trigger */

VADC 모듈의 Service Node 번호로 인터럽트 또는 서비스 요청을 처리하는 연결지점이다.

    IfxVadc_SrcNr_group0  = 0,  /**< \brief service request line 0 of group */
    IfxVadc_SrcNr_group1  = 1,  /**< \brief service request line 1 of group */
    IfxVadc_SrcNr_group2  = 2,  /**< \brief service request line 2 of group */
    IfxVadc_SrcNr_group3  = 3,  /**< \brief service request line 3 of group */

4개의 그룹이 있다.

resultSrcNr는 IfxVadc_Adc_initChannel() 함수에서 다음과 같이 사용된다.

IfxVadc_Status IfxVadc_Adc_initChannel(IfxVadc_Adc_Channel *channel, const IfxVadc_Adc_ChannelConfig *config)
{
...
    if (config->resultRegister < IfxVadc_ChannelResult_8)
    {
        IfxVadc_setResultNodeEventPointer0(vadcG, config->resultSrcNr, config->resultRegister);
    }
    else
    {
        IfxVadc_setResultNodeEventPointer1(vadcG, config->resultSrcNr, config->resultRegister);
    }
...
IFX_INLINE void IfxVadc_setResultNodeEventPointer0(Ifx_VADC_G *vadcG, IfxVadc_SrcNr resultSrcNr, IfxVadc_ChannelResult resultRegister)
{
    vadcG->REVNP0.U &= ~(IFX_VADC_G_REVNP0_REV0NP_MSK << (resultRegister * 4));
    vadcG->REVNP0.U |= (resultSrcNr << (resultRegister * 4));
}

REVNP0 레지스터를 수정하게 된다.

Group x의 Result Event Node Pointer Register 0 이다.
이 레지스터는 resultRegister 의 결과 이벤트 트리거를 Service Request Line으로 연결하는데 사용된다.

즉 내 설정으로 따르면 ADC 변환이 완료되면 1번 Service Node로 전달된다.

모든 채널을 초기화하면서
adcG->REVNP0.U |= (resultSrcNr << (resultRegister * 4));
이게 실행되니 모든 채널의 변환 완료를 1번 Service Node로 전달한다는 뜻이다.

디버거로 확인해보니 0번부터 4번까지 0x1 로 초기화 되었다.

Interrupt Setting

    IfxVadc_enableServiceRequest(g_VadcAutoScan.adcGroup.group, IfxVadc_ChannelResult_4);

    /* ADC SRC Setting*/
    SRC_VADCG0SR1.B.SRPN = 80u;
    SRC_VADCG0SR1.B.TOS = 0u;
    SRC_VADCG0SR1.B.SRE = 1u;

IfxVadc_enableServiceRequest(g_VadcAutoScan.adcGroup.group, IfxVadc_ChannelResult_4);
IfxVadc_ChannelResult_4, 즉 4번채널의 변환이 완료되면 인터럽트를 요청하라는 함수이다.
즉 0번부터 4번까지 순차적으로 변환하는데 마지막 4번이 변환이 완료되면 인터럽트가 걸린다.

IFX_INLINE void IfxVadc_enableServiceRequest(Ifx_VADC_G *vadcG, IfxVadc_ChannelResult resultRegister)
{
    vadcG->RCR[resultRegister].B.SRGEN = 1;
}


SRGEN 필드를 1로 바꾸면 result event 가 발생하면 인터럽트 서비스를 발생시킨다고 한다.

다음으로는 SRC_VADCGxRy 레지스터를 설정한다.
x는 그룹 넘버 y는 service request line(0-3) 이다.
위에서 IfxVadc_SrcNr_group1을 설정했기 때문에 y = 1이다.


SRPN : 인터럽트 우선순위
TOS : 어떤 CPU에게 인터럽트를 걸지
SRE : 인터럽트 활성화

Interrupt Handler

IFX_INTERRUPT(ADC_G0SR1IntHandler,0,80u);

void ADC_G0SR1IntHandler(void)
{
    uint32 chnIx;
    Ifx_VADC_RES conversionResult;

    IfxCpu_enableInterrupts();

    for(chnIx = 0; chnIx < 5u; ++chnIx)
    {
        conversionResult = IfxVadc_Adc_getResult(&adcChannel[chnIx]);
        adcDataResult[chnIx] = conversionResult.B.RESULT;
    }
}

RUN

static void AppTask10ms(void)
{
    
    stTestCnt.u32nuCnt10ms++;
    Unit_Mode();  

    /*ADC Test*/
    //Driver_Adc0_DataObtain();
    Driver_Adc0_ConvStart();
}

변환 요청만 하면 인터럽트에 의해서 값을 잘 불러온다

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

0개의 댓글