Timer/counter 2

Hi every one,

I am trying to use the timer/counter 2, output A (OC2A) with the following code :

DDRD |= (1<<PB3);

// Timer 2 activation
PRR &=~(1<<PRTIM2);

// Timer/Counter2 is clocked from the I/O clock
ASSR &=~(1<<AS2);

//Set Initial Timer value
TCNT2=0;

//Place TOP timer value to Output compare register A
OCR2A=255;

// Set fast PWM mode
// and make toggle PB3/OC2A pin on compare match
TCCR2A |=(1<<COM2A1);
TCCR2A |=(1<<COM2A0);

TCCR2B |=(1<<WGM22);
TCCR2A |=(1<<WGM21)|(1<<WGM20);

// Set prescaller 1024 and start timer
TCCR2B |=(1<<CS22);
TCCR2B |=(1<<CS21);
TCCR2B |=(1<<CS20);

// OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable
TIMSK2 |=(1<<OCIE2A);

with no success. :frowning:

The oscilloscope on pin PB3 (OC2A) (arduino pin 11) shows no signal at all.

What is wrong or missing with my code ?

Thank you for your help.

DDRD?

You need to take a look at the ATmega 328 data sheet. There are significant details regarding fast PWM mode.

From 15.7.3 Fast PWM mode.

The extreme values for the OCR2A Register represent special cases when generating a PWM
waveform output in the fast PWM mode. If the OCR2A is set equal to BOTTOM, the output will
be a narrow spike for each MAX+1 timer clock cycle. Setting the OCR2A equal to MAX will result
in a constantly high or low output (depending on the polarity of the output set by the COM2A1:0
bits.)

Correction :

// Port D Data Direction Register
DDRD |= (1<<PD6);

// Port B Data Direction Register
DDRB |= (1<<PB3);

But it still doesn’t work. :frowning:

Correction :

//Place TOP timer value to Output compare register A
OCR2A=111;

But still doesn’t work :frowning:

I think because you are using mode 8(sets WGM22,WGM21,WGM20) which sets fast pwm to OCR2A you still have the problem with any value of OCR2A as OCR2A is still TOP.

If you use mode 3(set WGM20 and WGM21)which sets fast pwm to 255 you should be able to get compare with OCR2A as long as it is not 255.

Correction :

TCCR2B &=~(1<<WGM22);
TCCR2A |=(1<<WGM21)|(1<<WGM20);

Fast PWM (mode 3).

I still get no signal on pin PB3. :frowning:

There is a problem when you enable the compare match interrupt, but do not have an ISR. Since you are toggling the pin with the hardware output, you do not need the compare match interrupt.

The following code puts a 62 HZ output on Pin 11 at 50% duty cycle.

void setup() {

  DDRB |= (1 << PB3); //pin 11 COM2A output

  // Timer 2 activation
  PRR &= ~(1 << PRTIM2);

  // Timer/Counter2 is clocked from the I/O clock
  ASSR &= ~(1 << AS2);

  //Set Initial Timer value
  TCNT2 = 0;

  // Output compare register A value
  OCR2A = 127;

  //Set on compare match, clear on bottom inverting mode
  TCCR2A |= (1 << COM2A1);
  TCCR2A |= (1 << COM2A0);

  //Set fast PWM mode 3 TOP = 255
  TCCR2A |= (1 << WGM21) | (1 << WGM20); //fast pwm to 255

  // Set prescaller 1024 and start timer
  TCCR2B |= (1 << CS22);
  TCCR2B |= (1 << CS21);
  TCCR2B |= (1 << CS20);

  // OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable
  
   //TIMSK2 |=(1<<OCIE2A);

}

void loop() {}

What is confusing to me, and I don’t understand the exact reason, when you do have the Match A Interrupt
enabled with out the ISR, but you do not set TCNT2 = 0 the code also runs.

Your code works perfectly :slight_smile:

But I don't understand what was wrong with mine. :frowning:

Thank you very much for your help !

But I don’t understand what was wrong with mine. :frowning:

You enabled the Match A Interrupt but did not have a matching interrupt vector. It’s actually not needed when you use the hardware outputs with the COM2A1:0 bits set.

ISR(TIMER2_COMPA_vect) {}
OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable  
 TIMSK2 |=(1<<OCIE2A);
ISR(TIMER2_COMPA_vect) {}

void setup() {

  DDRB |= (1 << PB3); //pin 11 COM1A output

  // Timer 2 activation
  PRR &= ~(1 << PRTIM2);

  // Timer/Counter2 is clocked from the I/O clock
  ASSR &= ~(1 << AS2);

  //Set Initial Timer value
  TCNT2 = 0;

  // Output compare register A value
  OCR2A = 127;

  //Set on compare match, clear on bottom inverting mode
  TCCR2A |= (1 << COM2A1);
  TCCR2A |= (1 << COM2A0);

  //Set fast PWM mode 3 TOP = 255
  TCCR2A |= (1 << WGM21) | (1 << WGM20); //fast pwm to 255

  // Set prescaller 1024 and start timer
  TCCR2B |= (1 << CS22);
  TCCR2B |= (1 << CS21);
  TCCR2B |= (1 << CS20);

  //OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable
  TIMSK2 |= (1 << OCIE2A);

}

void loop() {}

Thank you again for your help.