1

I'm trying to gain an understanding of the Arduino timer and interrupts, particularly the CTC-modes 4 and 12. I wrote a small example in which I generate interrupts while the mainloop sleeps for 1 second and the display how many interrupts occured. It can toggle between mode 4 and 12 with the #if 1.

This works fine for mode 12 ( 50 interrupts/sec ) but in mode 4 it gives -12k interrupts / seconds... unless when I set OCR1A to 39999 again inside the ISR then it does give the expected 50 interrupts/sec, but I'd like to know why.

I think my confusion might be related to not understanding the table-header explaining the modes where it says "Update of OCR1x at". What is meant with that ( who updates it, and to what value? or do I need to update it in the ISR ) ? Why would OCR1x be updated in mode 12 ( the table seems to state that it is) ? And it seems to work, even if I don't update it...?

Also, the only difference between mode 4 and 12 seems to be the register used for comparing to the timervalue (OCR1A vs ICR1)... but what is so fundamentally different between those? Why are there 2 options and what is the argument to choose for either mode 4 or 12 ?

Update: The issue seems to be related to initialization-order. If OCR1A is set to 39999 at the current location it gets reset to 0 a few lines further. When moving it after TCCR1A = TCCR1B = 0; then OCR1A keeps the value. So it's not necessary to set it on every interrupt. This also explains why we get -12k counts on mode 4 (because we are comparing OCR1A in that mode, comparing to 0 and generating loads of interrupts)...

Any insight into why the initialization-order matters in this case would be appreciated.

Thanks in advance! Arduino Datasheet Table 20-6

volatile int isr1 = 0;

ISR(TIMER1_COMPA_vect)
{
  // this is called every time our timer-compare matches to ICR1 or OCR1A
  isr1++;

  // when using the #if part below, we need to do this, or we end up with weird values for isr1 ( around -12.000 )
  // If we set it to the original value then we get 50 interrupts per second... 
  OCR1A= 39999;       
}

void setup() {

  Serial.begin(115200);
  delay(50);

  ICR1 = 39999;                   // 50Hz signal @ 16MHz clock
  OCR1A= 39999;

//TIMSK1 |= 1 << ICIE;            // bit 5: Input Capture Interrupt Enable (execute interrupt when TIFR1.ICF flag is set)  
  TIMSK1 |= 1 << OCIE1A;          // bit 4 : Enable the Timer-Output-CompareA-Match Interrupt 

  TCCR1A = TCCR1B = 0;            // reset timer-config flags
   // An interrupt can be generated at each time the counter value reaches the TOP value by either using the OCF1A or ICF1 Flag, 
   // depending on the actual CTC mode. If the interrupt is enabled, the interrupt handler routine can be used for updating the TOP value.
#if 1
  // Arduino Datasheet 20.12.2. : The counter value (TCNT1) increases until a compare match occurs with OCR1A, and then TCNT1 is cleared.
  TCCR1B |= 1<<WGM12;             // code 4 (CTC, compare with OCR1A, Immediate update of OCR1x, overflow on MAX)
#else
  // Arduino Datasheet 20.12.2. : The counter value (TCNT1) increases until a compare match occurs with ICR1, and then TCNT1 is cleared.
  TCCR1B |= 1<<WGM13 | 1<<WGM12;  // code 12 (CTC, compare with ICR1, Immediate update of OCR1x(?), overflow on MAX)
#endif

  // using a prescaler of 8, which "slows down" the clockticks by factor 8.
  // 1 clocktick takes 0.5 microseconds, so 39999 clockticks need 19999,5 microseconds
  // 1 second = 1.000.000 microseconds, so we get 50 interrupts per second
  TCCR1B |= 1<<CS11;   // timer CS11 = clki/o/8, 1 tick per 0.5 microseconds
}


void loop() 
{
  delay(1000);            // wait 1 second
  Serial.println(isr1);   // print how many interrupts we had in that second
  isr1 = 0;               // and reset for the next second.  
} 
1

As described in the operation part of the datasheet section, OC1x is double-buffered; the code sets a shadow buffer to a given value and then at some point the hardware copies the shadow buffer to the register that controls operation. "Immediate" means that the buffer is completely transparent since the value is copied immediately.

The difference between modes 4 and 12 is that mode 4 allows the use of ICP1 for input capture and mode 12 allows the use of OC1A for waveform generation.

  • Thanks you for your reply but it's still not entirely clear to me. Mode 4 compares to OCR1A, mode 12 to ICR1. Printing "OCR1A" to serial output every loop, OCR1A is set to 0 ( for both mode 4 and 12), even though it was initialize to 39999. That would explain why in mode 4 ( using OCR1A for comparison) it results in -12423. The timer compares with 0 and basically instantly has a hit and triggers the next interrupt, overflowing isr1. But why/where is OCR1A being set to zero. I can't find a description of that behaviour in the datasheet. – kalmiya Jul 30 '17 at 18:01
  • Which device are you using? – Ignacio Vazquez-Abrams Jul 30 '17 at 18:07
  • An Arduino-Uno (chinese) – kalmiya Jul 30 '17 at 18:11
  • So an ATmega328P? – Ignacio Vazquez-Abrams Jul 30 '17 at 18:11
  • When uploading: "avrdude: Device signature = 0x1e950f (probably m328p)", so yes... ah it also says " AVR Part: ATmega328P" – kalmiya Jul 30 '17 at 18:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.