본문 바로가기
카테고리 없음

[Infineon] 12.1. Aurix (TC23x) GTM TOM 4Ch PWM 설계 (동기맞추기)

by 방구석 임베디드 2021. 6. 26.
반응형

지금 만드는 자동차는 아래와 같이 하나의 PWM으로 4개의 바퀴를 제어하는 구조이다.

하지만, 더 정확한 제어를 하기위해 나는 이 4개의 모터를 각가 Feedback Control 해줄 것이다.

그렇기 위해서는 4개의 PWM을 각각 모터드라이브에 연결을 해주어야 한다!

 

따라서 아래와 같이 4개의 포트 PWM으로 만들고 동기화를 시키도록 한다.

IfxGtm_TOM1_4_TOUT30_P33_8_OUT
IfxGtm_TOM1_5_TOUT28_P33_6_OUT
IfxGtm_TOM1_6_TOUT5_P02_5_OUT
IfxGtm_TOM1_7_TOUT6_P02_6_OUT

 

이렇게 4개의 후보군을 지정한 이유는 아래와 같이 물리적인 위치와

TOM의 채널을 한군데로 모아주어서 설계를 하였다.

TOM1 모듈의 4,5,6,7번이 연달아서 설정이 되어 있음을 확인할수 있다.

이러할 경우 TOM1 CH4의 Clock을 5,6,7번도 동일하게 이용할수 있어서, 같은 시점의 PWM 생성이 가능하다.

그렇다면 그림은 아래와 같이 된다.

이제부터 4개의 채널을 동기를 맞추어 PWM을 생성하도록 코드를 변경해 보도록 하자!

 

인피니언에서 제공하는 예제코드의 형식을 가지고 왔다.

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

    /*obtain GTM clock frequency*/
    Ifx_GTM *gtm = &MODULE_GTM;
    g_GtmTomTimer.info.gtmFreq = IfxGtm_Cmu_getModuleFrequency(gtm);

    /*Enable GTM*/
    IfxGtm_enable(gtm);
    
    /*setting the global clock to 100MHz*/
    IfxGtm_Cmu_setGclkFrequency(&MODULE_GTM, g_GtmTomTimer.info.gtmFreq);
    /*get Global clock frequency*/
    g_GtmTomTimer.info.gtmGclkFreq = IfxGtm_Cmu_getGclkFrequency(gtm);

    /*setting CMU0 frequency*/
    IfxGtm_Cmu_setClkFrequency(&MODULE_GTM, IfxGtm_Cmu_Clk_0, g_GtmTomTimer.info.gtmFreq);
    
    GtmTom1Init();

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

    /*enable Cmu clock*/
    IfxGtm_Cmu_enableClocks(gtm, IFXGTM_CMU_CLKEN_FXCLK | IFXGTM_CMU_CLKEN_CLK0);
}

위의 코드에서 중요한 점은 GTM 모듈 안에서 Clock을 세팅하는 부분을 나타내고 있다.

100MHz가 들어오게 되면 CMU_CLK0을 타고 들어와서 최종적으로 FXCLK로 CMU_CLK0가 선택된다.

TOM에서 사용하는 Clock은 FXCLK으로 결국 CMU_CLK0을 사용하는 것이다.

이것을 256으로 나누어 사용한다.

이유는 100Hz를 만들기 위해서는 CNT에서 많이 카운트해야한다.

그런데 CNT의 크기가 16비트밖에 안되기 때문에 Clock을 느리게 만들어야 한다.

 

static void GtmTom1Init(void)
{
    IfxGtm_PinMap_setTomTout(&IfxGtm_TOM1_4_TOUT30_P33_8_OUT, IfxPort_OutputMode_pushPull, IfxPort_PadDriver_cmosAutomotiveSpeed4); /*Rear Left*/
    IfxGtm_PinMap_setTomTout(&IfxGtm_TOM1_5_TOUT28_P33_6_OUT, IfxPort_OutputMode_pushPull, IfxPort_PadDriver_cmosAutomotiveSpeed4); /*Rear Right*/
    IfxGtm_PinMap_setTomTout(&IfxGtm_TOM1_6_TOUT5_P02_5_OUT, IfxPort_OutputMode_pushPull, IfxPort_PadDriver_cmosAutomotiveSpeed4);  /*Front Left*/
    IfxGtm_PinMap_setTomTout(&IfxGtm_TOM1_7_TOUT6_P02_6_OUT, IfxPort_OutputMode_pushPull, IfxPort_PadDriver_cmosAutomotiveSpeed4);  /*Front Right*/

    GTM_TOM1_CH4_CTRL.B.RST_CCU0 = 0u;
    GTM_TOM1_CH4_CTRL.B.TRIGOUT = 1u;
    GTM_TOM1_CH4_CTRL.B.SL = 1u;

    GTM_TOM1_CH5_CTRL.B.RST_CCU0 = 1u;
    GTM_TOM1_CH5_CTRL.B.TRIGOUT = 0u;
    GTM_TOM1_CH5_CTRL.B.SL = 1u;

    GTM_TOM1_CH6_CTRL.B.RST_CCU0 = 1u;
    GTM_TOM1_CH6_CTRL.B.TRIGOUT = 0u;
    GTM_TOM1_CH6_CTRL.B.SL = 1u;

    GTM_TOM1_CH7_CTRL.B.RST_CCU0 = 1u;
    GTM_TOM1_CH7_CTRL.B.TRIGOUT = 0u;
    GTM_TOM1_CH7_CTRL.B.SL = 1u;

    GTM_TOM1_TGC0_GLB_CTRL.U = 0xAA000000u; 
    GTM_TOM1_TGC0_ENDIS_CTRL.U = 0xAA00u;    
    GTM_TOM1_TGC0_OUTEN_CTRL.U = 0xAA00u;  

    GTM_TOM1_CH4_CTRL.B.CLK_SRC_SR = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk2;
    GTM_TOM1_CH5_CTRL.B.CLK_SRC_SR = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk2;    
    GTM_TOM1_CH6_CTRL.B.CLK_SRC_SR = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk2;
    GTM_TOM1_CH7_CTRL.B.CLK_SRC_SR = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk2;

    GTM_TOM1_TGC0_GLB_CTRL.B.HOST_TRIG = 1u;  
}

위의 코드는 TOM을 초기화 하는 코드로서,

4,5,6,7번 채널의 핀을 초기화하고, 4번 채널에 맞추어 5,6,7번의 동기를 맞추는 코드이다.

그리고 4,5,6,7번 GTM을 사용하고 Clcok을 설정하는 부분을 나타내고 있다.

각각의 레지스터가 어떠한 의미를 지니고 있는지는 추후 레지스터를 분석해 보도록 하자!

오늘은 큰그림만 그리려고 한다.

 

void DrvGtmPwmTest(float32_t param_Ch4Duty, float32_t param_Ch5Duty, float32_t param_Ch6Duty, float32_t param_Ch7Duty)
{
    float32_t fPeriodCnt = PWM_PERIOD_CNT;
    uint32_t ulPeriodCnt = (uint32_t)fPeriodCnt;
    
    GTM_TOM1_TGC0_GLB_CTRL.U = 0xAA000000u; 
    
    GTM_TOM1_CH4_SR0.B.SR0 = ulPeriodCnt;
    GTM_TOM1_CH4_SR1.B.SR1 = (uint32_t)(fPeriodCnt*param_Ch4Duty);

    GTM_TOM1_CH5_SR0.B.SR0 = ulPeriodCnt;
    GTM_TOM1_CH5_SR1.B.SR1 = (uint32_t)(fPeriodCnt*param_Ch5Duty);

    GTM_TOM1_CH6_SR0.B.SR0 = ulPeriodCnt;
    GTM_TOM1_CH6_SR1.B.SR1 = (uint32_t)(fPeriodCnt*param_Ch6Duty);

    GTM_TOM1_CH7_SR0.B.SR0 = ulPeriodCnt;
    GTM_TOM1_CH7_SR1.B.SR1 = (uint32_t)(fPeriodCnt*param_Ch7Duty);
    
    GTM_TOM1_TGC0_GLB_CTRL.U = 0xAA000000u;
}

 

위의 코드는 4,5,6,7번의 채널을 독립적으로 PWM을 주는 API이다. 

하지만 시작점은 모두 동일하도록 설정하였다.

 

 

아래 결과를 확인해 보도록 하자!

4개의 채널의 PWM이 모두 동일 선상에서 만들어지고 있는것을 볼수 있다.

오케이 각각의 PWM을 제어하지만, 동일선상으로 PWM의 시작점을 맞추었다.

이제 4개의 PWM이 각각 제어됨을 확인할수 있다.

이제 차량을 연결하여 확인해 보고,

엔코더부분을 구현해 보도록 하자!

 

반응형

댓글