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

[Infineon] 12. Aurix (TC23x) GTM TOM을 이용한 PWM 출력

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

이제 모터를 돌려 볼 것이다.

모터를 돌리려면 어떻게 해야할까?

 

간단한 DC모터를 생각해 보자!

DC 모터에 입력으로 들어가는 전압에 따라 모터의 회전 속도는 달라진다.

예를들어 0~5V의 입력을 가지는 모터에

1V DC 전압을 인가했을때보다 2V를 넣을때가 더 빠르고

3V를 넣을때가 더 빠르다.

 

그렇다면 MCU는 어떻게 DC모터에 전압을 인가할수 있을까?

어떻게 아날로그 전압을 만들어 줄까?

 

MCU가 아날로그 전압을 만들어 주려면 별도의 Digital Analog IC를 이용하여 만들어주어야 한다.

어떠한 추가 장치가 필요하다는 의미이다.

 

MCU자체내에서는 0V와 5V 전압밖에 낼수가 없다.

그런데 이렇게 하면 0~5V전압을 만들어 줄수 있다.

 

예를 들어 아래와 같이 5ms동안은 5V를 주고, 그후 또 5ms동안은 0V를 주면

평균적으로는 2.5V를 주는 꼴이 된다.

따라서, 2.5V의 아날로그값이 DC모터에 입력으로 들어가는것과 대치되는 현상이 발생하게 된다.

아래 파형들을 PWM (Pulse Width Modulation)이라고 부른다.

위의 PWM은 주기가 10ms이고 Duty가 50%인 PWM이다.

그렇다면 이제부터 저 파형을 한번 만들어 보도록 하자!

인피니언 Aurix MCU는 GTM 이라는 모듈이 있다.

아래와 같이 타이머 모듈인데, 이 타이머 모듈안에 TOM이라는 더 작은 모듈이 들어 있고

이것을 이용하여 PWM을 발생 시킬수 있다.

 

GTM 모듈에는 100MHz의 Clock이 들어오도록 미리 설정을 해놓았다.

그리고 이 100MHz Clock을 이용하여 PWM을 만든다.

원리는 간단하다.

GTM은 TOM에서 사용하는 Clock을 Count해서 저 CN0라는 레지스터에 값을 넣어둔다.

그리고 CN0의 Count가 CM1에 도달하면 High에서 Low로 Voltage Level을 아래로 내린다.

그리고 CM0에 도달하면 다시 High로 올리고 CN0를 초기화 한다.

예를 들어

CM0 = 100, CM1 = 50 이라고 하면

이것은 Duty 50%의 PWM이 나가는 것이다.

 

그런데 저기 CM0, CM1은 아래와 같이 16비트의 크기를 가진다.

따라서 넣을수 있는 최대 Counter는 65536 이다.

CN0도 16비트다.

따라서, 오버플로우가 되지 않도록 잘 설계할 필요가 있다.

 

나는 주기가 10ms인 PWM을 만들어주려고 한다.

따라서, CM0가 1000000 를 넣어주면

1000000/ 100000000 = 1/100 = 0.01 (10ms) 가 된다.

 

그런데 CM0의 레지스터의 크기는 16비트이니까

1000000을 넣을수가 없다.

따라서 GTM TOM은 이것으 더 낮은 Clock으로 만들어 주고

이것을 이용해야 10ms의 주기를 가지는 PWM을 만들수 있다.

 

그래서 100MHz/ 256 의 크기의 Clock을 사용하도록 설정할것이다.

따라서 초기화 코드는 아래와 같다.

static void GtmTomTimer_initTimer(void) { { /*Create Gtm Timer Output Module (TOM) configuration for timer*/ IfxGtm_Tom_Timer_Config timerConfig; /*Init TOM timer configuration*/ IfxGtm_Tom_Timer_initConfig(&timerConfig, &MODULE_GTM); /*Setting timer configuration*/ timerConfig.base.frequency = 100; /*Set PWM period : 100Hz*/ timerConfig.base.isrPriority = ISR_PRIORITY(INTERRUPT_TIMER_10MS); timerConfig.base.isrProvider = ISR_PROVIDER(INTERRUPT_TIMER_10MS); timerConfig.base.minResolution = (1.0 / timerConfig.base.frequency) / 1000; timerConfig.base.trigger.enabled = FALSE; timerConfig.tom = IfxGtm_Tom_1; /*Set TOM1*/ timerConfig.timerChannel = IfxGtm_Tom_Ch_7; /*Set Channel 7*/ timerConfig.clock = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk2; /*100MHz/256*/ // Set output port, p33.10 timerConfig.triggerOut = &IfxGtm_TOM1_7_TOUT32_P33_10_OUT; timerConfig.base.trigger.outputEnabled = TRUE; timerConfig.base.trigger.enabled = TRUE; timerConfig.base.trigger.triggerPoint = 500000/256; /*5msec source: Fxclk2 100MHz/256*/ timerConfig.base.trigger.risingEdgeAtPeriod = TRUE; /*Rising edge에서 interrupt*/ /*Apply GTM Tom Reisgter*/ IfxGtm_Tom_Timer_init(&g_GtmTomTimer.drivers.timerOneMs, &timerConfig); /*Start timer*/ IfxGtm_Tom_Timer_run(&g_GtmTomTimer.drivers.timerOneMs); } }

 

위의 코드는 GTM TOM을 초기화 시키는 ILLD를 이용한 코드이다.

하나하나 레지스터를 분석해서 의미를 해석해야 한다.

그런데 시간이 너무 많이 걸리니 핵심적인 부분만 설명하려고 한다.

 

나는 Tom1 모듈의 채널7번을 사용하여 PWM을 만들것이고

PWM의 주파수를 100MHz로 설정하여 10ms의 Period를 가지도록 설계할 것이다.

그리고 100Mhz를 다 사용해서는 CM0,CM1, CN0의 레지스터가 넘치니까!

이것을 256으로 나누어 좀더 느려진 클락을 사용할것이다.

 

초기 Duty는 Trigger Point CM1에 들어갈 레지스터 값이라고 생각하면 된다.

다시 말해서 Duty를 표현하는 지점이 어디인가?

초기 50%로 설정하였다.

 

이제 PWM API를 살펴 보도록 하자!

void GtmTomMyPwmTest(void) { Ifx_TimerValue triggerPoint= (uint32_t)(fMyTestPwmDuty*PWM_FREQ); /*Disable Update*/ IfxGtm_Tom_Timer_disableUpdate(&g_GtmTomTimer.drivers.timerOneMs); /*Set PWM duty*/ IfxGtm_Tom_Timer_setTrigger(&g_GtmTomTimer.drivers.timerOneMs, triggerPoint); /*Apply Update*/ IfxGtm_Tom_Timer_applyUpdate(&g_GtmTomTimer.drivers.timerOneMs); } 

#define PWM_FREQ (1000000.0f/256.0f) /*100Hz*/

float32_t fMyTestPwmDuty = 0.5f;

fMyTestPwmDuty 변수는 Duty를 표현하는 값으로 0~1.0f의 값을 가진다.

 

MCU를 확인할때는 reference manaul을 잘 읽어야 한다.

GTM TOM PWM을 설정할경우는 반드시

Disable Update 이후 PWM 설정한후, Enable을 하도록 메뉴얼에서 나와 있다.

정상적으로 동작하기 위해서는 위의 방식대로 API가 설계 되어야 한다.

 

이제 준비가 다 되었다.

TOM1 7채널과 연결된 포트를 찍어 보도록 하자!

그런데, 우리는 PWM 어떻게 볼수 있을까?

 

오실로스코프라는 것으로 볼수 있는데 장비가 너무 비싸다

그래서 Logic Analyzer를 집에서 하나 구매하면 아주 값싸게 디버깅이 가능하다.

위의 장비는 추후 더 포스팅 하겠다.

아래와 같은 장비인데, P33.10을 연결하여 최종적으로 PC와 연결해 준다.

그러면, 아날로그 값이 저장비를 통해 분석들어와서 PC에서 보여준다.

PC에서 Logic Analyzer 프로그램을 깔고 동작시키면 실시간으로 파형이 저장되어 보여지게 된다.

 

그렇다면 한번 분석해 보도록 하자!

아래와 같은 파형을 얻게 되었다.

주파수 : 100Mhz에 Duty가 50%인 파형을 얻게 된것을 확인할수 있다.

이제 됐다. 우리는 Duty값을 얼마든지 조절하여 DC모터를 Control 할수 있게 되었다.

 

이제 정말 모터를 돌려 보도록 하자!

앗! 코드가 필요하신 분은 댓글 달아주세요.

처음에는 완성된 코드로 보시는것이 도움이 많이 되실 겁니다 ㅎㅎ

반응형

댓글