KL03 PWM bare copper code not working

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

KL03 PWM bare copper code not working

ソリューションへジャンプ
1,442件の閲覧回数
stevengarfinkel
Contributor III

I am adding a pwm function to my code and it compiles but no PWM comes out of the pin.  I previously used the pin for GPIO so I know the hardware is functional.

Here is the code for initialization, which in this version leaves the outputs on at 50% dutycycle:

void PWM_init ()

{

  //Select time clock source

  //Select 48 MHz clock

  SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1);

  //Enable the Clock to the timer Modules

  SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK;

  SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK;

  //Set pins to timer outputs

//PHA_LO = 7, PHB_LO = 10, PHC_LO = 11

  PORTB->PCR[B_PHALO] = PORT_PCR_MUX(2);

  PORTB->PCR[B_PHBLO] = PORT_PCR_MUX(2);

  PORTB->PCR[B_PHCLO] = PORT_PCR_MUX(2);

  //Enable clock, divide by 1

  TPM0_SC = 4;

  TPM1_SC = 4;

  //pwm frequency to 48MHz/20kHz = 2400;

  TPM0_MOD = 2400;

  TPM0_C0SC = 20; //Edge PWM

  TPM0_C0V = 1200;

  //PHC_LO

  TPM0_C1SC = 20;

  TPM0_C1V = 1200;

  //PHB_LO

  TPM1_MOD = 2400;

  TPM1_C0SC = 20;

  TPM1_C0V = 1200;

  //PHA_LO

}

I would greatly appreciate it if someone would point me to what I am not doing correctly.

Thanks so much!

ラベル(1)
タグ(2)
0 件の賞賛
返信
1 解決策
1,204件の閲覧回数
mjbcswitzerland
Specialist V

Hi

1 Make sure that you have enabled the IRC48M by setting the HIRCEN bit in MCG_MC.

2. TPMx_MOD should be (2400 - 1) to give the exact frequency you want.

3. PTMx_CnSC of 0x28 is a known good value for PWM - yours (0x14) may be Ok but I didn't check.

4. TMPx_SC is best written as final command rather than before setting up the details (since it enables the operation)

5. I suspect the major issue is the TPMx_SC value since 4 divides the clock by 16 but doesn't enable the operation. Probably you wanted to set 8 in order to have a divide by 1 and start it.

I would always work with defines for the control bits to avoid such potential errors.

Below is the uTasker code to do this on the KL03, plus the simulated KL03 registers so that you can check your register values for comparison:

PWM_INTERRUPT_SETUP pwm_setup;

pwm_setup.int_type = PWM_INTERRUPT;

pwm_setup.pwm_mode = (PWM_IRC48M_CLK | PWM_PRESCALER_1);             // clock PWM timer from the IRC48M clock with /1 pre-scaler

pwm_setup.int_handler = 0;                                           // no user interrupt call-back or DMA on PWM cycle

pwm_setup.pwm_frequency = PWM_FREQUENCY(20000, 1);                   // generate 20kHz on PWM output

pwm_setup.pwm_value   = _PWM_PERCENT(50, pwm_setup.pwm_frequency);   // 50% PWM (high/low)

pwm_setup.pwm_reference = (_TIMER_0 | 0);                            // timer module 0, channel 0

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

pwm_setup.pwm_reference = (_TIMER_1 | 0);                            // timer module 1, channel 0

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

TPM0:

pastedImage_0.png

TPM1:

pastedImage_1.png

Regards

Mark

P.S. As reference, I have attached the uTasker PWM interface code which is compatible for TPM or FlexTimer PWM operation on all chips, including interrupt and DMA operations.

元の投稿で解決策を見る

0 件の賞賛
返信
2 返答(返信)
1,205件の閲覧回数
mjbcswitzerland
Specialist V

Hi

1 Make sure that you have enabled the IRC48M by setting the HIRCEN bit in MCG_MC.

2. TPMx_MOD should be (2400 - 1) to give the exact frequency you want.

3. PTMx_CnSC of 0x28 is a known good value for PWM - yours (0x14) may be Ok but I didn't check.

4. TMPx_SC is best written as final command rather than before setting up the details (since it enables the operation)

5. I suspect the major issue is the TPMx_SC value since 4 divides the clock by 16 but doesn't enable the operation. Probably you wanted to set 8 in order to have a divide by 1 and start it.

I would always work with defines for the control bits to avoid such potential errors.

Below is the uTasker code to do this on the KL03, plus the simulated KL03 registers so that you can check your register values for comparison:

PWM_INTERRUPT_SETUP pwm_setup;

pwm_setup.int_type = PWM_INTERRUPT;

pwm_setup.pwm_mode = (PWM_IRC48M_CLK | PWM_PRESCALER_1);             // clock PWM timer from the IRC48M clock with /1 pre-scaler

pwm_setup.int_handler = 0;                                           // no user interrupt call-back or DMA on PWM cycle

pwm_setup.pwm_frequency = PWM_FREQUENCY(20000, 1);                   // generate 20kHz on PWM output

pwm_setup.pwm_value   = _PWM_PERCENT(50, pwm_setup.pwm_frequency);   // 50% PWM (high/low)

pwm_setup.pwm_reference = (_TIMER_0 | 0);                            // timer module 0, channel 0

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

pwm_setup.pwm_reference = (_TIMER_1 | 0);                            // timer module 1, channel 0

fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration

TPM0:

pastedImage_0.png

TPM1:

pastedImage_1.png

Regards

Mark

P.S. As reference, I have attached the uTasker PWM interface code which is compatible for TPM or FlexTimer PWM operation on all chips, including interrupt and DMA operations.

0 件の賞賛
返信
1,204件の閲覧回数
stevengarfinkel
Contributor III

Thanks again.  With your help I was able to figure it out and get it to work.

0 件の賞賛
返信