Electronic – Calculate exact timer frequency for ATTiny

attinyavrinterruptstimer

Trying to wrap my head around these overflow timers for the ATTinyx5 (45 in this particular case). I seemed to have a great handle on it with the ATMega328 but I cannot get it to work the way I want on the tiny chips.

I'm trying to achieve a 1 second pulse (for the purposes of testing, LED on for 1s then off for 1s). I know there are many ways to achieve this, but the simplest seem to be by utilizing the overflow ISR. Here's what I've got so far:

//Who can ever remember what the prescaler combinations are?
//These are for Timer0
#define PRESCALE0_1 _BV(CS00)
#define PRESCALE0_8 _BV(CS01)
#define PRESCALE0_64 (_BV(CS00) | _BV(CS01))
#define PRESCALE0_256 _BV(CS02)
#define PRESCALE0_1024 (_BV(CS02) | _BV(CS00))

void setup()
{
  DDRB |= _BV(PINB0); // Set Pin 5 (PB0) as output;
  PORTB &= ~_BV(PINB0); //Set it to low, just to be safe

  cli();
  TIMSK |= _BV(TOIE0);
  TCCR0B |= PRESCALE0_64;
  sei();

}

uint8_t _interval = 2;
uint16_t _pulseCount = 0;
uint16_t _pulseMax = 15625; // = 1s / 0.000064s
bool state = false;

ISR(TIM0_OVF_vect) 
{ 
  _pulseCount++;
  if(_pulseCount >= _pulseMax)
  {
    _pulseCount = 0;

    if(!state)
    {
      PORTB |= _BV(PINB0);
      state = true;
    }
    else
    {
      PORTB &= ~_BV(PINB0);
      state = false;
    }
  }
} 

As you can see, I'm doing little more than enabling the Timer0 overflow ISR and setting the prescaler to 8. Now, I'm running the chip at 1Mhz by setting the /8 clock fuse.

Given that 1 / (F_CPU / 64) = 0.000064 or 64 uS that should mean that 1/0.000064 = 15625 overflows per second. So, the general plan was to count overflows in a uint16_t variable util it reached 15625 and then do what I needed to do at 1 second. Sort of an overflow for the overflow.

But instead, I get a pulse every couple of minutes!. To get the pulse I need I have to set _pulseMax to more like 128 which should be 0.000064s * 128 = ~8ms.

I'm sure whatever I'm doing is terribly stupid, but I can't see it. What am I doing wrong here?

Best Answer

I don't use AVRs (I use PICs, but the basic peripherals are much the same), but I imagine the timer register is 8-bit, and the basic setting is to trigger an interrupt on an overflow.
So unless I've missed something (very possible, been up all night :-)) I think you are out by a factor of 256, since you don't appear to have allowed for this.

If your clock is 1MHz, and the prescaler is 64, then the overflow should occur every:

1 / (1e6 / 64 / 256) = 16.3ms.

If you multiply this by the 128, you get ~2 seconds.