Weird Timer Behavior ATtiny104 Xplained Nano

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My application is using Timer/Counter0, Overflow Interrups to toggle the LED. The interrupt service routine at 0x005 does toggle the LED and reloads the counter repetitively at 1 sec intervals. The problem is with the very first  interrupt which occurs at  approx. 63 secs instead of 1 sec.  The following code sets up the timer and interrupts:

 

;        setup timer
    ldi    r16, 0x81            ;sync timer & reset prescaler
    out    GTCCR, r16        ;hold timer during config, TSM & PSR
    ldi    r16, 0x05            ;prescaler = 1024 (8Mhz / 1024)
    out    TCCR0B, r16        ;sets timer clk rate = 8MHz/1024=7812Hz

;
;  timer counts up from 0; overflows in 65535/7812 = 8.4 secs
;  to trip overflo in 1 sec, start timer at 
;  65535-7812/8.4 = [65535-930] = [0xFFFF-0x3A2] = 0xFC5D

;
    ldi    r16, 0x5D            ;load timer start count
    out    TCNT0L, r16       ;counter low byte
    ldi    r16, 0xFC            ;counter high byte
    out    TCNT0H, r16        ;counter now loaded
    ldi    r16, 1                  ;TOV0 bit
    out     TIFR0, r16         ;clear TOV0 bit
    ldi    r16, 1                  ;timer mask reg, TOIE0 bit
    out     TIMSK0, r16       ;enable Timer/Counter0 Overflow interrupts
    ldi    r16, 1                  ;PSR bit =1, TM bit = 0
    out    GTCCR, r16        ;clr TM bit to start timer
    sei                              ;enable global interrupts 

 

The exact same code except these 2 lines:

 

    ldi    r16, 0x05             ;prescaler = 1024 (8Mhz / 1024)
    out    TCCR0B, r16        ;sets timer clk rate = 8MHz/1024=7812Hz

 

is repeated in the interrupt service routine which works correctly. For 63 secs, I calculate that the counter must start at [65535 - 63 x 7812/8.4] = [65535 - 58590] = 0x1B21 instead of 0xFC5D

If I do load the counter with that value, the first interrupt occurs at 2 x 63 secs! The only explanation is that the timer somehow adds an extra 63 secs. Loading the counter just a few counts below 65535 results in the first interrupt occurring at 63 secs.

Skier

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When you write TCNT0H it doesn't go directly to the register, it goes to a TEMP register. When you write TCNT0L, TEMP is written to the real TCNT0H register. So on the first pass, TCNT0L gets 0x5D, but TCNT0H gets the uninitialized value from TEMP. Subsequent passes get the correct value for TCNT0H since it was written to TEMP on the previous pass.

 

TL;DR: Swap the order you write TCNT0L & TCNT0H.

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This solution required intimate knowledge of the Assembler which I don't have. Many thanks. 

SKIER

Skier

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    ldi    r16, 0x05            ;prescaler = 1024 (8Mhz / 1024)
    out    TCCR0B, r16        ;sets timer clk rate = 8MHz/1024=7812Hz

As soon as the CS bits are written the timer starts to count. So this is the LAST thing you probably want to do not the first! Do it just before the SEI.

 

Also if you ever find yourself loading specific values into TCNT, esp in an ISR, then you are almost certainly using the wrong mode and probably want to be using CTC (Clear Timer on Compare) mode.