Pages: [1]   Go Down
Author Topic: understanding timer interrupts  (Read 931 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi everyone,

I'm trying to port over some code to the Due, and I'm having trouble understanding the section that deals with ISR and timer/counters - more specifically, I'm unsure exactly with which settings the timer is being initialized.  I'm looking at the following:

Code:
  TCCR1A = 0;
  TCCR1B = _BV(WGM13);

  ICR1 = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins
  TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  TIMSK1 = _BV(TOIE1);
  TCCR1B |= _BV(CS10);

I plan on using the following timer library on the due in order to handle timer ISR, however I'm uncertain about how the original timer is setup.  Could someone please shed some light into this?  I'm afraid I still don't quite understand bit math so I can't tell to which value each of the register values is being set.  I was hoping someone could simply tell me to what frequency the timer is set as well as which mode.

Furthermore, I don't understand how ICR1 works in this case since from the rest of the code, I understand that once timer1 overflows an ISR is called because the code contains
Code:
ISR(TIMERx_OVF_vect)
there is no mention of the timer input capture interrupt service routine within the original code.

Thanks for the help and enlightenment everyone!



Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is from the Atmega328, right?

This line doesn't seem to me to do anything useful:

Code:
  TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));

So we can ignore that.



This seems to turn on mode 8: PWM, phase correct, top at ICR1:

Code:
  TCCR1B = _BV(WGM13);



Code:
  TIMSK1 = _BV(TOIE1);

You get an interrupt on Timer 1 overflow (TIMER1_OVF_vect).



This won't do anything:

Code:
ISR(TIMERx_OVF_vect) 



Start the timer with no prescaler:

Code:
  TCCR1B |= _BV(CS10);



Code:
  ICR1 = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins

Assuming F_CPU is 16000000 it will count up to 4 * TIME_CHUNK.
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Assuming F_CPU is 16000000 it will count up to 4 * TIME_CHUNK.

Plus 1, because the count is zero-relative.
Logged


Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are the Mega328P register names going to work on the Due?
Will they work the same way?

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think he just wants to understand what the original is doing, so he can plug the correct values into the Due library.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think he just wants to understand what the original is doing, so he can plug the correct values into the Due library.

That's correct. 

I'm understanding (please correct if wrong) that timer1 is simply setup to interrupt on overflow.  Is it correct to assume that the timer overflows every
Code:
(F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins
?

So, using the Due timer/interrupt library I could simply do:
Code:
long freq = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins
startTimer1(freq, interruptRoutine); // (Frequency, function)

where interruptRoutine is the function that is called upon timer overflow?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it correct to assume that the timer overflows every ...

Yes, plus 1.

If the number happens to be 50, it will count 51 times because it includes zero.

Quote
So, using the Due timer/interrupt library I could simply do: ...

I haven't used the Due yet, but in principle that looks OK.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it correct to assume that the timer overflows every ...

Yes, plus 1.

If the number happens to be 50, it will count 51 times because it includes zero.

Quote
So, using the Due timer/interrupt library I could simply do: ...

I haven't used the Due yet, but in principle that looks OK.

Hi Nick!

thanks for the speedy replies and help, I'll get to some testing this week and post back if I'm having any difficulty!
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is a phase and frequency correct PWM mode, so the counter will count to N, turn around and count back down to 0.  It will then call the overflow ISR.  It doesn't seem to be doing anything other than using ICR1 to set the TOP value (probably because it is double buffered).  So if N is 50, it will generate an overflow every 100 counts.

For example:  If ICR1 was set to 3, the TCNT1 register progression would be to start at 0, 1, 2, 3, 2, 1, 0, 1, 2,....  Since it started at 0, three ticks to get to the TOP and three ticks to get back to 0.

I assume that the overflow ISR is doing something with toggling pins based upon the comments.
Logged

Experience, it's what you get when you were expecting something else.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

In the original the ISR didn't do anything at all because it was misnamed:

Code:
ISR(TIMERx_OVF_vect)
Logged


texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the original the ISR didn't do anything at all because it was misnamed:

Code:
ISR(TIMERx_OVF_vect)

I saw that too, but I figured since the OP wasn't asking for help with mysterious resets, that the real program must have it correctly spelled out somewhere.  smiley-wink  But yeah, any routine named exactly the way the OP showed isn't being called by the interrupt processor.
Logged

Experience, it's what you get when you were expecting something else.

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I assume that the overflow ISR is doing something with toggling pins based upon the comments.

Yep, you assumed correctly. The code is used to drive a stepper motor which needs an alternating HIGH/LOW sequence of pin actuation.

In the original the ISR didn't do anything at all because it was misnamed:

Code:
ISR(TIMERx_OVF_vect)

Yep, it was misnamed, must have happened while I was doing some reading on TIMERx, the correct version should be:
Code:
ISR(TIMER1_OVF_vect)
Logged

Pages: [1]   Go Up
Jump to: