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 not appearing on some pins [Tiva C Launchpad]

Other Parts Discussed in Thread: ENERGIA

I have hardware PWM working but I can't get it to appear on any pins other than the three that drive the LEDs. Is my code wrong?

In this case I'm looking for a PWM signal on PF0 and PA6 but not finding it.

/*################################################
# Hardware PWM proof of concept using
# the Tiva C Launchpad
#
# Started with example code by
# lawrence_jeff found here:
# http://forum.stellarisiti.com/topic/707-using-hardware-pwm-on-tiva-launchpad/
# 
# Altered to use code found on section
# 22.3 of the TivaWare Peripheral Driver
# Library User's Guide found here:
# http://www.ti.com/lit/ug/spmu298a/spmu298a.pdf
#
#
# This example pulses three on-board LEDs
#
#################################################*/


#include "driverlib/pin_map.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"

void delayMS(int ms) {
    SysCtlDelay( (SysCtlClockGet()/(3*1000))*ms ) ;
}




int main(void)
{

    
    //Set the clock
   SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC |   SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

   //Configure PWM Clock to match system
   SysCtlPWMClockSet(SYSCTL_PWMDIV_64);

   // Enable the peripherals used by this program.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);  //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins

    //Configure PF1,PF2,PF3 Pins as PWM
    GPIOPinConfigure(GPIO_PA6_M1PWM2);
    GPIOPinConfigure(GPIO_PF0_M1PWM4);
    GPIOPinConfigure(GPIO_PF1_M1PWM5);
    GPIOPinConfigure(GPIO_PF2_M1PWM6);
    GPIOPinConfigure(GPIO_PF3_M1PWM7);
    GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6);
    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    //Configure PWM Options
    //PWM_GEN_2 Covers M1PWM4 and M1PWM5
    //PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC); 
    PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    unsigned long period = 5000;
    unsigned long pwmNow = period/10;

    //Set the Period (expressed in clock ticks)
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, period);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period);

    //Set PWM duty-50% (Period /2)
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1,pwmNow);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow);   //90 degrees
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);   //90 degrees
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);

    // Enable the PWM generator
    PWMGenEnable(PWM1_BASE, PWM_GEN_1);
    PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    PWMGenEnable(PWM1_BASE, PWM_GEN_3);

    // Turn on the Output pins
    PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT | PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);

    //Fade
    bool fadeUp = true;
    unsigned long increment = 10;
    
    while(1)
    {
        /*
    	delayMS(2000);
        pwmNow = period/20;
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow);   
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);   
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);

        delayMS(2000);
        pwmNow = period/10;
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow);   
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);   
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);
        */   
    }

}

  • PF0 is locked by default in GPIO only NMI pin, check Table 10-1. GPIO Pins With Special Considerations on the datasheet. You need to unlock it

      //
      // Unlock the Pin PF0 and Set the Commit Bit
      //
      HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
      HWREG(GPIO_PORTF_BASE + GPIO_O_CR)   |= 0x01;

    Also you have:

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1,pwmNow);

    When it should be PWM_OUT_2

  • Luis Afonso said:
    PF0 is locked by default in GPIO only

    Or not!  PF0 is locked into NMI service - not GPIO.

    For most here - that was a bad default - and herein claims (yet another) victim.

    PA6 should be a different issue - poster should further review...

  • cb1- said:

    PF0 is locked by default in GPIO only

    Or not!  It's locked into NMI service - not GPIO - and for most here - that was a bad default.

    [/quote]

    Right! sorry, corrected now

  • Good - you clearly know this stuff - used PWM in several of your projects...

  • do i note a bit of sarcasm? :P

    Well i know a bit, but of course there is much more to learn

  • Thank you all for your help figuring this out.

    Also you have:

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1,pwmNow);

    When it should be PWM_OUT_2

    The above suggestion fixed my issues with PA6. I suspected some type of "gotcha" with PF0 so I tried a different pin and port in PA6 only to be greeted by my own mistake :-P

    The unlocking issue is perplexing. It would be nice if TI did something like using red-fill on the lock pins in every table where they are displayed (like table 20-1).

    At any rate. I cleaned up my code and comments in hopes that this will be useful to others.

    /*################################################
    # Hardware PWM proof of concept using
    # the Tiva C Launchpad
    #
    # Started with example code by
    # lawrence_jeff found here:
    # http://forum.stellarisiti.com/topic/707-using-hardware-pwm-on-tiva-launchpad/
    # 
    # Altered to use code found on section
    # 22.3 of the TivaWare Peripheral Driver
    # Library User's Guide found here:
    # http://www.ti.com/lit/ug/spmu298a/spmu298a.pdf
    #
    #
    # This example pulses three on-board LEDs
    #
    #################################################*/
    
    
    #include "driverlib/pin_map.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pwm.h"
    
    void delayMS(int ms) {
        SysCtlDelay( (SysCtlClockGet()/(3*1000))*ms ) ;
    }
    
    
    
    
    int main(void)
    {
    
        
        //Set the clock
       SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC |   SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    
       //Configure PWM Clock to match system
       SysCtlPWMClockSet(SYSCTL_PWMDIV_64);
    
       // Enable the peripherals used by this program.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);  //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    
        //
        // Unlock the Pin PF0 and Set the Commit Bit
        // See datasheet table 10-1 for explanation of
        // why this pin needs unlocking
        HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
        HWREG(GPIO_PORTF_BASE + GPIO_O_CR)   |= 0x01;
    
    
        //Configure PF0,PF1,PF2,PF3, and PA6 Pins as PWM
        //See table 20-1 for these assignments
        GPIOPinConfigure(GPIO_PA6_M1PWM2);
        GPIOPinConfigure(GPIO_PF0_M1PWM4);
        GPIOPinConfigure(GPIO_PF1_M1PWM5);
        GPIOPinConfigure(GPIO_PF2_M1PWM6);
        GPIOPinConfigure(GPIO_PF3_M1PWM7);
        GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6);
        GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    
        //Configure PWM Options
        //PWM_GEN_2 Covers M1PWM4 and M1PWM5
        //PWM_GEN_3 Covers M1PWM6 and M1PWM7 See table 20-1 for these assignments
        PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC); 
        PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        
        //These settings are specifically designed to run servo motors
        //which expect 20mS period with between 1ms and 2ms high time
        //
        //System clock is 16MHz with PWM divider of 64
        // 16000000/64 = 250000/50 = 5000  ### 1S/50 = 20mS thats where divisor comes from
        unsigned long period = 5000;
        // Set high time to 2mS
        unsigned long pwmNow = period/10;
    
        //Set the Period (expressed in clock ticks)
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period);
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, period);
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period);
    
        //Set PWM duty
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,pwmNow);
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow); 
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);  
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);
    
        // Enable the PWM generator
        PWMGenEnable(PWM1_BASE, PWM_GEN_1);
        PWMGenEnable(PWM1_BASE, PWM_GEN_2);
        PWMGenEnable(PWM1_BASE, PWM_GEN_3);
    
        // Turn on the Output pins
        PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT | PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
    
        while(1)
        {
           
        	delayMS(2000);
            //set high time to 1mS
            pwmNow = period/20;
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,pwmNow);
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow);   
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);   
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);
    
            delayMS(2000);
            //set high time to 2mS
            pwmNow = period/10;
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,pwmNow);
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4,pwmNow);   
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,pwmNow);   
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,pwmNow);
            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,pwmNow);
            
        }
    
    }

  • I'm glad is working now, and thanks for sharing the code :)

  • @ Mike,

    More than 3 years past I suggested that vendor here employ bold RED to better communicate the (unwanted/devilish) default behavior enforced upon PF0 & PD7.  Vendor always "duly notes" but employs (proven) ineffectual forum "sticky" to alert.  Worked well for you (and many others) did it not?

    @ Luis,

    No sarcasm was implied nor intended - as business owner that is not effective - not my style.  I know that you have good understanding of PWM (we discussed this via conversations)  Note that my writing (above) employs "irony" not sarcasm in the ongoing protest of this vendor's "ineffectual" handling of "LONG STANDING Problems!"  Duly noted provides little comfort - ACTION corrects/solves.  Red was well utilized - each every front page of abandoned LM3S series!

  • I don't quite remember the LM3S datasheet, i was still only using Energia so consulting the datasheet was not necessary (imagen what is being presented with a 1,4k pages datasheet when i never seen one before)

    Sticky notes almost never work. This should be highlighted in the MCU datasheet or other document.The problem comes up more frequently than rain it seems so clearly what exists now does not work.

  • thanks for sharing the code
  • Thanks Mike for your code example. I spent several hours trying to drive a buzzer with a PWM. I went thru your code (very clean by the way) and I found that my mistake was how I calculated the period. Everything is working now. :-)
  • Your "thank you" gesture is appreciated - but possibly "not" by poster Mike!     (last seen/heard - these parts - more than two years past.)
    Mousing over poster's name/id reveals "recent postings" - providing such insight.

    It is good that you thanked and provided detail - my firm finds that ALWAYS employing "constants" (initially) for  "PWM Period & Frequency" - rather than a more complicated/calculated value - minimizes or prevents - the issue you found & corrected...