AVR Timer, can't get timing right.

I’m still fairly new to avr programming and I could use a little help getting my timer to interrupt correctly. I’m would like it to fire off the timer every second but, my math is either wrong or I’m just not doing it right, any ideas would be helpful!

Here’s the info: I’m using an AVR-MT (using an ATTiny2313), the board has a 10MHz oscillator.

The stuff I read online seemed to say that this formula might work but, I’m getting about a 3 second delay, bit longer then I need. the formula: 10000000/1024 (prescaler value) == 9766

Then this: (0x000 - 9766= 55770|0xD9DA)

So here’s my code:

.equ timer_value = 0xD9DA
....
....
ldi r16, 0b10000000		; the timer 1 setup code:
	out TIMSK, r16		; enable Timer 1 overflow int in TIMSK
	ldi r16, high(timer_value)	; set timer 1 counting value
	out TCNT1H, r16						
	ldi r16, low(timer_value)			
	out TCNT1L, r16						
	ldi r16, 0b00000101	; and start timer 1 with a prescaler of 1024
	out TCCR1B, r16

Ok I don’t have a good grasp on the timer workings yet, anyone have suggestions on how I can get this thing clicking off every second?

There is actually a fair bit more code involved in setting up timers. Not sure if you omitted it from your snippit or did not include it. Some things to consider:

1- The 2313 will default to using its internal 8Mhz RC oscillator with a divide by 8 prescaler. You need to reprogram the fuse bits to make it use an external oscillator/resonator and disable the divide-by-8 prescaler (unless your board already comes programmed this way).

2- You need to setup the TCCRxB register (TCCR1B in your case since you are using timer 2). That will select the timers clock source and divisor. Presumably you are setting CS12/CS11/CS10 to 101 to use the system clock divided by 1024.

3- For what you want to do, I suggest CTC mode (clear timer on compare match). In that mode, you set the timer match in OCR1A and the timer will generate an interrupt each time the match is reached, and then will reset the timer and start over. To set CTC mode, you need to set WGM13…WGM10 to 0100. Then set TIMSK to 01000000 (OCF1A enable).

So with your 10Mhz clock enabled and a /1024 prescaler, set OCR1A to 9766 and you will get an interrupt every second. Note that if you use the interrupt to flash an LED, it will on 1 second, off 1 second (you need to run a 1/2 second cycle if you want the LED to turn on each second).

Good luck. Timers and interrupts can be trick to setup, but very cool to use (much better than loops and polling).

Here is a nice application that will help you set up the timer. (or at least check if you did it correctly)

http://www.b9.com/elect/avr/kavrcalc/

Also: have you tried running the code in avr studio using the simulator?

I always check timing with the simulator, its really easy.

Good Luck

Hey Vraz,

Thanks so much for the guidance. I am breaking out the 2313 docs and reading up on the timers. One thing I haven’t figured out yet is on number 1, overriding the default prescaler. I think from the looks of the board [url =http://www.sparkfun.com/datasheets/AVR/avr-mt-b-sch.gif]schematic that it has been overridden to use the 10MHz oc, though I’m not sure. The 10MHz is tied tot he XTAL1 and XTAL2 and though the datasheet says that you connect the T0,T1 pins to the external oscillator it really isn’t clear if its referring to the same thing.

I don’t really mind going at 8MHz over 10 the datasheet seems to imply that the internal is better but, eh whatever. I do however need to make sure that prescaler default is being overridden since at 10MHx or 8 the number is huge at a prescale of 8. Anyway my question is, am I overriding the prescaler default by setting CS12:0 to 101? How can I tell?

I think if I can get that part clear then switching to the CTC approach wont be a problem. Thanks again for the help, I feel like I’m on track to getting this thing right. Interrupts are great, I don’t find them to be too difficult as its actually easier then coding interrupts in onther high level languages, not timers on the other hand… well lets just say us high level coders have it easy there! :lol:

Oh hey thanks for the link! Looks like that might come in handy for a little validation.

newbie123:
Here is a nice application that will help you set up the timer. (or at least check if you did it correctly)

http://www.b9.com/elect/avr/kavrcalc/

Also: have you tried running the code in avr studio using the simulator?

I always check timing with the simulator, its really easy.

Good Luck

I think from the looks of the board that it has been overridden to use the 10MHz oc, though I’m not sure. The 10MHz is tied tot he XTAL1 and XTAL2 and though the datasheet says that you connect the T0,T1 pins to the external oscillator it really isn’t clear if its referring to the same thing.

So the timer itself can accept either an extern clock signal from T0/T1 or use the system clock. The system clock can also come from multiple sources including the three different internal RC oscillators (128Khz, 4Mhz, 8Mhz) or external crystal/resonator (10Mhz on your board). Your programming software will use "fuse bits" to select where the system clock comes from while the CS12-CS10 bits in TCCRxB control where the timer input comes from.

As a simple starting point, I suggest something like the following:

 ldi r16,5
 out TCCR1B,r16 ; timer1 driven by system clock / 1024
Loop:
 in r16, TCNT1H ; get high byte of timer count
 bst r16,7 ; bit 7 toggles every 128*256*1024 timer ticks
 in r16,PORTD ; 
 bld r16,3 ; I assumed the relay/LED as an indicator
 out PORTD,r16
 rjmp Loop

The LED will blink at some rate. Use a stopwatch to determine the period. Then you can work backwards to determine what speed the system clock is running at. (10Mhz should be on for approx 3.3 seconds, off for 3.3 seconds; 8 Mhz should be on/off 4.2 secs; 1 Mhz should be on/off 33 secs). If its not 10Mhz, look up the fuse bit settings and get than enabled. Once you know what frequency your system clock is at, working with the timer will be easier.

Hey just thought I would post an update on my timer issue. I dug through the 2313 datasheet looking at “fuse bit” related info and it seems that the 2313 is shipped using the internal 8Mhz Oscillator. That wouldn’t explain my issue with the timing being so far off but it also has a default prescaller of 8 which results in a system clock of 1Mhz! Yea that would explain why its so slow.

I wonder two things, why would you ever want such a slow clock? The other is it seems to imply that a fuse bit controls the default prescaller which would explain why my code wouldn’t improve things. What I can’t seem to figure out is what controls the prescaller in the fuse bits or could it be that when using the internal oscillator are you simply stuck with the prescaller setting?

I dug through the 2313 datasheet looking at “fuse bit” related info and it seems that the 2313 is shipped using the internal 8Mhz Oscillator.

Yes, hence my original reply to that effect. However, when you purchase a complete board, the manufacturer will sometimes download a demo program and/or update the fuse settings. Did you use your programmer to query the fuse bits or use the testing program I outlined to find out how the controller is actually programmed?

I wonder two things, why would you ever want such a slow clock?

The part ships at 1Mhz because it is guaranteed to operate at all voltage settings at that speed. Higher speed such as 8Mhz only work at the higher voltage levels. So they ship the chip is a configuration that always works with the expectation that you will reprogram it for your needs.

The CLKDV8 fuse bit (divide by 8 ) actually provides the default value for the CLKPR clock divisor register. Why would you want to set the division in software? To slow down the chip and conserve power. In a battery operated application, running the clip slowly can save lots of power.