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/TM4C123GH6PM: Issue on TIMERS frequency

Part Number: TM4C123GH6PM

Tool/software: Code Composer Studio

Hi

I need to generate two signals for driving a device, one at 25 Hz and another one to 1.4MHz. I have been testing with the code below but I can only achieve 645 kHz even setting the Load to 1.4Mhz, is there something am I doing wrong?
I can also notice that in some frequencies the duty cycle changes with no reason since I left it on 50%. I am trying to figure out what is happening on the datasheet and the TIVA peripherals library but since I am beginner with the Tiva C any help is appreciated.

Thanks in advance

Isra

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"


int main(void)
{
    uint32_t ui32Period;

    //SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    ui32Period = (SysCtlClockGet()/25) / 2 ;
    TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1);
    IntEnable(INT_TIMER0A);
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    //IntMasterEnable();
    TimerEnable(TIMER0_BASE, TIMER_A);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
    TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
    ui32Period = (SysCtlClockGet()/10) / 2;
    TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period -1);
    IntEnable(INT_TIMER2A);
    TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
    //IntMasterEnable();
    TimerEnable(TIMER2_BASE, TIMER_A);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
    ui32Period = (SysCtlClockGet()/1400000) /2 ;
    TimerLoadSet(TIMER1_BASE, TIMER_A, ui32Period -1);
    IntEnable(INT_TIMER1A);
    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    IntMasterEnable();
    TimerEnable(TIMER1_BASE, TIMER_A);


    while(1)
    {
    }
}

void Timer0IntHandler(void)
{
    // Clear the timer interrupt
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    // Read the current state of the GPIO pin and
    // write back the opposite state
    if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
    }
    else
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
    }
}

void Timer1IntHandler(void)
{
    // Clear the timer interrupt
    TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    // Read the current state of the GPIO pin and
    // write back the opposite state
    if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1))
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
    }
    else
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 2);
    }
}

void Timer2IntHandler(void)
{
    // Clear the timer interrupt
    TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);

    // Read the current state of the GPIO pin and
    // write back the opposite state
    if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3))
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);
    }
    else
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 8);
    }
}

  • Hi Israel,
    If you want to generate periodic PWM you need to either use the GPTM module in PWM mode or use the PWM module. The way you are using the GPTM to control the period of the PWM will not be precise. The higher priority interrupts can preempt lower priority interrupts. In addition, when you spend longer time in the ISR than the next interrupt arrives it will affect your duty cycle.

  • The "duty cycle" changes because it takes too long for the isr to execute vs the desired frequency.

    Try output compare or pwm peripheral for high frequency output.
  • Beyond poster "Danny's" valid suggestions - might I advise that you employ, "KISS?"

    To my mind - you are,  "Holding your Key/Critical PWM Output HOSTAGE - to many variables - which (both) complicates - and serves to "Mask your Diagnosis" - and  correction!

    Rather than launch 3 separate PWM attempts - would it not "Speed, Ease, Enhance" - to attempt just ONE?     And in ISOLATION - not constrained by the "false gods" - of  OTHER Influences and/or Restrictions?

    As another has stated - you should easily be able to create PWM at your (highest) chosen frequency - by employing an INDIVIDUAL TIMER (A or B) configured (properly) to PWM Mode.    

    The "Peripheral Driver Library - User Guide" exhaustively details (via Timer Section) and is "Sure to prove enlightening!"     And escapes/avoids the "excess" - which your current code (failing) reveals...

  • Dear all, I tried something simpler as cb1_mobile suggested and with PWM as the others kindly recommend. I got now the 1.4 MHz signal (thanks) but I cannot produce a 25 Hz signal,  it goes to 1.4 kHz, could you take a look into my (failing again) code please?

     unsigned long ulPeriod;
        unsigned long u2Period;
    
        SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); //for 80 MHz
    
       SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
        ulPeriod = SysCtlClockGet() / 1400000;
        u2Period = SysCtlClockGet() / 25; // 
    
        GPIOPinConfigure(GPIO_PF1_M1PWM5);
        GPIOPinConfigure(GPIO_PF2_M1PWM6);
    
        GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    
        PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
        PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, u2Period);
    
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,u2Period/2);
    
        PWMGenEnable(PWM1_BASE, PWM_GEN_2);
        PWMGenEnable(PWM1_BASE, PWM_GEN_3);
    
        PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT, true);
    
           while(1)
        {
    
        }

  • Had you reviewed - as past directed - the  "requirement forced upon (ulPeriod)" when contained w/in "PWMGenPeriodSet()?"      Does that not prove a (very) likely suspect?

    Now its not my desire to, "Do your job for you" - yet I will "hint" here that your use of the  "PWM Generator" ...  "Giveth - but (sometimes) Taketh Away!"    

    You did not remark upon your (somewhat unusual)  "1000:1" difference in PWM Output Frequencies - even though - especially though - your divisors, "Exhibit NO SUCH relationship!    (i.e. 1.4M & 25!)

    That's of  key/critical note - is it not?     (and (sorry) should NOT have been missed!)     Do you (now) see your issue?

  • Why do you unsolve a problem that you already solved?
  • What ... (already) solved problem?     Poster noted: "Only achieve 645 kHz!"    

    Far from solved - (some) would say...    (a "more correctly guiding" solution - appears above...)

  • I was thinking wrong about the response. Feel kind of stupid I did not pay attention on that but thanks so much for the guidance
  • No one "wants" such a "feeling" - you're surely clever enough to spot such (unusual) occurrences (1000:1 ratio)  such should be Noted - should it not?

    You need to "better focus upon ALL clues" - that's NOT at all (low-intellect) - poor awareness better describes.      (and for a 2nd here - as well.)

    Fortunately - even though (banned) here, "KISS" very much - assists that effort!    (extra focus - aids/amplifies awareness)

    Thanks your verification - yet you've not (yet)  "Seized upon" the reason for the 1000:1 ratio" - and (someone) here - (still) believes - that will AID your understanding/make you stronger...

  • Fly west early tomorrow - (thus unlikely I'll be here) - to reduce frustration -  comes now ...  (another) clue.

    Might you be,  "Trying to stuff-in" -  more than this (particular)  "bag of stuff"  (yes, "stuff")  - may  (reasonably) hold?     For "extra credit" - from where did the 1000:1 "frequency ratio" (as you earlier reported) arise?

  • Had this forum penetrated w/in the hallowed halls of "Bronx Sci" ... the "extra credit bin" would (now) be, "OVER-FLOWING!"     Pity...

    Crack millennial staffer offers up,  "0xD400"  as one further clue...   (it is feared that her effort - may pass unrecognized...)