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.

Timer trouble

Hi everyone,

I faced with trouble about frequency of timer as a counter mode.

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

#define SW1            GPIO_PIN_4
#define SW2         GPIO_PIN_0

#define LED_RED        GPIO_PIN_1
#define LED_GREEN    GPIO_PIN_2
#define LED_BLUE    GPIO_PIN_3


uint32_t ui32Period,t;
uint32_t val;

void INIT_LED()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTF_BASE,  LED_RED|LED_GREEN|LED_BLUE, 0);
}

void CFG_TIM0()
{
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
        ui32Period = (SysCtlClockGet()/40);
        TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period-1);
         TimerEnable(TIMER0_BASE, TIMER_A);
}
int main(void) {
    SysCtlClockSet(SYSCTL_SYSDIV_2_5| SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ);
    INIT_LED();
    CFG_TIM0();
    t = LED_RED;
    while(1)
    {
        val=TimerValueGet(TIMER0_BASE,TIMER_A);
        if(val==0)
        {
            GPIOPinWrite(GPIO_PORTF_BASE,  LED_RED, t);
            t = t ^ LED_RED;
        }
    }
}

As my knownledge, timer will counter from 0 to ui32Period -1, with frequency = 1/SysCtlClockGet(); but after some tests, I realized that frequency for counter is a constant = 2Mhz ( not equal 80Mhz as clock of CPU). Please help to explain for my trouble.

Thanks in advanced!

  • Hello Anh,

    You are correct that the timer will count from 0 to ui32Period-1. However the frequency will be SysCtlClockGet() and not 1/SysCtlClockGet(). 1/SysCtlClockGet() is the time period of the clock. In this case the timer frequency will be 400KHz (80MHz/200).

    Secondly. when counting the fact that TimerValueGet has to be 0 may not be true as the CPU when reading the timer may not read 0 due to the fact it takes a few instructions for the CPU to read the timer output. Rather use an interrupt when timer reaches time put value to toggle the IO.

    Regards
    Amit
  • Sorry Amit,
    I just adjusted ui32Period = (SysCtlClockGet()/40);
    In my thought, Timer period = 2Mhz. that mean. timer will count from zero to a value = 2,000,000. with frequency = SysCtlClockGet().
    Am I right? If not please correct it.
    Thanks!

  • Hello Anh

    Yes, that is correct. Divide by 40 will yield a count for timer interval of 2MHz when the system clock is configured for 80MHz.

    Regards
    Amit
  • Below program used to toggle RED LED with period = 2 second. Can you explain for me?

    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/sysctl.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/timer.h"
    
    #define SW1 GPIO_PIN_4
    #define SW2 GPIO_PIN_0
    
    #define LED_RED GPIO_PIN_1
    #define LED_GREEN GPIO_PIN_2
    #define LED_BLUE GPIO_PIN_3
    
    
    uint32_t readStatus,ui32Period,tinh;
    uint32_t val=0;
    int tick;
    
    void INIT_LED()
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, 0);
    }
    
    void config_timer()
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
    ui32Period = (SysCtlClockGet()/40);//1s
    TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period-1);//1s
    TimerEnable(TIMER0_BASE, TIMER_A);
    }
    int main(void) {
    SysCtlClockSet(SYSCTL_SYSDIV_2_5| SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    
    INIT_LED();
    config_timer();
    
    tinh = LED_RED;
    while(1)
    {
    val=TimerValueGet(TIMER0_BASE,TIMER_A);
    if(val==0)
    {
    GPIOPinWrite(GPIO_PORTF_BASE, LED_RED, tinh);
    tinh = valLED ^ LED_RED;
    }
    }
    }



    Thanks

  • Hi,

    Anh Nguyen Duc said:
    I faced with trouble about frequency of timer as a counter mode

    This is a little bit confusing what you really want to do.

    But, supposing you try just to play with a timer, then I suggest to change the operating mode to counting down, as you test the timer value against zero - this is specific to counting down. To count up, you need to use the matching register, and when the timer value equals the content of matching register, then an event will be triggered. You load the timer register with a value and counting up no event is triggered - the timer overflows and then it gets zero value. 

    Second, this kind of working is much better suited to work with interrupts, rather than polling the end value. 

    Please review the user manual....

  • Hi,
    In my case, zero mean a value within period, we can change it to whatever value, it's will blink red LED with period = 2 second (1s ON, 1s OFF).
    As you can see, this line:
    ui32Period = (SysCtlClockGet()/40);
    I set period = 2,000,000; CPU frequency = 80Mhz, how it can blink with period = 2 second? I'm really confusing.

  • Hello Anh,

    As both Petrei and me have suggested , instead of polling use an interrupt mechanism to get the right time period for the LED change instead of the polling mode of TimerValueGet(TIMER0_BASE,TIMER_A);

    Regards
    Amit
  • Yes, thanks for your suggestions, but I need to clear my confusing, please help to explain previous question. The program I write above (it's work well) make me confuse with my knowledge.
    Thanks!
  • Hello Anh

    And the answer is in the forum post as well. How can you be sure that when function TimerValueGet is called the counter value is read as 0. Read any CPU architecture and it will tell that it takes x number of instructions to get a register value in the system address space. It is not possible to ensure that it will read 0.

    Another way to look at it, that you are looking at display screen that is refreshing at 60Hz while blinking your eyes. How can you be sure that every time you blink your eye, you would see the same refresh cycle per second!!!!

    Regards
    Amit
  • Hi Amit,
    I measured it by a counter program in smartphone with my friend, maybe it not accuracy 100%, but it's can acceptable.
    When I change ui32Period = (SysCtlClockGet()/40); to ui32Period = (SysCtlClockGet()/20);
    The periode of blinking = 4 sec ( 2sec ON and 2sec OFF). With your answer, I reprogram and it work. But the second program still make me confused. I can not make it clear by myself.
    Thanks for your support!
  • Hello Anh,

    We have already stated the correct approach to use timer to generate accurate delays every time. There can be no more over-emphasis.

    Regards
    Amit
  • I still waiting for a answer for my question :) I hope someone can help.
  • Anh Nguyen Duc said:
    I still waiting for a answer

    My small tech firm find that vendor's Rep provided "above/beyond" tech support.

    Rather than "waiting" might several re-reads of the MCU manual's Timer section and the various Timer API examples - guide you to that critical answer?

    It's likely that you'll require such Timer mastery to pursue your 64x32 RGB Led project - is it not?

    Sometimes (perhaps often) individual study and experimentation proves superior to "waiting."

  • Hello cb1,

    Both Petrei's input and mine have been to use the timer interrupt, but it seems that the poster does not intend to use interrupt for some reason....

    Regards
    Amit