Go Down

Topic: Triggering interrupts with 1200Hz (Read 1 time) previous topic - next topic

udoklein

Today I tried to used timer1 for triggering interrupts @20*60 Hz=1200 Hz. I followed  the datasheet "15. 16-bit Timer/Counter1 with PWM" and inferred the following code:

Code: [Select]

// disable timer1 interrupts
TIMSK1 = 0;

// Mode 4, CTC using OCR1A
TCCR1A = 1<<WGM12;

// set prescaler to 1
TCCR1B = 1<<CS10;

// Set OCR1A for running at 1200 Hz (because we have 20 discrete phases per period and want to have 60 Hz)
OCR1A = (F_CPU / (60*20)) - 1;

// enable match interrupts
TIMSK1 = 1<<OCIE1A;


however ISR(TIMER1_COMPA_vect) gets triggered to slow. Using a frequency counter it appears that the ISR triggers every 65536 or 65535 CPU cycles. That is it looks as if it gets triggered when the timer reaches the 16bit overflow.
Has anyone a hint for me on what I am missing here?
Check out my experiments http://blog.blinkenlight.net

Coding Badly


udoklein

Yes, 328P, Arduino  Duemilanove.
Check out my experiments http://blog.blinkenlight.net

Coding Badly


Excellent!  Then I may be able to help...

[font=Courier New]   // disable timer1 interrupts
   TIMSK1 = 0;
   
   // Mode 4, CTC using OCR1A
   // TCCR1A = 1<<WGM12;  // WGM12 is not located in the TCCR1A register
   TCCR1A = 0;

   // set prescaler to 1
   // TCCR1B = 1<<CS10;
   TCCR1B = (1 << WGM12) | (1<<CS10);

   // Set OCR1A for running at 1200 Hz (because we have 20 discrete phases per period and want to have 60 Hz)
   OCR1A = (F_CPU / (60*20)) - 1;  // I think you missed a division by 2...
   // (16000000 / (60 * 20)) - 1 = 13332.3333
   // F_CPU / (2 * N * (1 + OCRnA)) = frequency
   // 16000000 / (2 * 1 * (1 + 13332)) = 600.01500

   // enable match interrupts
   TIMSK1 = 1<<OCIE1A;
[/font]

udoklein

Argh. I was tricked because WGM10 and WGM11 are located in TCCR1A. Obviously I should have looked much closer at where the bits are located instead of what the bits mean. I never expected these closely related bits to be in two different registers. Now it runs @1200,04088 Hz which is 34ppm of the mark --> consistent with what I would expect.

Quote

  // Set OCR1A for running at 1200 Hz (because we have 20 discrete phases per period and want to have 60 Hz)
   OCR1A = (F_CPU / (60*20)) - 1;  // I think you missed a division by 2...


This is another pitfall in the datasheet. I did not miss a division by 2. The formula in the datasheet gives the frequency for PWM. However it does not mention why the 2 enters the formula and why this formula does not apply to CTC interrupt frequency. The point is that for PWM the counter will run twice to make up one period. However for CTC the interrupts are triggered whenever the counter hits the compare value. Thus no division by 2.

Obviously you find everything in the datasheet but sometimes the contents are not that obvious.

Thanks a lot for your help. Now everything works as desired.
Check out my experiments http://blog.blinkenlight.net

Coding Badly

Argh. I was tricked because WGM10 and WGM11 are located in TCCR1A. Obviously I should have looked much closer at where the bits are located instead of what the bits mean. I never expected these closely related bits to be in two different registers.


That's been a nagging annoyance for me as well.  It makes it impossible to atomically change the mode.

Quote
Now it runs @1200,04088 Hz which is 34ppm of the mark --> consistent with what I would expect.


Excellent!

Quote
However for CTC the interrupts are triggered whenever the counter hits the compare value. Thus no division by 2.


Oh right.  Sorry about that.

Quote
Obviously you find everything in the datasheet but sometimes the contents are not that obvious.


Yeah.  There is definitely some ambiguity in the datasheets!

Quote
Thanks a lot for your help.


You are welcome!

Go Up