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.

CCS/DK-TM4C129X: Can't get PWM output.

Part Number: DK-TM4C129X


Tool/software: Code Composer Studio

I have used the PWM before but for some reason I can't get it to output a pulse.

pinout.c configuration:

//
// Configure the GPIO Pin Mux for PF0
// for M0PWM0
//
MAP_GPIOPinConfigure(GPIO_PF0_M0PWM0);
MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);
//
// Configure the GPIO Pin Mux for PG0
// for M0PWM4
//
MAP_GPIOPinConfigure(GPIO_PG0_M0PWM4);
MAP_GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_0);
//
// Configure the GPIO Pin Mux for PF2
// for M0PWM2
//
MAP_GPIOPinConfigure(GPIO_PF2_M0PWM2);
MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2);

My code is:

// Enable PWM0
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0))
{}
 // Configure the PWM0
PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 4096);

PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0_BIT, 2048);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2_BIT, 2048);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4_BIT, 2048);
PWMGenEnable(PWM0_BASE, PWM_GEN_0);
PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT), true);


  • Hello Robert,

    You need to call multiple Generator configuration API's.

    PWM Out 0 and Out 1 are on PWM_GEN_0

    PWM Out 2 and Out 3 are on PWM_GEN_1

    PWM Out 4 and Out 5 are on PWM_GEN_2

    So you need three sets of the PWMGen calls.

    That should get you going.

  • Ralph,

    I modified my init code and still do not get any output on PF0, PF2 or PG0

    void PWMInitialize(void)

    {

    // Enable PWM0

    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0))

    {}

    // Configure the PWM0

    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 4096);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4_BIT, 2048);

    PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    PWMGenEnable(PWM0_BASE, PWM_GEN_1);

    PWMGenEnable(PWM0_BASE, PWM_GEN_2);

    PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT), true);

    }

  • Hello Robert,

    Looking over one of my examples, this API call is also used:

        //
        // Set the PWM clock to the system clock.
        //
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    Try adding that. I will also try and test your code shortly on a Dev Kit.

  • Ralph,

    Added call but still no output.

    void PWMInitialize(void)

    {

    // Enable PWM0

    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0))

    {}

    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    // Set the PWM clock to be 30MHz, 120MHz / 4

    // PWMClockSet(PWM0_BASE, SYSCTL_PWMDIV_4);

    // Configure the PWM0

    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 4096);

    // set valves to 50%

    // setAirValvePWM(50);

    // setAbateValvePWM(50);

    // setAmbientValvePWM(50);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4_BIT, 2048);

    PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    PWMGenEnable(PWM0_BASE, PWM_GEN_1);

    PWMGenEnable(PWM0_BASE, PWM_GEN_2);

    PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT), true);

    }

  • At least w/in these most recent posts - there appears 'no evidence'  that Ports 'F &  G' have been Enabled!

    BOTH the appropriate Ports & PWM Modules  MUST be Enabled!     You 'have' quite nicely 'Configured & Typed' the PWM Pins/Modules - yet the 'Sleeping Ports' (appear) to be 'Signalling their displeasure!'

    An 'excellent' yet 'under-utilized means of rapid trouble-shooting' sees one, 'Attempting to Output initially via the selected Port's GPIO!'     This proves FAR Faster & Easier - and will quickly signal such 'Missing' Port Enables!       (which is too easily 'masked' by the more complex PWM demands - as (very) well noted here...)

  • From pinout.c generated from pinmux,

    //

    // Enable Peripheral Clocks

    //

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);

  • How would one, 'Distant from your code' know that?     Remote diagnostics demands (reasonably) complete communication of all key facts.

    I believe your next step is to attempt to "output via those same pins - yet configured (this time) as GPIO Outputs!"     (this prevents the 'undue exercising' of vendor & outsider staff...)

    Three here (my firm) have searched - w/your new advisement (Ports WERE Enabled) our 'best/fast bet' is that (maybe) the code's sequence of function calls proves important.    Here's one of  our 'PWM Module' call sequences - 'KNOWN to WORK!'     Port & other PWM housekeeping has already been performed.

    ROM_GPIOPinTypePWM();

    ROM_GPIOPinConfigure();

    ROM_PWMGenConfigure();

    ROM_PWMGenPeriodSet(); 

    ROM_PWMPulseWidthSet();

    ROM_PWMGenEnable();

    ROM_PWMOutputState();

  • I modified the init code to set the pins as GPIO and toggle.  I see the pins toggle stepping through code.  Still no PWM output.

    void PWMInitialize(void)

    {

    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0);

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);

    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);

    GPIOPinConfigure(GPIO_PF0_M0PWM0);

    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2);

    GPIOPinConfigure(GPIO_PF2_M0PWM2);

    GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_0);

    GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0, GPIO_PIN_0);

    GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0, 0);

    GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_0);

    GPIOPinConfigure(GPIO_PG0_M0PWM4);

    // Enable PWM0

    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0))

    {}

    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    // Set the PWM clock to be 30MHz, 120MHz / 4

    // PWMClockSet(PWM0_BASE, SYSCTL_PWMDIV_4);

    // Configure the PWM0

    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 4096);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 4096);

    // set valves to 50%

    // setAirValvePWM(50);

    // setAbateValvePWM(50);

    // setAmbientValvePWM(50);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2_BIT, 2048);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4_BIT, 2048);

    PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    PWMGenEnable(PWM0_BASE, PWM_GEN_1);

    PWMGenEnable(PWM0_BASE, PWM_GEN_2);

    PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_2_BIT | PWM_OUT_4_BIT), true);

    }

  • Hello cb1,

    FYI I knew those were called because he mentioned pinout.c which when used enables all GPIO, so that's why I didn't ask on my end. Naturally though you are right that as an outsider that wouldn't be clear.

    We all missed a little 'devil in the details' with the configuration though.

    Robert, 

    Now that I ran the code I was able to see what was missing. The PWMPulseWidthSet function needs the PWM_OUT_x parameter, not the PWM_OUT_x_BIT parameter! Use this instead:

        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 2048);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, 2048);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, 2048);

    That got me the output on the DK board.

  • That did it, thanks.

  • Good job, Ralph.     But do note:

    Ralph Jacobi said:
    I knew those were called because he mentioned pinout.c

    May I note that 'such mention' only occurred (after) I had noted the 'Lack of Port Peripheral Enables' - and poster's mention was 'Not w/in his code' - it was (only) w/in his 'explanation.'   (of  'pinout.c - having 'gone missing!)

    We have always felt that the 'similarity' between those named parameters - and the fact that they are 'arbitrary' (i.e. w/out any 'tie' to the calling function) proves 'troublesome' - and as shown here - has 'claimed another victim.'

    A 'superior parameter naming  (CONVENTION)' - one 'Linked back to the specific 'Function Call' - surely would assist.     For example:

    • PWMPulseWidthSet()  better employs,   "PWM_OUT_0_PW"  - rather than the (current) cryptic  "PWM_OUT_X"
    • PWMOutputState()       better employs,   "PWM_OUT_0_OS"  - rather than the  (current) cryptic  "PWM_OUT_0_BIT"

    Note that in each case - the (suggested NEW  'Parameter'  Name) actually  REFLECTS the  'Calling Function's'  Name (significantly improving usage & diagnosis) - and differing by (only) the final 2 letters!    (which perfectly 'mirror' the calling function!)      As was proven today - right here - over TEN Forum Postings were required to resolve  this (existing) 'parameter name confusion'  (even after your & my best efforts) - caused by the lack of (any) logical nor realistic 'parameter connection or link'  - to its  'hapless' calling function!   (Overheard ...  "What  WAS  that parameter's name???")

    Surely those parameters are 'unlikely'  to benefit from this contribution - yet a 'better way' has been identified - and presented here - for the benefit of  MANY!