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.

PMW problem on TM4C123GH6PGE

Other Parts Discussed in Thread: TM4C123GH6PGE

Hello,

I have problem enabling pwm signal on my TM4C123GH6PGE device on PP1 pin. Here's the code:

int main()
{
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);


    GPIOPinTypePWM(GPIO_PORTP_BASE, GPIO_PIN_1);
    GPIOPinConfigure(GPIO_PP1_M0PWM1);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 10000);
    PWMPulseWidthSet(PWM0_BASE, PWM_GEN_0, 2000);

    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
    while(1)
    {

    }
}

When I connect oscilloscope I can't see anything, PP1 stays high.

  • I've reviewed your code - its similar to ours - and ours works! Might you (temporarily) migrate that code to another port/pin - and try there?

    Suggest that you (first) change that port/pin to GPIO Output - and bang that. Does that toggle that pin? At least this proves that port/pin to be, "alive/well." Sorry I don't see your error...

    I've made the time/effort to check for your, "TM4C123GH6BGE" @ Digi-Key - no such part number reveals.

    I suspect that double letter forces yours to be BGA device - and I do find PP1 resident upon 157 pin BGA.   But again - none as you've listed, here.

    If the device "is" BGA - and if its not a "pro" Eval board - how sure are you of the chip's assembly/soldering?

    Note that this pin may serve as a Timer, too.   Check to insure you've not re-config'ed this pin - away from the PWM set-up you show...

  • Hello user4232017,

    It seems that you may have the debugger connected. If that is indeed the case then set the DEBUG bit in the PWM0CTL since it may be halting the PWM counter when clear.

    cb1,

    I think it is PGE and not BGE...

    Regards
    Amit
  • Hi Amit,

    I have no doubt that, "You are correct, Sir!" Yet poster's have (some) responsibility to properly ID their part AND I have no (insider) knowledge of PGE vs. BGE. (such is marketing - not engineering/programming)

    May I note that our J-Link is (most always) connected and while we "halt PWM" when the program breaks/stops - our debugger has never prevented our PWM from appearing.    Might you detail?    Thanks.

  • Hello cb1,

    Sure. When the debugger is connected and the Register view window is open for PWM register space, that causes the PWM to stop. I have always set the bit after a heart burn experience to keep PWM rolling.

    Regards
    Amit
  • Hi Amit,

    Instant Amit response - and fully detailed - thank you & (as always) much appreciated!

    As we (so often) operate w/high power motors/actuators - we want our PWM to cease immediately when our program breaks/stops. And we achieve that w/parameter, "PWM_GEN_MODE_DBG_STOP" w/in function, "ROM_PWMGenConfigure()."

    I'm wondering if the behavior you note (PWM output disabled) may be "CCS specific" - I don't recall such via our IAR IDE... Again thanks...

  • Hello cb1,

    When the parameter PWM_GEN_MODE_DBG_STOP is not given then the default value is PWM_GEN_MODE_DBG_STOP in the register bit.

    Regards
    Amit
  • Yet - is it not (far) safer to, "Not rely upon default behavior - which may change w/a new {SW or HW} release - and may not be especially clear to non-insiders (i.e. all but you)" and instead produce code which (clearly) identifies your exact desires?
  • Hello cb1,

    I believe the idea behind the default value was to be able to stall the PWM when the register space is open under debug,

    Regards
    Amit
  • Yes it is PGE not BGE , I'm sorry for misspelling device ID.

    I've checked PP1 pin before posting, it works when used as GPIO.

  • I've set PWM_GEN_MODE_DBG_RUN, I can see PWM_0_COUNT changing, but still no output on PP1 pin. Here's the screenshot of ccs in dbg mode:

  • Feel your (continued) pain.    I've looked at your code - ours (working) is much the same.

    Good that you confirmed via GPIO - such is always a "good idea" & helpful if included in first posting.

    May I suggest that you (temporarily) alter your code to support another PWM appropriate pin - and see if that works.   We may "chase our tails" if there's some "issue" w/PP1 in PWM mode - switching to another pin serves to confirm that your code (in general) is correct.

    We note that you're "silent" as regards your program (possibly) altering that PWM config. elsewhere.   (that PP1 may be used as Timer_4 iirc.)

    Only other possibility is that your program "faults" and thus does not reach (nor remain) w/in the PWM code segment.   A blinking Led w/in your "while loop" would confirm that indeed - program is running & reached that PWM code segment.

  • Well, my code looks exactly like this now, no PWM config changes in software after initial setup (just like before):

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


    int main()
    {
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);

    GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_6);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_3);
    GPIOPinConfigure(GPIO_PG3_M1PWM1);

    PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC | PWM_GEN_MODE_DBG_RUN);

    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, 10000);
    PWMPulseWidthSet(PWM1_BASE, PWM_GEN_0, 2000);

    PWMGenEnable(PWM1_BASE, PWM_GEN_0);
    PWMOutputState(PWM1_BASE, PWM_OUT_1_BIT, true);
    uint32_t i;
    while(1)
    {
    for(i = 0; i < 500000; i++);
    GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, GPIO_PIN_6);
    for(i = 0; i < 500000; i++);
    GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0);
    }
    }

    PM6 is my led pin, it blinks like it should. As you can see, I've changed PWM output to PG3, still no luck.
    I'm using XDS560v2 STM JTAG emulator, if that info may help.

    Can someone please confirm that I'm using PWMGenConfigure and other functions with correct parameters? Table 20-1 in datasheet says in description field for PG3: "Motion Control Module 1 PWM 1. This signal is controlled by Module 1 PWM Generator 0." Is that what I'm using or is there some error in my code?
  • I would not have made so extensive a change.   (i.e. changed the module from 0 to 1)

    Rather than search your code - here's an extract of "known working" PWM code:

     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);    

     delay(10);    

     // Make the PWM pins be peripheral function.          

    ROM_GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6 | GPIO_PIN_7);     

    ROM_GPIOPinConfigure(GPIO_PB6_M0PWM0);     

    ROM_GPIOPinConfigure(GPIO_PB7_M0PWM1);          

    ROM_GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_4 | GPIO_PIN_5);     

    ROM_GPIOPinConfigure(GPIO_PG4_M0PWM4);     

    ROM_GPIOPinConfigure(GPIO_PG5_M0PWM5);          

    ROM_GPIOPinTypePWM(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);     

    ROM_GPIOPinConfigure(GPIO_PC4_M0PWM6);     

    ROM_GPIOPinConfigure(GPIO_PC5_M0PWM7);

    ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2);     

    ROM_GPIOPinConfigure(GPIO_PF2_M0FAULT0);          

    ROM_PWMGenConfigure(PWM0_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN |  PWM_GEN_MODE_GEN_SYNC_GLOBAL  |  PWM_GEN_MODE_GEN_SYNC_LOCAL   |   PWM_GEN_MODE_DB_SYNC_LOCAL |   PWM_GEN_MODE_FAULT_EXT | PWM_GEN_MODE_FAULT_MINPER |    PWM_GEN_MODE_DBG_STOP));

    ROM_PWMGenEnable(PWM0_BASE, PWM_GEN_0);    

    ROM_PWMGenEnable(PWM0_BASE, PWM_GEN_2);    

    ROM_PWMGenEnable(PWM0_BASE, PWM_GEN_3);

    ROM_PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_4_BIT |   PWM_OUT_5_BIT | PWM_OUT_6_BIT |   PWM_OUT_7_BIT), true);

    Do note its 04:40 here - I haven't time/patience to format this code better.

    I suggest that you search your MCU data to see if any of the pins (above, my code) enjoy the same PWM function as yours.   If so - you should be able to simply "cut/paste" this working code.

    Note that we did not use your, "SysCtlPWMClockSet(SYSCTL_PWMDIV_1);"    I'm unsure if - at your chosen system clock speed - that function works w/the DIV_1!     I simply don't know.    We relied upon default value (which I normally abhor).

    Ours is a complex PWMGenConfigure() - unlikely that you require this.   (yours looked good to me)

    Note that we set PWM frequency & duty cycle at regular update intervals - elsewhere in our code.   Your code - in that regard - looked fine.

  • Hello _BT_

    Replace
    PWMPulseWidthSet(PWM1_BASE, PWM_GEN_0, 2000);

    with
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1, 2000);

    The original parameter will load CmpA while you are using the CmpB.

    Regards
    Amit
  • Hi Amit,

    Indeed - you found it! As stated - we updated that piece of code elsewhere - here's our version:

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, ulWidthA); // ulWidthA
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, ulWidthA);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, ulWidthB);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_5, ulWidthB);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6, ulWidthC);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_7, ulWidthC);

    Poster's not alone in "guessing" that parameter's proper choice/coding. To my mind - these parameters are NOT named w/great clarity - nor are they fully/properly detailed.

    And - worse still - the (otherwise) excellent MCU manual provides NO direction toward StellarisWare or TivaWare - employing (dreaded) Direct Register in its place! Good job in finding - one must look "everywhere!"

    There's a "lesson learned" here in cb1's screw-up - keep ALL related code (even if bypassed/commented out) together - for efficient "reuse or diagnosis."    As we use many ARM MCUs (several vendors) - I can't (easily) recall all such detail (nor would I want to) thus "everything together" speeds/simplifies/enhances...   That NOT being together "bit me - and this poor poster" in this thread.    Sorry BT...