1
\$\begingroup\$

I am trying to use Timer1 on the ATtiny85 (Adafruit Trinket) to blink an LED every second. The prescaler value is 1024, and the compare register value is 28. I loop through this 279 times to get a delay of 1 second.

$$\frac{1024\ . 28\ . 279}{8\ .10^6}\simeq1$$

With the code below I get something like 8.5 seconds. I set -mmcu=attiny85 and -DF_CPU=8000000UL when compiling. What could I be missing.

#include <stdint.h>
#include <avr/interrupt.h>

#define TIMER_OVERFLOW_COUNT 279

volatile uint16_t timerCount = TIMER_OVERFLOW_COUNT;
ISR(TIMER1_OVF_vect)
{
    timerCount++;
}

int main(void)
{
    DDRB = 1 << DDB1;
    OCR1C = 28;
    TIMSK = 1 << TOIE1;
    sei();
    TCCR1 = (1 << CS13) | (1 << CS11) | (1 << CS10);
    while( 1)
    {
        if( timerCount >= TIMER_OVERFLOW_COUNT)
        {
            timerCount = 0;
            PORTB ^= 1 << PORTB1;
        }
    }
    return 0;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Updating the timerCount in both interrupt handler and the loop is a bad idea. You have a race condition here. Why not put all of the logic in the handler? It's not that heavy. \$\endgroup\$ – Eugene Sh. Aug 30 '16 at 14:42
  • \$\begingroup\$ @EugeneSh. while true, I find it hard to believe it happens all the time on a system which has a much higher frequency than the interrupt frequency. Disabling the interrupts before and enabling after the change in the main function is still a good idea... I don't like the arcane magic to set the frequency with a compiler option though - is it really running at 8 MHz? Are there prescalers for peripherals in the ATTiny85? \$\endgroup\$ – Arsenal Aug 30 '16 at 14:46
  • 2
    \$\begingroup\$ Wait. You don't want to interrupt on overflow, you want to interrupt on compare match \$\endgroup\$ – Eugene Sh. Aug 30 '16 at 14:56
  • 1
    \$\begingroup\$ @SubaThomas I am right for sure. But the way to do it should be described in the datasheet an demonstrated in some tutorials around. \$\endgroup\$ – Eugene Sh. Aug 30 '16 at 15:17
  • 1
    \$\begingroup\$ @EugeneSh and Bence Kaulics, thanks for your help. I read the datasheet with a bit more care and found this: "In the normal mode an overflow interrupt (TOV1) is generated when Timer/Counter1 counts from $FF to $00..." Essentially the compare match option is not available in the normal mode. I changed TIMER_OVERFLOW_COUNT to 31 and set OCR1C to 255 (which is really superfluous) and things work as expected. \$\endgroup\$ – Suba Thomas Aug 30 '16 at 16:51
1
\$\begingroup\$

The CKDIV8 fuse is programmed on devices fresh from the factory. If you forget to unprogram this fuse then the device will run at 1/8 the expected clock speed.

\$\endgroup\$

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.