Playing with Arduino
A page to record my playing with Arduino
TIMER0_OVF_vect

Abstract

TIMER0_OVF_vect is an interrupt handler that is executed when the Timer/Counter0(TCNT0) overflows. It is used to manage uptimes of the Arduino.

As the TCNT0 is an 8bit Timer/Counter, it overflows after each 256 increments. The division ratio is set to 64, the TCNT0 is incremented every 64 clocks. As a result, this handler is executed each 256 * 64 = 16384 clocks.

Source Code

The TIMER0_OVF_vect is defined in hardware/arduino/avr/cores/arduino/wiring.c as below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 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;
 
ISR(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++;
}

The MICROSECONDS_PER_TIMER0_OVERFLOW is a value of interval of Timer/Counter0 overflow in microseconds.

The clockCyclesToSeconds() is a macro to convert specified clock numbers to milliseconds.

The MILLIS_INC represents the interval time of Timer/Counter0 overflow in millisecgonds.

FRACT_INC stores the fractional number of milliseconds.

The timer0_overflow_count is a variable to hold the number of times that this interrupt handler is called.

The timer0_millis holds the millisecond part of the time. The timer0_fract holds the fractional part of milliseconds in microseconds.

The ISR() is a macro to define an interrupt handler.

Timer0_millis and timer0_fract are copied to m and f respectively.

18
19
20
21
22
23
ISR(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;

This interrupt handler is called when the Timer/Counter0 overflows.

If the f is greater than or equal to FRACT_MAX, it means the microsecond part exceed 1000.

25
26
27
28
29
30
    m += MILLIS_INC;
    f += FRACT_INC;
    if (f >= FRACT_MAX) {
        f -= FRACT_MAX;
        m += 1;
    }

Then f and m are wrote back to the original variables.

Finally、timer0_overflow_cout(The number of times this handler was called) is incremented.

32
33
34
35
    timer0_fract = f;
    timer0_millis = m;
    timer0_overflow_count++;
}

Version

Arduino 1.8.13

Last Update

June 19, 2020

inserted by FC2 system