NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » C function that returns time?

January 06, 2013
by Eirias42
Eirias42's Avatar

Hi. Newbie here. Is there any c function that will return the time (like elapsed time since the program started or something similar to that?)

Thanks!

January 06, 2013
by Noter
Noter's Avatar

Not in the world of micro-controllers. You'd have to write your own function or find one someone else wrote.

January 06, 2013
by Eirias42
Eirias42's Avatar

OK.... Anybody know of one someone else wrote that's in the public domain? It's presumably possible, there's a millis() function on arduino that seems to do pretty much that...

thanks in advance for any help!

January 07, 2013
by JimFrederickson
JimFrederickson's Avatar

Hopefully this will give you a little bit of an understanding about timers.

    //  Global Variables
    volatile uint8_t timedays;
    volatile uint8_t timehours;
    volatile uint8_t timeminutes;
    volatile uint8_t timeseconds;
    volatile uint8_t timefracs;

    volatile uint8_t lasttimefracs;

    void timeclear () {
        cli();

        timefracs = 0;
        timeseconds = 0;
        timeminutes = 0;
        timehours = 0;
        timedays = 0;

        sei();
    }

    void timer0set(int timerid) {

    //  TCCR0A  -  Timer 0 Counter Control Register A
    //  TCCR0B  -  Timer 0 Counter Control Register B
    //
    //  Timer 0 Prescaler
    //  CS00  CS01  CS02    Description
    //    0     0     1     CPU Clock
    //    0     1     0     CPU Clock / 8
    //    0     1     1     CPU Clock / 64
    //    1     0     0     CPU Clock / 256
    //    1     0     1     CPU Clock / 1024

    //  Timer 0 Counter
    //  TCNTO

    //  TIMSK0  -  Timer Mask Register
    //  OCIE0  Timer 0 Comparison Interrupt
    //  TOIE0  Timer 0 Overflow Interrupt

    // setup Timer0:
    // CTC (Clear Timer on Compare Match mode)
    // Match Value set by OCR0A register
    TCCR0A |= (1<<WGM01);
    // clocked from System Clock CLK/1024
    // which is 14745600/1024, or 14400 increments per second
    TCCR0B |= (1<<CS02) | (1<<CS00);
    // set TOP to 143
    // because it counts 0, 1, 2, ... 142, 143, 0, 1, 2 ...
    // so 0 through 143 equals 144 events
    OCR0A = 155;
    // enable interrupt on compare event
    // (14400 / 144 = 100 per second)
    TIMSK0 |= (1<<OCIE0A);

    timeclear();
    }

    ISR(TIMER0_COMPA_vect)
    {
    //  Timer 0 Interrupt Overflow Service Routine

    //  One tick

    timefracs++;

    if (timefracs > 99) {
       timefracs = 0;
       timeseconds++;
       if (timeseconds > 59) {
          timeseconds = 0;
          timeminutes++;
          if (timeminutes > 59) {
             timeminutes = 0;
             timehours++;
             if (timehours > 23) {
                timehours = 0;
                timedays++;
                }
             }
          }
       }
    }

The above code doesn't particularly do it, but you can tweak the code so as to create and second/minute/hour/day time source accurate to a couple of seconds per week. (Depending on how stable your power source it, how consistent the temperature is, and how prone to vibration your wiring is. Maybe some other variables as well, but for consistency those for me were the primary ones.)

Where "OCR0A = 155" it is a little different than the remark's would indicate, but that is because this build was using a non-standard Crystal.

Basically that is creating an Interrupt about 100 times per second.

NOTE: The variables must have "VOLATILE" as an attribute.

What that attribute does is to make sure than in your code whenever any of those variables are accessed their values are read from memory and not from a register that the compiler had optimized.

That is NECESSARY because both foreground and background/interrupt tasks are accessing those values.

NOTE: It would be best, at least to start, to make sure that the values are ONLY changed from the interrupt routine.

you can use that as a basis to create any timers that you may need/want.

Try it, play with it, change it to suite your needs.

January 07, 2013
by Noter
Noter's Avatar

Using the internal timer of the ATmega is one way to do it, another is to add a real time clock chip like the DS3232 and query it whenever you want the time. If you reset it to 00:00 when the program starts then the time you read would be the elapsed time. Check Rick's thread on the DS3232 RTC where he shows how to use it and provides code samples.

January 07, 2013
by Ralphxyz
Ralphxyz's Avatar

Then of course there is always the Nerdkits Real Time Clock project if you want good documented help.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that the printf format string "%.3f" will show three digits after the decimal point? Learn more...