This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C1231H6PZ: PWM and Prescaler

Part Number: TM4C1231H6PZ

Hello ,

i have an problem to understand pwm and prescaler ...

If i use the pwm without prescaler,

everything work as  expected.

If i use the precaler, erverything went wrong ...

TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) ;

I thought, that this will divide /2 .

The freq will be 1khz instead of 2khz, but the pwm dutycycle doesn't work anymore.

As i understood i will have an 24bit Counter ( 16bit + 8bit prescaler ), but what about the

the load and match, they are still 16bit ?

What i have to do, to use pwm with prescaler?

//PWM frequency in hz
uint32_t freq = 2000;

int tmain()
{

  //Set system clock to 80Mhz
  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
  SysTickbegin();

  uint32_t Period, dutyCycle;
  Period = SysCtlClockGet()/freq ;
  dutyCycle = Period-2;
 
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  SysCtlDelay(3);


  GPIOPinConfigure(GPIO_PF1_T0CCP1);
  GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_1);
 
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
  SysCtlDelay(3);

  TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) ;

 
  TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);
  TimerLoadSet(TIMER0_BASE, TIMER_B, Period -1);
  TimerMatchSet(TIMER0_BASE, TIMER_B, Period  ); // PWM

 
  TimerEnable(TIMER0_BASE, TIMER_B);

  int i;

  while(1)

{
 
    for(i=1; i <  ( Period ) -1; i++){
      TimerMatchSet(TIMER0_BASE, TIMER_B, i);
      SysCtlDelay(200);
    }

  }

}

  • Hi,

      TimerPrescaleSet is used to prescale the timebase. If the prescale value is equal to 0 then the timebase is to PWM is 80Mhz. Hence, 80MHz is the timebase for the counter to count down based on the load value you set in TimerLoadSet. If the prescale value is 1 as in your TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 )  then the timebase is 40Mhz. The counter is first preloaded with the value you define in TimerLoadSet() and count down based on the timebase of 40Mhz. Suppose, the prescale value is 9 and therefore the timebase becomes 8MHz.  The timebase for the counter becomes 8Mhz. You will have to configure the load value and match value with respect to the new timebase. If you want a 50% duty cycle you still need to configure as follows:

      TimerLoadSet(TIMER0_BASE, TIMER_B, Required_Period);

    TimerMatchSet(TIMER0_BASE, TIMER_B, Required_Perioed / 2); 

    I'm not sure why you wrote the below. The match value is larger than the load value. In this case the PWM output will always be HIGH. 

     TimerLoadSet(TIMER0_BASE, TIMER_B, Period -1);
      TimerMatchSet(TIMER0_BASE, TIMER_B, Period  ); // PWM

    Also in your while loop, you cannot just keep updating the match value. Your while loop will be much faster than the PWM finishing one PWM period.  If you want to walk through all the match values, you should generate interrupt at the end of each PWM period and in the ISR increment the match value. 

  • Hi,

    i thinke don't understand the prescaler ...

    I have changed Load and the match to fixed values.

    With this Code i see what i expected

     // TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) ;


      TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);
      TimerLoadSet(TIMER0_BASE, TIMER_B, 32000 );
      TimerMatchSet(TIMER0_BASE, TIMER_B, 16000 ); // PWM

    The i use the prescaler  ....

     TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) ;


      TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);
      TimerLoadSet(TIMER0_BASE, TIMER_B, 32000 );
      TimerMatchSet(TIMER0_BASE, TIMER_B, 16000 ); // PWM

    And i got this

    Why the dutycycle isn't 50% anymore, if the prescaler only devides the freq by to ????

    Andreas

  • Hi,

      Sorry, perhaps I wasn't clear in my explanation before. When you set TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) , try to think the counter become 17 bits. The period of you PWM is calculated as follows. 

      TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 1 ) ;

      TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);


      TimerLoadSet(TIMER0_BASE, TIMER_B, 32000 );


      period = TimerLoadGet(TIMER0_BASE, TIMER_B) + TimerPrescaleGet(TIMER0_BASE, TIMER_B) * 65536 ;

      duty = period / 2; 

     TimerPrescaleMatchSet(TIMER0_BASE, TIMER_B, duty / 65536);


    TimerMatchSet(TIMER0_BASE, TIMER_B, duty % 65536);

    You can try to do an experiment with the below PWM period. Let me know if you get 50% duty cycle. 

     TimerPrescaleSet( TIMER0_BASE , TIMER_BOTH , 123 ) ;

      TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);

      TimerLoadSet(TIMER0_BASE, TIMER_B, 45678 );

     period = TimerLoadGet(TIMER0_BASE, TIMER_B) + TimerPrescaleGet(TIMER0_BASE, TIMER_B) * 65536 ;

      duty = period / 2; 

     TimerPrescaleMatchSet(TIMER0_BASE, TIMER_B, duty / 65536);


    TimerMatchSet(TIMER0_BASE, TIMER_B, duty % 65536);