[Aurix TC275] PWM - 1

사이킷·2025년 1월 20일

AURIX MCU

목록 보기
11/13
post-thumbnail

PWM

PWM 은 통신용으로 개발된 기술이었으나 전류,전압 제어용으로 탁월한 방식이어기 때문에 현재는 통신보다는 DC쪽 전력제어나 모터 제어 쪽에 쓰이는 모듈이다.

해당 글에서는 Generic Timer Module (GTM) 의 in-build 된 Timer Output Module 을 사용하여 PWM 신호를 만들어보겠다.

GTM 초기화 코드

void Driver_Gtm_Init(void)
{
    /* disable interrupts */
    boolean  interruptState = IfxCpu_disableInterrupts();

    /** - GTM clocks */
    Ifx_GTM *gtm = &MODULE_GTM;
    g_GtmTomTimer.info.gtmFreq = IfxGtm_Cmu_getModuleFrequency(gtm);
    IfxGtm_enable(gtm);

    /* Set the global clock frequencies */
    IfxGtm_Cmu_setGclkFrequency(gtm, g_GtmTomTimer.info.gtmFreq);
    g_GtmTomTimer.info.gtmGclkFreq = IfxGtm_Cmu_getGclkFrequency(gtm);

    /** - Initialise the GTM part */
    Driver_Tom0_Init();

    /* enable interrupts again */
    IfxCpu_restoreInterrupts(interruptState);

    IfxGtm_Cmu_enableClocks(gtm, IFXGTM_CMU_CLKEN_FXCLK | IFXGTM_CMU_CLKEN_CLK0);
}

GTM clocks

    Ifx_GTM *gtm = &MODULE_GTM;
    g_GtmTomTimer.info.gtmFreq = IfxGtm_Cmu_getModuleFrequency(gtm);
    IfxGtm_enable(gtm);

GTM 모듈을 불러오고
GTM 의 클럭을 가지고 오고 있다.
Cmu 는 Clock management Unit 의 약자이다.

sys_clk로 클럭이 들어오고 있다.

GTM Module 로 fgtm 과 fspb가 들어가는것을 볼 수 있다.


IFX_INLINE float32 IfxScuCcu_getGtmFrequency(void)
{
    return IfxScuCcu_getSourceFrequency() / SCU_CCUCON1.B.GTMDIV;
}

IfxGtm_Cmu_getModuleFrequency를 타고 타고 들어가면 결국 fgtn 클럭을 사용하는것을 볼 수 있다. 100Mhz이다.

IfxGtm_enable(gtm);
void IfxGtm_enable(Ifx_GTM *gtm)
{
    uint16 psw = IfxScuWdt_getCpuWatchdogPassword();

    IfxScuWdt_clearCpuEndinit(psw);
    gtm->CLC.B.DISR = 0;
    IfxScuWdt_setCpuEndinit(psw);
}

gtm->CLC.B.DISR 레지스터를 0으로 바꾼다.

CLC는 Clock Control register의 약자로

GMT Module을 enable 시켜준다.

Set the global clock frequencies

    /* Set the global clock frequencies */
    IfxGtm_Cmu_setGclkFrequency(gtm, g_GtmTomTimer.info.gtmFreq);
    g_GtmTomTimer.info.gtmGclkFreq = IfxGtm_Cmu_getGclkFrequency(gtm);
void IfxGtm_Cmu_setGclkFrequency(Ifx_GTM *gtm, float32 frequency)
{
    float32 f;
    float32 bestDistance = frequency;

    float32 fIn          = IfxGtm_Cmu_getModuleFrequency(gtm);
    uint32  z, n, nBest = 1, zBest = 1;
    float32 t;

#if 1

    for (z = 1; z < 0xFFFFFF; z++)
    {
        boolean endLoop = FALSE;
        t = fIn / z;

        for (n = z; n > 0; n--)
        {
            float32 distance;
            f        = t * n;
            distance = fabsf(frequency - f);

            if (distance < bestDistance)
            {
                bestDistance = distance;
                nBest        = n;
                zBest        = z;
            }

            if (bestDistance < 0.1)
            {
                endLoop = TRUE;
                break;
            }
        }

        if (endLoop)
        {
            break;
        }
    }

    uint16 psw = IfxScuWdt_getCpuWatchdogPassword();
    IfxScuWdt_clearCpuEndinit(psw);
    gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest;
    gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest;   /* write twice to be sure */
    gtm->CMU.GCLK_DEN.B.GCLK_DEN = nBest;
    IfxScuWdt_setCpuEndinit(psw);
}
float32 IfxGtm_Cmu_getGclkFrequency(Ifx_GTM *gtm)
{
    float32 N          = gtm->CMU.GCLK_DEN.B.GCLK_DEN;
    float32 Z          = gtm->CMU.GCLK_NUM.B.GCLK_NUM;
    float32 multiplier = N / Z;

    return IfxGtm_Cmu_getModuleFrequency(gtm) * multiplier;
}

GTM 의 글로벌 클럭(GCLK) 을 설정하는 함수이다.
GLCK는 GTM 내부의 다양한 서브모듈 (TOM,ATOM 등) 이 사용할 클럭 소스로, 이를 설정하는 코드이다.

TOM 초기화 코드

static void Driver_Tom0_Init(void)
{
    {   /* GTM TOM configuration */
        IfxGtm_Tom_Timer_Config timerConfig;
        IfxGtm_Tom_Timer_initConfig(&timerConfig, &MODULE_GTM);
        timerConfig.base.frequency       = 100;
        timerConfig.base.isrPriority     = 0u;
        timerConfig.base.minResolution   = (1.0 / timerConfig.base.frequency) / 1000;
        timerConfig.base.trigger.enabled = FALSE;
        timerConfig.tom                  = IfxGtm_Tom_0;
        timerConfig.timerChannel         = IfxGtm_Tom_Ch_0;
        timerConfig.clock                = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk1;

        timerConfig.triggerOut                      = &IfxGtm_TOM0_0_TOUT76_P15_5_OUT;
        timerConfig.base.trigger.outputEnabled      = TRUE;   
        timerConfig.base.trigger.triggerPoint       = 0u;   /*Default 0 duty*/    
        timerConfig.base.trigger.risingEdgeAtPeriod = TRUE;

        IfxGtm_Tom_Timer_init(&g_GtmTomTimer.drivers.timerOneMs, &timerConfig);
        IfxGtm_Tom_Timer_run(&g_GtmTomTimer.drivers.timerOneMs);
    }
}

Congiration 불러오기

이 모듈도 마찬가지이다.

		IfxGtm_Tom_Timer_Config timerConfig;
        IfxGtm_Tom_Timer_initConfig(&timerConfig, &MODULE_GTM);

초기 설정값을 불러온다.

Configuation

        timerConfig.base.frequency       = 100;
        timerConfig.base.isrPriority     = 0u;
        timerConfig.base.minResolution   = (1.0 / timerConfig.base.frequency) / 1000;
        timerConfig.base.trigger.enabled = FALSE;
        timerConfig.tom                  = IfxGtm_Tom_0;
        timerConfig.timerChannel         = IfxGtm_Tom_Ch_0;
        timerConfig.clock                = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk1;

        timerConfig.triggerOut                      = &IfxGtm_TOM0_0_TOUT76_P15_5_OUT;
        timerConfig.base.trigger.outputEnabled      = TRUE;   
        timerConfig.base.trigger.triggerPoint       = 0u;   /*Default 0 duty*/    
        timerConfig.base.trigger.risingEdgeAtPeriod = TRUE;

timerConfig.base.frequency를 100으로 설정하였다. timerConfig.base.frequency는 타이머가 1초에 몇번 PWM을 발생시킬지 정하는 변수이다. 즉 100Hz로 주기가 10ms 마다 인터럽트를 발생시킨다.

isrPriority는 0으로 설정하였다. 인터럽트를 비활성화하고 Task에서 PWM을 10ms간격으로 생성하겠다.

minResolution은 타이머가 제어할 수 있는 최소 시간 단위를 설정하는 것이다. 10us 면 타이머는 10us의 간격으로 이벤트를 생성하거나 시간을 제어할 수 있다.

IfxGtm_Tom_Ch_ClkSrc_cmuFxclk1; 내부 클럭 소스를 선택한다.

cmuFxclk1의 값은 sys_clk값(100Mhz)를 Divider에 의해 16으로 나누어지게된 값이다.
즉 내부 클럭은 6,250,000 Hz 이다.

timerConfig.triggerOut       = &IfxGtm_TOM0_0_TOUT26_P33_4_OUT;

PWM 아웃풋 핀을 설정한다. P33_4를 아웃풋 핀으로 설정하였다.

PWM 생성 코드

void Driver_Gtm_Tom0Test(void)
{
    Ifx_TimerValue triggerPoint = 0u;
    static float32_t fDuty = 0.5f;
 
    triggerPoint = (uint32_t)(fDuty * (100000000.0f/16.0f/100.0f));
    IfxGtm_Tom_Timer_disableUpdate(&g_GtmTomTimer.drivers.timerOneMs);
    IfxGtm_Tom_Timer_setTrigger(&g_GtmTomTimer.drivers.timerOneMs, triggerPoint);
    IfxGtm_Tom_Timer_applyUpdate(&g_GtmTomTimer.drivers.timerOneMs);
}

PWM 신호의 Duty 및 trigger point를 설정한다.
fDuty가 0.5면 한 사이클에 50%가 HIGH 신호가 되는것을 의미한다. 100%일때 5v를 주게된다면 50%일때는 2.5v를 주게된다.

triggerPoint는 언제 HIGH -> LOW 전환을 하는지 의미한다.

triggerPoint = fDuty * (100000000.0f / 16.0f / 100.0f);

100000000은 타이머의 입력 주파수이다. 100Mhz
16.0은 IfxGtm_Tom_Ch_ClkSrc_cmuFxclk1를 설정하기위한 Divider의 값
100은 timerConfig.base.frequency값으로 타이머 주파수 설정값이다.

정리하자면 최종 입력주파수는 6,250,000hz인데
주기를 10ms로 설정했으니 (timerConfig.base.frequency = 100;) 10ms 동안의 틱수는 62,500이다. 그 중 우리는 50%를 HIGH로 설정했으니 주기가 시작되고 31,250 틱 이후에 LOW로 전환하겠다는 의미이다.

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

0개의 댓글