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 on a TM4C123GH6PZ

Other Parts Discussed in Thread: TM4C123GH6PZ

I am using a TM4C123GH6PZ using CCS 5.1 and TivaWare 1.0.  I have ported PWM code that was working on the LM4F EKS and is not working our new target hardware that arrived this week.  The HW is working nicely on many levels.  I have an example main loop that was derived from LM3F example code and example code in the TivaWare user guide.  The #define lets me put out a wave form on H0,1,2 using simple GPIO writes to prove that the HW works.  The outputs drive test LEDs.  The HW works.  Would any sharp eye pick up what is in the PWM code that is not working?  The LEDs are off at all times.  With the USE_FAUX_PWM set to 1, all LEDs flash.

Tiva™ TM4C123GH6PZ

#define USE_FAUX_PWM 0
    {
        unsigned long ulPeriod;
        unsigned long fauxPWMcounter = 0;
        unsigned long onOff = 0;
        SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN
                        | SYSCTL_XTAL_20MHZ);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
#if USE_FAUX_PWM
        GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2);
#else
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
        GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_2);
        GPIOPinTypePWM(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        ulPeriod = SysCtlClockGet() / 500;
        PWMGenConfigure(PWM0_BASE, PWM_GEN_0,
                PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ulPeriod);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, ulPeriod / 4);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, ulPeriod * 3 / 4);
        PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, true);
        PWMGenEnable(PWM0_BASE, PWM_GEN_0);
#endif
        /// ***************************************************************

        while (1) {
            fauxPWMcounter++;
            if (fauxPWMcounter>=100000) {
                fauxPWMcounter = 0;
                if (onOff) {
#if USE_FAUX_PWM
                    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, 0);
#else
                    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, 0);
#endif
                    onOff = 0;
                }
                else {
#if USE_FAUX_PWM
                    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2);
#else
                    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, GPIO_PIN_2);
#endif
                    onOff = 1;
                }
            }
        }
    }

  • P.S.  I moved back to the EKS, which for this function has the same pinout and function.  The above code does not work on the EKS either.  I doubt whether this is a Tiva silicon vs LM4F silicon issue.  I do not believe the above code should generate an interrupt.  I am not ending up in the defined interrupts for PWM_GEN_0.

  • John Osen said:
    Would any sharp eye pick up what is in the PWM code

    Reluctantly after your past issue (yesterday) was quickly/completely solved - yet unheralded...  (might you correct?)

    GPIOPinConfigure() is required - but escapes your code.  You did list GPIOPinType() - but while necessary - that is insufficient. 

    GPIOPinConfigure() requires bit different parameterization: "GPIO_PC4_M0PWM6" illustrates.

    And - PWMGenConfigure() proves far safer when you include parameter: "PWM_GEN_MODE_DBG_STOP" - again absent your listing.  (will kill the PWM outputs upon a debug "halt" - thus protecting any future - downstream power components and/or precious load...

     

  • While you were responding, I was backing my code into your suggestion. The final code:

            SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN
                            | SYSCTL_XTAL_20MHZ);
            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    #if USE_FAUX_PWM
            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
            GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2);
    #else
            SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
            SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
            GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_2);
            GPIOPinConfigure(GPIO_PH0_M0PWM0);
            GPIOPinConfigure(GPIO_PH1_M0PWM1);
            GPIOPinTypePWM(GPIO_PORTH_BASE, GPIO_PIN_0);
            GPIOPinTypePWM(GPIO_PORTH_BASE, GPIO_PIN_1);
            ulPeriod = SysCtlClockGet() / 20000;
            PWMGenConfigure(PWM0_BASE, PWM_GEN_0,
                    PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ulPeriod);
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, ulPeriod / 4);
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, ulPeriod * 3 / 4);
            PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
            PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
            PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    I had two problems.  The one you suggest and I was setting the period to something that clearly did not work. 

    I also note that in all of the LM3|4F examples of PWM and GPIOPinConfigure that the combination is only used a handful of times and not in the examples I happened to use as templates (a subsequent search came up with the use of GPIOPinConfigure).  Our code worked when based on StellarisWare, but it appears TivaWare requires this explicit call.  Hmmm....

    Thanks for you advice.

    (I did mark my issue yesterday as solved this morning.)

  • John Osen said:
    Our code worked when based on StellarisWare, but it appears TivaWare requires this explicit call.  Hmmm....

    While we're told (most of the rebrand SW is "the same") - past experience rarely confirms.  (and not just here - but many times - past 20 years...)  Thus - our group avoids rebrand till pioneer bodies removed from over-flowing trail.

    Might you award Verify to today's response (both you/I) as in concert - solved your issue.  (I did not review each/every line - your code - as the missing call was the major stumbling block...and I highlighted for your correction)

    Comments yesterday - and today - were based upon my understanding of StellarisWare - months away from adopting the rebrand.

    Thanks for your verify - yesterday's post - always appreciated.  (vendor's wampum - difficult to barter...) 

    And - did you attempt the GPIODirectModeSet() offered by another - yesterday?   This does not work under StellarisWare - indeed requires the 2nd call - as I listed in your behalf.  Both such calls are "encapsulated" w/in GPIOPinType() (w/in Stellarisware) - thus to our group/clients - superior...

  • On DirectModeSet...Not yet.  I need to polish my PWM code, drive changes through CAN commands and see what happens.  I may have been wrong about our StellarisWare code, I now find that it was our code (written by another engineer) that drove me to try the Config function.  I was surprised that the many pwmgen.c files did not.  A couple did.  The example in TivaWare DRL did not.

    I hope a TI engineer sees the "Update the PWM example in TivaWare-DRL-UG.pdf" hint in this thread.  Of course now that it was answered in a day, they may not look at it.

    Thanks again for inputs.  I have included the DEBUG flag as well.

  • John Osen said:
    I have included the DEBUG flag as well.

    Believe that is wise - likely will buffer you from the PWM counter's continuance - which may prove "exciting" - when you "continue" after pause @ break-point.

    Perhaps during rebrand - "some/many" past Stellaris Functions were "encapsulated."  Sue Cozart alerted towards a document - which may describe/define.  (again - our group will trust rebrand effort when tide recedes - signposts more prominent.)  (this via any vendor)

    May I flag concern re: "drive changes via CAN Commands?"  Too many items in the "chain of events" may dull responsiveness and add complexity.  Believe it faster/safer to initially develop/test each of your target functions via direct SW call.  Then - we'd test the commo channel - (we use small TFT which convincingly monitors up to 64 GPIO) - only after both have been test/verified - would shotgun wedding (CAN -> PWM fn) be attempted...

  • CB,

    Thanks for the pointers.  I will hunt down the Cozart reference.

    (I have written "throw away" tests at the function level.  I used to put them into a private configuration managed function test, but the app would never be maintained after the next dozen features or so.  So now I am honest about just throwing away unit tests.  I actually had this awesome oscilliscope hooked up that measured frequence and duty cycle.  This helped discover that the SysCtlClockGet returns the clock frequency and SysCtrlPWMClockGet returns the PWM clock register option that is not a frequency.)

    The commanded tests are setting up our build facility to test at end-of-line.  I use the throw away unit tests to reduce the chance these overwhelmed engineers have to deal with obvioius garbage.  (Somehow this is a step that was not fully exercised in the Tivo rebrand.)