Electronic – arduino – Toggle OC1A, OC1B and OC1C using timer in CTC mode

arduinoavrinterruptstimer

Most AVR microcontrollers got three dedicated pins for each timer (for example, OC1A, OC1B, and OC1C) that can be toggled automatically when the counter reaches the so called top value in the corresponding three registers (OCR1A, OCR1B, and OCR1C).

I'm not sure how can those three dedicated pins/registers operate in CTC mode for different independent top values, and this is what I want to accomplish. I want to toggle OC1A, OC1B and OC1C (though "output compare", not through interrupt or something like that) at different intervals (to see the having three dedicated registers and pins).

Let's say I want to program the AVR timer to toggle the pins OC1A, OC1B and OC1C at different intervals (for example 1 second, half second, quarter a second), but it does not work as I expect. I set compare match register A and B and C with the three different value, having the greatest value on A (I also tried having it on C).

Only OC1A is toggled at the needed frequency.

To me it seems that if they made only OC1A top clears the counter then it would be possible to have the three pins work at different three independent values. Is this right?

Here is the segment I put in my Arduino Lenoardo's (based on ATmega32U4) setup. I left loop() empty.

  // Initialize timer1
  noInterrupts();           // Disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1C = 0;
  TCNT1  = 0;

  OCR1A = 62500;            // Compare match register 16 MHz/256/1 Hz
  OCR1B = 31250;            // Compare match register 16 MHz/256/2 Hz
  OCR1C = 15625;            // compare match register 16 MHz/256/4 Hz

  // Toggle OC1A, OC1B and OC1C => (on Lenoardo) PB5, PB6 and PB7 => digital 9, 10, 11
  // TCCR1A = 0b01010100;
  TCCR1A |= (1 << COM1C0) | (1 << COM1B0) | (1 << COM1A0);
  // TCCR1B = 0b1100
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler

  interrupts();             // Enable all interrupts

Best Answer

A timer in normal, Fast PWM, or CTC mode counts directly from BOTTOM to TOP if no external influence is applied. As it passes each OC value it emits an interrupt and/or frobs a pin, as it is configured to do. Each OC value is only crossed once, which means that all OCs for the same timer all run at the same frequency.

They can be configured to have different phases or to operate in differential pairs based on the values of OCRnr and the COMnrb bits, but the only way to directly have them use different frequencies is to manipulate their OCR values each time their ISR is invoked.

The easiest way to have the pins change at different frequencies would be to set the timer to the GCF/LCM of the various periods/frequencies desired, maintain a count of cycles elapsed, and then frob the pins when the appropriate number of cycles have passed.