Pages: [1]   Go Down
Author Topic: Timer 1 on ATtiny25/45/85 (CTC mode)  (Read 750 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 2
Posts: 85
(╯°□°)╯︵ ┻━┻
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm currently trying to make a simple ISR that counts how many seconds have passed. I have to use Timer1 because Timer0 is used for PWM on my project and I can't swap pins that easily. For some reason Timer1 on the ATtinyX5 chips is really weird. This is my implementation but it doesn't work and I can't figure why. Has anyone experience on this?

The system is running at 16.5MHz (with V-USB -- disabled it for testing just in case). I used http://www.et06.dk/atmega_timers/ to calculate timer values.

Code:
DDRB |= (1 << PB0); // output
PORTB |= (1 << PB0); // high

OCR1A = 64453;            // compare match register
TCCR1 |= (1 << CTC1);   // CTC mode
TCCR1 |= (1 << CS13);    // 256 prescaler
TCCR1 |= (1 << CS10);    // 256 prescaler
TIMSK |= (1 << OCIE1A);

Code:
ISR(TIM1_COMPA_vect) { // also tried TIMER1_COMPA_vect
  PORTB ^= (1 << PB0);
}

Thanks!
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13044
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Core?
Logged

Offline Offline
God Member
*****
Karma: 25
Posts: 529
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I believe the ATtiny25/45/85 timer1 is an 8 bit timer.  In CTC mode you don't use OCR1A as the top.  Here's what the spec sheet says:

Quote
• Bit 7 – CTC1 : Clear Timer/Counter on Compare Match
When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare
match with OCR1C register value. If the control bit is cleared, Timer/Counter1 continues counting and is unaffected
by a compare match.

Maybe you should try using OCR1C instead of OCR1A.  And use a value that is less than 256.
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 85
(╯°□°)╯︵ ┻━┻
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Core?
For this testing I'm not using a core just to be sure nothing is messing with the Timers! I'm aware some cores use Timer1 for millis() and similar functions.

I believe the ATtiny25/45/85 timer1 is an 8 bit timer.  In CTC mode you don't use OCR1A as the top.  Here's what the spec sheet says:

Quote
• Bit 7 – CTC1 : Clear Timer/Counter on Compare Match
When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare
match with OCR1C register value. If the control bit is cleared, Timer/Counter1 continues counting and is unaffected
by a compare match.

Maybe you should try using OCR1C instead of OCR1A.  And use a value that is less than 256.

Yes. You are absolutely correct! I tried various values but nothing changed. I'm trying to make the ISR run at 1s intervals.

Should I just cheat and see how the ATtiny cores handle millis() etc using Timer1 or figure it myself? smiley-razz
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4093
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The system is running at 16.5MHz (with V-USB -- disabled it for testing just in case). I used http://www.et06.dk/atmega_timers/ to calculate timer values.

I'm trying to make the ISR run at 1s intervals.

Without actually trying it, I'm not sure this is possible. The largest clock prescaler is 16384, so with a 16.5 MHz system clock and using the overflow interrupt, the slowest the ISR could run would be

16,500,000 / 16,384 / 256 = 3.934 Hz

I might not use a web page that calculates ATmega timer values for an ATtiny.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
God Member
*****
Karma: 25
Posts: 529
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, you probably can't get the hardware to call your ISR at one second intervals, but you could set up a counter in your ISR that calculates when a one second interval is, and calls your code accordingly.

I think the standard 328 core uses a FRACT calculation because it uses the standard 256 top and prescaler of 64.  That doesn't divide evenly into 16,000,000.  It's close to a millisecond, but not exact.  So they have to calculate how far off it is every time so there isn't any drift.

If all you want is one second timer, you could set up your timer interrupt with a top of 250 and a prescaler of 8.  Then you could count down to 20625 and your code would be called at exact one second intervals.
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 85
(╯°□°)╯︵ ┻━┻
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Without actually trying it, I'm not sure this is possible. The largest clock prescaler is 16384, so with a 16.5 MHz system clock and using the overflow interrupt, the slowest the ISR could run would be

16,500,000 / 16,384 / 256 = 3.934 Hz

I might not use a web page that calculates ATmega timer values for an ATtiny.

Yes you are correct.

Well, you probably can't get the hardware to call your ISR at one second intervals, but you could set up a counter in your ISR that calculates when a one second interval is, and calls your code accordingly.

I think the standard 328 core uses a FRACT calculation because it uses the standard 256 top and prescaler of 64.  That doesn't divide evenly into 16,000,000.  It's close to a millisecond, but not exact.  So they have to calculate how far off it is every time so there isn't any drift.

If all you want is one second timer, you could set up your timer interrupt with a top of 250 and a prescaler of 8.  Then you could count down to 20625 and your code would be called at exact one second intervals.

Thanks! I'll try to implement this and post results.
« Last Edit: May 31, 2013, 07:59:35 pm by Abfahrt » Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 85
(╯°□°)╯︵ ┻━┻
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If all you want is one second timer, you could set up your timer interrupt with a top of 250 and a prescaler of 8.  Then you could count down to 20625 and your code would be called at exact one second intervals.

I have setup the timer as you suggested. Prescaler 8, top 250. This is my ISR routine:
Code:
ISR(TIMER1_COMPA_vect) {
  if (counter == 0) {
counter = 20625;
PORTB ^= (1 << PB0);
  }
  counter--;
}

It seems that the LED is flashing with periods longer than ~2.5s (I'll have to get my multimeter to be sure). Can you please explain how you calculated 20625? 16500000/8 equals 2062500

EDIT: I got it! The ISR needs to count to 8250. That's 16500000/8/250! Thanks everyone smiley-mr-green
« Last Edit: May 31, 2013, 08:01:52 pm by Abfahrt » Logged

Pages: [1]   Go Up
Jump to: