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.

PWM Clock Divisor Not Working

Other Parts Discussed in Thread: TM4C1294NCPDT

I am using the LM4F part with the TivaWare library.  In the datasheet for the LM4F232H5QD, there is a note about the clock configuration register (RCC) being available only as legacy support for the PWM clock divide and to use PWMPC (page 252).  So I used the new PWM register PWMPC (page 1315) but it does not divide the clock.  The register shows the value 0x101 when viewed in the debugger for a divide by 4 PWM clock but it still runs at the system clock speed. I tried other clock speeds too.

I decided to try the legacy register to see if it would work and it will allow the USEPWMDIV bit to be set but will not allow any other value written to the PWMDIV register except 0 so only a divide by 2 clock works and not 4.  So the RCC register appears to have slightly more functionality than the new PWMPC register but I still can't get a divide by 4 option set. 

Is there a trick or order to make this work or is the functionality broken in the micro? 

  • A little more investigation I find that the only way to get the divider set is through the (supposed to be removed) TivaWare function SysCtlPWMClockSet(SYSCTL_PWMDIV_4).  This does work but the PWMPC register doesn't seem to do anything.  It doesn't even update with the value once the previous function is called.  If in the debugger, you attempt to change the value of the RCC system register, it will only take a 0 value giving a divisor of 2.  Just be careful when using the SysCtlPWMClockSet function as a similar change was done to the ADC module and it could "undo" the other module as they both have ties to the RCC register. The ADCPC register at this point appears to function.

    So there is an issue with the CCSv5 debugger register view/change and the PWMPC register and/or datasheet. 

  • Adding to the same subject, as I had a similar problem in July/2014 and found a solution:

    Initially I tried the "obvious":

    SysCtlPWMClockSet(SYSCTL_PWMDIV_32);
    // Should set the PWM clock to use SysClock divided BUT THIS IS NOT WORKING!!!

    However, on Tiva uC's the register which sets the divider has changed. Up to version 2.1.0, as far as I am aware, there is no TivaWare function for that.

    So I wrote directly to the proper register as below:

    HWREG(PWM0_BASE + 0xFC8) = (256 + 5);
    // Set register PWMCC to use SysClock divided by 64

    Value 5 can be anything from 0 to 5, and divides by 2, 4, 8, 16, 32, 64. This worked just fine.

    The processor is the TM4C1294NCPDT, that comes on the Evaluation Board.

  • Yes i can confirm that there are some bugs with TivaWare with the new TM4C1294NCPT wich i was unable to change the clock. So i tried an alternative since i don't know almost notigh at all about direct acess

    So i used the timers to produce PWM, like so:

    The folowing code is for the TM4C1294 but should work in most Tivas. In this case it configures PA4 as a PWM output

    uint32_t freq = 100000;
    
    void setup()
    {
      // put your setup code here, to run once:
      unsigned long ulPeriod, dutyCycle;
      ulPeriod = 120000000/freq ;
      dutyCycle = ulPeriod/2; 
    
      // Configure PA4 as T2CCP0
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);    
      GPIOPinConfigure(GPIO_PA4_T2CCP0);              
      GPIOPinTypeTimer(GPIO_PORTA_BASE, GPIO_PIN_4);  
      //
    
      // Configure timer
      SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);                        
      TimerConfigure(TIMER2_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);   
      TimerLoadSet(TIMER2_BASE, TIMER_A, ulPeriod -1);                     
      TimerMatchSet(TIMER2_BASE, TIMER_A, dutyCycle); // PWM  
    
      //Turn on PWM
      TimerEnable(TIMER2_BASE, TIMER_A);
    }
  • Luis Afonso,

    Thanks for the input! I guess there's more than one way to skin a cat.

    I had read about the PWM function of the Timers block (which I believe is a totally different peripheral than the above discussed PWM module), but never used it. It is indeed an option for generating PWM signals, and I will give it a try sometime soon.

    My concern is about creating low frequency PWM's... The timer clock is typically SysClock, and with the new Tiva's that's already running at 120MHz. The Timer counter is only 16 bits, so only quite high frequencies can be generated. HOWEVER, there is the "prescaler" thing on the GP Timer settings, which apparently turns the counter as a 24-bit. If that is indeed the case, pulses as slow as 14Hz can be achieved, but I have yet to understand, try and figure out this prescaler.

    By the way, about writing directly to a register, simply use:

    HWREG(REGISTER_ADDRESS) = (NEW_VALUE);

    It's worth learning about it. If you have time, follow the example of the PWM Divider above and you will surely understand.

    Saudações!

    Bruno

  • Yes with the prescaler you should be able to get realy low frequency rates, i still haven't had the need for that so i don't know the math for that 

    If anyone could assist with that it would be apreciated

    Saudações

  • Hello Luis,

    The PWM module with the PWMCC divider and maximum LOAD values can be used to get the PWM pulse rate down to 28Hz as well.

    Please note that the timer can do the same thing as well, but control and configuration for PWM with other inputs like fault, deadband is something that the Timer implementation would not be able to do.

    Regards

    Amit

  • Gentlemen,

    After dealing with the matter for a while, I was finally able to get timers running from very slow clocks (available on the TM4C129x). Using 32768Hz as a timer clock, it is easy to generate or measure very low frequencies.

    This is the timer settings that I got to work FOR MEASURING. For generating, it is quite similar except for the timer mode. It runs on the EK launchpad.

    //==============================================
    // Configure Timer3 to run from the Hibernate clock at 32768Hz
    //==============================================
    void configure_timer3(void)
    {
    	// Configure the hibernate module accordingly
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    	HibernateEnableExpClk(g_ui32SysClock);
    	WaitForClockRegister();
    	HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE);  // Use external 32768Hz crystal with 12pF capacitors
    	WaitForClockRegister();
    	HibernateClockConfig(HIBERNATE_OUT_SYSCLK);    // Enables the RTCOSC to be used as a system clock for peripherals
    	WaitForClockRegister();
    	HWREG(0x400FE000 + 0x138) = (0x03);  // Configures register ALTCLKCFG to use RTCOSC as a source
    
        // Configure the Timer module
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
        GPIOPinConfigure(GPIO_PM2_T3CCP0);
        GPIOPinTypeTimer(GPIO_PORTM_BASE,GPIO_PIN_2);
    
        TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_PIOSC);   // Configures GPTMCC with 0x01 to use the alternate clock ALTCLK
        TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME | TIMER_CFG_B_PERIODIC);
        TimerLoadSet(TIMER3_BASE, TIMER_A, 0xFFFF);
        TimerLoadSet(TIMER3_BASE, TIMER_B, 0xFFFF);
        TimerControlEvent(TIMER3_BASE,TIMER_A,TIMER_EVENT_POS_EDGE);
        TimerIntClear(TIMER3_BASE, TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT);
        TimerIntEnable(TIMER3_BASE, TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT);
        IntEnable(INT_TIMER3A);
        IntEnable(INT_TIMER3B);
        TimerEnable(TIMER3_BASE, TIMER_BOTH);
    }

    This code uses two separate timers, the B part increments a counter in case the period is longer than 2 seconds... The theory behind it would also work for timers running from the system clock, but there would be an interrupt every ~250us, which is not that efficient.

    The period measured is (65536*counter + delta_capture)

    Cheers,

    Bruno