Skip to main content
Visitor II
February 27, 2011
Question

How to generate us and ms incremental counters?

  • February 27, 2011
  • 1 reply
  • 769 views
Posted on February 27, 2011 at 03:50

How to generate us and ms incremental counters?

    This topic has been closed for replies.

    1 reply

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 15:12

    Your question has no solution, if it's literally taken.

    Even Arduino milli() or micro() functions use an interrupt routine...

    To make things clear, the following code is taken from:

    arduino-0022-src.tar.gz\arduino-0022\hardware\arduino\cores\arduino\wiring.c

    // the prescaler is set so that timer0 ticks every 64 clock cycles, and the

    // the overflow handler is called every 256 ticks.

    #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))

    // the whole number of milliseconds per timer0 overflow

    #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)

    // the fractional number of milliseconds per timer0 overflow. we shift right

    // by three to fit these numbers into a byte. (for the clock speeds we care

    // about - 8 and 16 MHz - this doesn't lose precision.)

    #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)

    #define FRACT_MAX (1000 >> 3)

    volatile unsigned long timer0_overflow_count = 0;

    volatile unsigned long timer0_millis = 0;

    static unsigned char timer0_fract = 0;

    SIGNAL(TIMER0_OVF_vect)

    {

        // copy these to local variables so they can be stored in registers

        // (volatile variables must be read from memory on every access)

        unsigned long m = timer0_millis;

        unsigned char f = timer0_fract;

        m += MILLIS_INC;

        f += FRACT_INC;

        if (f >= FRACT_MAX) {

            f -= FRACT_MAX;

            m += 1;

        }

        timer0_fract = f;

        timer0_millis = m;

        timer0_overflow_count++;

    }

    unsigned long millis()

    {

        unsigned long m;

        uint8_t oldSREG = SREG;

        // disable interrupts while we read timer0_millis or we might get an

        // inconsistent value (e.g. in the middle of a write to timer0_millis)

        cli();

        m = timer0_millis;

        SREG = oldSREG;

        return m;

    }

    unsigned long micros() {

        unsigned long m;

        uint8_t oldSREG = SREG, t;

       

        cli();

        m = timer0_overflow_count;

    #if defined(TCNT0)

        t = TCNT0;

    #elif defined(TCNT0L)

        t = TCNT0L;

    #else

        #error TIMER 0 not defined

    #endif

     

    #ifdef TIFR0

        if ((TIFR0 & _BV(TOV0)) && (t < 255))

            m++;

    #else

        if ((TIFR & _BV(TOV0)) && (t < 255))

            m++;

    #endif

        SREG = oldSREG;

       

        return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());

    }

    As you can see, the millis() and micros() functions use timer0_overflow_count and read the TIMER0 value.

    If you want to replicate them, TIM4 is alike Arduino's timer0.

    As regards your code, you have to follow what wiring.c does: handle TIM4 overflow interrupt and read TIM4 in millis() and micros() code.

    regards

    EtaPhi