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.

TM4C1290NCPDT: There is a problem with timer setting to PWM mode

Part Number: TM4C1290NCPDT

dears all:
              I set TIMER1B to PWM mode; The rest of the configuration is the same, except when different edges are used to capture interrupt update cycles and duty cycles, the phenomenon is different;
             1、Code section: PWM period value change mode(ms): 1 -> 2 -> 3 -> 4 ->5 - 4 -> 3 -> 2- > 1 ->2 ... ; duty: 50%

/* timer configuration */
GPIOPinConfigure(GPIO_PL6_T1CCP0);
GPIOPinConfigure(GPIO_PL7_T1CCP1);
GPIOPinTypeTimer(GPIO_PORTL_BASE, GPIO_PIN_6|GPIO_PIN_7);

TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM);
HWREG(TIMER1_BASE + TIMER_O_TBMR)|=0x00000500; // update on the next timeout.

TimerControlLevel(TIMER1_BASE,TIMER_B,0);
TimerControlEvent(TIMER1_BASE, TIMER_B, TIMER_EVENT_POS_EDGE); //TIMER_EVENT_NEG_EDGE);

TimerIntClear(TIMER1_BASE, TIMER_CAPB_EVENT);
TimerIntEnable(TIMER1_BASE,TIMER_CAPB_EVENT);
IntEnable(INT_TIMER1B);

/* timer start */
TimerLoadSet(TIMER1_BASE, TIMER_B, 120000 & 0xFFFF); // 1ms period
TimerPrescaleSet(TIMER1_BASE,TIMER_B, (120000 >> 16)&0xff);
TimerMatchSet(TIMER1_BASE,TIMER_B, 60000 & 0xFFFF);  // 50% duty
TimerPrescaleMatchSet(TIMER1_BASE,TIMER_B, (60000 >> 16)&0xff);
TimerEnable(TIMER1_BASE, TIMER_B);


/* interrupt handle */
void Timer1BIntHandler(void)
{
    static uint32_t period = 120000; // 1ms
    static uint32_t duty = 0;
    static uint8_t inc_flag = 1;
    // printf("timer1B int\n");

    if (inc_flag) 
    {
        period += 120000;
        if (period >= 600000)
        {
            inc_flag = 0;    
        }
    }
    else 
    {
        period -= 120000;
        if (period <= 120000)
        {
            inc_flag = 1;    
        }
    }

    duty = period >> 1;
    TimerLoadSet(TIMER1_BASE, TIMER_B, period&0xffff);       // period
    TimerPrescaleSet(TIMER1_BASE, TIMER_B, (period >> 16)&0xFF);
    TimerMatchSet(TIMER1_BASE, TIMER_B, duty&0xffff);          // duty
    TimerPrescaleMatchSet(TIMER1_BASE, TIMER_B, (duty >> 16)&0xFF);
    // TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    TimerIntClear(TIMER1_BASE, TIMER_CAPB_EVENT);
}

2、When using the drop edge mode, the normal, waveform is as follows:




3、When using the rising edge mode, anomalies and waveforms appear as follows:




Thanks.

  • Greetings,

    Nicely presented - it is a "bit early" to wrap my head around the "width & breadth" of your code's logic.

    Might you consider - at least as a means to, "Speed success while adding insight" use of  "at least one - perhaps Two Wide Timers" - enabling you to eliminate the added complexity & demands imposed by the Pre-Scaler!    (Note that ARM MCUs are usually "rich in timers" - and by your reducing your code's breadth & extent - your focus is properly limited - usually resulting in faster & superior results!)

    Later - if "Saving Timers" proves desirable - you can exploit your "Wide Timer Success" to return (now "better armed") to your earlier timer usage...

    The above is an illustration of "KISS" - one basic step - carefully monitored & confirmed - and only then extending...   Multiple "moving parts" - all activated in "One Go" - rarely leads to a, "fast, successful, stress-free" outcome...

  • Hello,

    user4100895 said:
    I set TIMER1B to PWM mode; The rest of the configuration is the same, except when different edges are used to capture interrupt update cycles and duty cycles, the phenomenon is different;

    I am not entirely clear on the problem here. It looks like perhaps as you change the period value, there are issues with the duty cycle, is that what you are seeing? Maybe a bit more description about the exact difference from the performance vs what you are expecting would help. Right now I am unclear what the boxed areas in your images are meant to represent.

  • hello,

    thanks for your reply.

    What I expect is to adjust the PWM cycle and duty cycle at the same time, and the duty cycle is 50%; However, the waveform measured by the actual oscilloscope is not the same as I expected.

  • hello,

    thanks for your reply, but I didn't understand what you meant.

  • wesley zeng said:
    I didn't understand what you meant.

    My friend,

    You chose to use the "Half-Timers" AND the "Prescaler" - that demands added code (and effort) upon both you & any "would be" helpers!

    You can SIMPLIFY (ease & speed your code) by using (instead) any "WIDE TIMER" (32 bits) which ELIMINATES the requirement for the PreScaler!

    Pardon but I do not know HOW to (even) better explain...    Might you identify that which you do not understand?

  • hello,

    I see what you mean, But when the chip's timer is set to PWM mode, this is the only way.Here is the chip description:

    The pre-divider register in this mode is only used to extend the periodic value of PWM.

    I did some more experiments and found that they didn't match my description,Both the uptrend and downtrend events trigger the PWM cycle and duty cycle will occur, but not necessarily.Later, I only updated the PWM cycle, not the duty cycle.This way I can do more experiments without any problems.

    Periodic register: GPTMTnILR and GPTMTnPR

    Duty cycle control register: GPTMTnMATCHR and GPTMTnPMR

  • Whoops - you are correct - I was wrong.   My direction to "simplify" clashed w/the MCU's (actual) capability.    (and there are ARM Cortex MCUs which "Do deliver" 32 bit PWM capability - keeping track of such fine detail - across different vendors' MCUs - is demanding...)

    [edit]: 12:52 CST   Sunday, late arriving staff commented, "Not so Fast w/that "Whoops" - on this (rare) occasion - you (meaning moi) may have been right!"   (I'm well aware of, "Pity Laughs" (as I employ humor (or attempt to) to "tease greater effort")  ... yet "Pity Support" - that's new!)   Our MCU manual notes:

    ■ 32/64-bit operating modes:
    – 32-bit PWM mode with a 16-bit prescaler and software-programmable output inversion of the PWM signal


    This from the TM4C123 manual - we have never been fans of the '129 family.   Is it possible that the (lowly) yet cost down '123 - offers beyond that of the '129?

    Now I must note:

    wesley zeng said:
    I did some more experiments and found that they didn't match my description.  Both the uptrend and downtrend events trigger the PWM cycle and duty cycle will occur, but not necessarily.   Later, I only updated the PWM cycle, not the duty cycle.   This way I can do more experiments without any problems.

    The fact that you "experimented" - as you've noted - is outstanding!   (I'm sure that vendor agents & we (interested) outsiders appreciate & applaud your "experimentation."   Almost always - a "carefully designed & implemented experiment" produces "Real Insight & Understanding" - which MCU manuals & API usage alone - often cannot match!)   (i.e. many (including moi) "learn best" by "Doing" (i.e. poking around & experimenting!)

    *** Wise to Note: Such "Experimenting" - beneficial as it is - must AVOID:   

    • Re-Purposing any of the JTAG Pins (PC0-PC3)
    • Creating any form of configuration error of the System Clock   (double, triple check - before making (any) changes!)

    (violation of this "guide" may "Lock you Out" from your MCU!)

    Now while we applaud your experiment - issues reveal:

    • "Later, I only updated the PWM cycle, not the duty cycle."

    You've not explained "Why you felt the need" to update the PWM cycle (frequency).   I believe that updating the PWM frequency - w/out also updating the duty cycle - will yield improper results.   (i.e. the duty cycle (will or may) continue w/the value as last set (which is not what you want) or if the PWM frequency was "raised too much" - the "old" duty cycle value may be "excessive" - causing unwanted results.)

    It is believed "best practice" to:

    • disable the timer & prescaler   (it appears that this was never done!)
    • configure into the 32 bit, PWM mode   (unless the '129 (cannot) achieve that!   Pity!)
    • enter the newly sought PWM Frequency
    • only then enter the desired Duty Cycle
    • re-enable the timer/prescaler

    Most applications run w/PWM Frequency "fixed" - and only the duty cycle is regularly updated - which proves much easier to implement.    Do you (really) need to change the PWM frequency?

  • Hello Wesley,

    Are aware there is setup time required when you reconfigure GPTM on the fly in the interrupt context? Also it seems you are capturing edges and configure 2 CCPn GPIO inputs but only configure timer B, down count or up count? There was errata on 1294 up count, not sure about 1290 check errata sheet. It is clear to us duty cycle update via the timer interrupt does not work well on the 1294. It would often stop updates for no reason when modifying the duty match counts register, say for 20-25kHz frequency.

    It is a much better work around to update match counts via a separate periodic interval timer not associated with CCPn edge count interrupt.  

  • hello,

    Our application direction is motor control, PWM is used to control the motor pulse, the period is required to change in real time.

    I will also try to turn the timer on/off later, although this is something we should avoid.

  • hello GI,

    Thank you for your reminding, I went to see the errata of the chip, as follows:

    But the PWM mode of the chip is working down the count, the erratum did not make a statement.

  • wesley zeng said:
    Our application direction is motor control, PWM is used to control the motor pulse, the period is required to change in real time.

    Are not the "Motor & Driven Load" subject to inertia?    Thus much depends upon the definition of, "Real time" - does it not?   

    Would you be good enough to "identify" your motor-type - which demands (both) "Regular PWM Frequency & Duty Cycle" Updates?    Again - it is believed that "Regular Duty Cycle Updates" is "Far more common!"

    Should your "motor control" application be at all serious - your use of the "vastly more capable (& protective) PWM Generator" proves a (most) superior choice!    (My group now, "out of bullets" - good luck...)

  • For 1ms time base, GPTM seemingly use PIOSC, recall mention in datasheet. CB1 last bullet has best approach unless GPTM intent was sinusoidal wave points for duty cycles. The edged counter works ok at 1Hz, not so sure about how reliable PWM dutycycle. Forget real time duty updates the match count load may lock timer at some point no matter the update mode. GPTM 60mHz clock source may cause issues at low frequency.

        /* Configure GPTM-0 16Mhz, 62.5us clock source.*/
    	MAP_TimerClockSourceSet(TIMER0_BASE, TIMER_CLOCK_PIOSC);
        /* GPTM ALTCFG clock source low frequency
         * PIOSC = 10kHz Min, 33kHz Nom, 75kHz Max*/
    	HWREG(SYSCTL_ALTCLKCFG) = SYSCTL_ALTCLK_PIOSC;