AnsweredAssumed Answered


Question asked by JAEYONG SONG on May 7, 2019
Latest reply on May 10, 2019 by JAEYONG SONG



I have modified the TPM_PWM example to use freeRTOS and drive a motor.

The PWM signal was very noisy when I checked with an oscilloscope and also with a motor controller as shown below.



I changed the PWM frequency and for some reasons, it seemed to work better with higher frequency then stopped working after some value.

When I was checking with the oscilloscope, the measuring frequency was also changing. I assume there might be something wrong with the TPM source clock?

Here is the code I used and the TPM1_CH0 pin was used to send PWM out. 

What the code does is, once the SW3 button is pressed and Motor_Switch is true, the sinusoidal duty cycle of PWM is sent out.


/* Interrupt to enable and flag to read; depends on the TPM channel used */
#define TPM_CHANNEL_INTERRUPT_ENABLE kTPM_Chnl1InterruptEnable
#define TPM_CHANNEL_FLAG kTPM_Chnl1Flag

/* Get source clock for TPM driver */


void vMotor_Control_Task(void)
   volatile uint16_t updatedDutycycle=0;
   TickType_t xLastWakeTime;

   tpm_config_t tpmInfo;
   tpm_chnl_pwm_signal_param_t tpmParam;

   #define TPM_LED_ON_LEVEL kTPM_HighTrue
   tpmParam.chnlNumber = (tpm_chnl_t)TPM_CHANNEL;
   tpmParam.level = TPM_LED_ON_LEVEL;
   tpmParam.dutyCyclePercent = 100U;

   /* TPM known issue of KL81, enable clock of TPM0 to use other TPM module */
   /* Select the clock source for the TPM counter as kCLOCK_PllFllSelClk */

   /* Initialize TPM module */
   TPM_Init(TPM_BASEADDR, &tpmInfo);
   TPM_SetupPwm(TPM_BASEADDR, &tpmParam, 1U, kTPM_EdgeAlignedPwm, 5000U, TPM_SOURCE_CLOCK);
   TPM_StartTimer(TPM_BASEADDR, kTPM_SystemClock);

   /* Disable channel output before updating the dutycycle */
   TPM_UpdateChnlEdgeLevelSelect(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, 0U);

   int Motor_Switch = -1;
   uint16_t Sin_time = 0;
   while (1)
      xLastWakeTime = xTaskGetTickCount();

      if (g_ButtonPress)
         PRINTF(" %s is pressed \r\n", BOARD_SW_NAME);
         GPIO_PortToggle(EDO_GPIO, 1U << EDO_PIN);
         Motor_Switch *= -1;
         g_ButtonPress = false;
            PRINTF("Duty Cycle is on \r\n");

            PRINTF("Duty Cycle is off \r\n");
            Sin_time = 0;
            updatedDutycycle = 100;
      if (Motor_Switch==1)
         updatedDutycycle = (uint16_t) 450 + 350*sin(2*PI*Sin_time/1000-PI/2);
         /* Disable channel output before updating the dutycycle */
         TPM_UpdateChnlEdgeLevelSelect(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, 0U);

         /* Update PWM duty cycle */
         TPM_UpdatePwmDutycycle(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, kTPM_EdgeAlignedPwm, updatedDutycycle);

         /* Start channel output with updated dutycycle */
         TPM_UpdateChnlEdgeLevelSelect(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, TPM_LED_ON_LEVEL);
         TPM_UpdateChnlEdgeLevelSelect(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, 0U);
         TPM_UpdatePwmDutycycle(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, kTPM_EdgeAlignedPwm, 100U);
         TPM_UpdateChnlEdgeLevelSelect(TPM_BASEADDR, (tpm_chnl_t)TPM_CHANNEL, TPM_LED_ON_LEVEL);

      vTaskDelayUntil(&xLastWakeTime, 1);


Thank you.