I want to change timer0 frequency because I need to use 4 PWM pins at a frequency lower than 500Hz and the SPI on an ATmega328. So I changed timer2 to Fast PWM with 64 divisor, enabled the overflow interrupt for timer2 and disabled the overflow interrupt for timer0:

  TCCR2A = _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  TIMSK2 |= (1 << TOIE2); // enable overflow interrupt for timer2
  TIMSK0 &= ~(1 << TOIE0); // disable overflow interrupt for timer0

and changed the ISR vector in wiring.c from ISR(TIMER0_OVF_vect) to ISR(TIMER2_OVF_vect).

But delay doesn't work. What can be the problem?


Now everything works except for delay()

delay() uses micros() and micros() reads the hardware registers, like this:

unsigned long micros() {
    unsigned long m;
    uint8_t oldSREG = SREG, t;

    m = timer0_overflow_count;
#if defined(TCNT0)
    t = TCNT0;
#elif defined(TCNT0L)
    t = TCNT0L;
    #error TIMER 0 not defined

#ifdef TIFR0
    if ((TIFR0 & _BV(TOV0)) && (t < 255))
    if ((TIFR & _BV(TOV0)) && (t < 255))

    SREG = oldSREG;

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

You would need to change all those references (TCNT0, TIFR0, TOV0 etc.) to use the Timer 2 equivalents.

  • This fixed it. Strange that micros() works fine without the fix? – Vasil Kalchev Feb 14 '18 at 5:07
  • Appeared to work. I'm sure over a longer interval you would have seen anomalies. – Nick Gammon Feb 14 '18 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.