Timer2 ctc mode problem

Good day everyone!
I'm facing a problem while I'm trying to set the ATmeag8a TIMER2 in CTC mode, the problem is when I'm giving OCR2 some value it doesn't affect the TIMER2, the timer doesn't give me the result I want,
I set fuses to internal 8MHZ oscillator
and I'm using external 32.768Khz crystal and this code:

void setup() {
  cli();
  ASSR = 0x08; // set clockSource to external crystal
  TCNT2 = 0;
  OCR2 = 32; // compare register
  TCCR2 = 0b10001111; // CTC, no port output, 1024 prescaler
  while ((ASSR & 0x07)); // Wait until updating of the Above 3 register completes
  sei();
  TIMSK |= (1 << OCIE2); // activate compare match interrupt.
  pinMode(13,OUTPUT);
}

volatile bool a;
ISR(TIMER2_COMP_vect) {
  a=!a;
}

void loop{
   digitalWrite(13,a);
}

What I expect is to toggle the LED on 13 pin every exactly 1 second, what I get is a very speed flashing LED,
but if add this inside the ISR:

OCR2=32;

it gives me what I want but freezes for a second every approximately 5 minutes,
I read in datasheet and internet and found some examples they set OCR2 value only in the setup{}
why it doesn't work with me, what should I do ?
why OCR2 forgets its value ? or there is another issue ?

If it doesn't work, make it simpler! Use the default clock and a LED on the timer output pin.

1 Like

I've tried, same result. my question is why OCR2 forgets its value

What if you initialize OCR2 after all other timer registers?

I tried, it didn't work.
please check this example to see how the do it, all examples say same thing and it doesn't work with me

It's for T0, possibly different for T2!
Which controller do you use?

I know, they are same. and i checked datasheet to set the registers correctly
my controller is ATmega8a

Try this sketch (your one slightly modified)

volatile bool flag = false;

void setup() 
{
  cli();
  ASSR = 0x08; // set clockSource to external crystal
  TCNT2 = 0;
  OCR2 = 32; // compare register
  TCCR2 = 0b10001111; // CTC, no port output, 1024 prescaler
  while ((ASSR & 0x07)); // Wait until updating of the Above 3 register completes
  sei();
  TIMSK |= (1 << OCIE2); // activate compare match interrupt.
  pinMode(13,OUTPUT);
}

void loop
{
   if(flag == true)
   {
       digitalWrite(13, !digitalRead(13));
       flag = false;
   }
}

ISR(TIMER2_COMP_vect) 
{
   flag = true;
}

didn't work :frowning: ,, very speed flashing LED.. same as what I was getting

How that? 32kHz and a prescaler of 1024 yields about 1kHz, and OCR of 32 yields 1/32 kHz or about 33 Hz and a blink rate of 16 Hz. Isn't this what you really get?

Ooops, sorry for that crap :frowning:

oscillator freq. / prescaler = output timer frequencey
32768 / 1024 = 32Hz
so if I set OCR2=32 I should get 1Hz flashing LED
is that right ?
anyway, if I set OCR2 = 1 or OCR2= 200 nothing changes
the led flashes at same speed (as I see)

I would say -- yes, it is right! Then where is the problem?

37.768 kHz/1024 = 32 Hz

The driving clock for TCCR2 (clkTc2) is : 32 Hz, which means that the TCNT2 will count 32 clock pulses in 1-sec. If OCR2 is loaded with 32, then the COMP flag (OCF2) will set 1-sec point which can be used to interrupt the MCU. The timing is shown below (Fig-1):

ctcMode2
Figure-1:

2. Kindly, re-arrange your setup codes as follows and re-run the sketch. You should not start TC2 until initialization is done.

void setup() 
{
  pinMode(13, OUTPUT);
  TCCR2 = 0x00
  ASSR = 0x08; // set clockSource to external crystal
  TCNT2 = 0;
  TCCR2 |= bit(WGM21);
  OCR2 = 32; // compare register
  TIMSK |= (1 << OCIE2); // activate compare match interrupt.
  TCCR2 |= bit(CS22)|bit(CS21)|bit(CS20);
}

3. Is Clock Prescaler applicable when the TC2 is operated directly by external asynchronous clock?

1 Like

One possibility is that the registers are busy when you update them. I would check the busy flags after setting AS2 and before writing to the registers:

  ASSR = 0x08; // set clockSource to external crystal
  while (ASSR & 0x07);  // Wait until the registers are not updating.
  TCNT2 = 0;
  OCR2 = 32; // compare register
  TCCR2 = 0b10001111; // CTC, no port output, 1024 prescaler
  while (ASSR & 0x07); // Wait until updating of the Above 3 register completes

I would NOT set the Force Output Compare bit in TCCR2:
TCCR2 = 0b00001111; // CTC, no port output, 1024 prescaler

Note: You should set OCR2 to 31 to get 32 counts.

That's all I can suggest for now.

Do you have an oscilloscope you could use to check the clock frequency?

Note: If the 8 MHz clock is leaking through you'll get about 244 Hz interrupt (instead of 1 Hz) for an output frequency of 122 Hz (two octaves below middle B).

Needs clarification as to why the OCR2 register should be loaded with 31 and not 32 for the OCF2 flag to get set at every 1-sec interval in CTC-2 mode operation of TC2 of ATmega8A MCU.

If we solve the following equation, then it comes 31--

f = 32768/(2*N*(1+OCR2))
==> 0.5 = 32768/(2*1024*(1+OCR2)) //period = 2 sec; so f = 0.5 Hz
==> 1+OCR2 =  32768/(2*1024*0.5)
==> OCR2 = 32 -1 = 31

But, how to understand it physically?

The counter starts at zero and counts up to and including TOP. The first state is zero, the second one is 1, and the N-th state is N-1. For 32 states the last one is 31, followed by 0.

1. Initially, TCNT2 contains 0. After that and at the very first start, the TCNT2 must count 32 pulses (RE, HIGH, FE or LOW) to spend 1-sec time -- is this correct?

2. If Step-1 is correct, then OCR2 must be loaded with 32 to make an equality comparison at 1-sec -- is this correct?

3. At the equality point, the TCNT2 goes to BOTTOM (due to CTC Mode) and this transition from TOP to BOTTOM requires 1 clock pulse -- is this correct?

4. So, excluding the beginning compare phase, the remaining compare phases does include this transition time: 1x1/32-sec

5. Therefore, at steady-state operation, the OCR2 must be loaded with 31 which being added with the transition clock gives 32.

6. My stand is: the count should be 32 to measure 1-sec time when the driving clock for TCN2 is 32.768 kHz/1024. For steady-state operation, OCR2 should be loaded with 31 for the reason described in Step-5.

Wow! that worked :slight_smile:
Thank you very much and thank you all my friends!!
as you're saying OCR2 should be 31 not 32
I can sleep well now

1 Like

The main problem that I was setting FOC2 bit in TCCR2 while it should be disabled as @GolamMostafa said
I set it to 0 and it worked fine

1 Like

Apart from FOC2-bit, have you verified that the order of placement of the following line is important for the sketch to work?

TCCR2 |= bit(CS22)|bit(CS21)|bit(CS20);

I set it before, the prescaler is already 1024

but now I still facing a problem,
the frequancy is precise 1HZ, but I'm losing some seconds in an hour..
it looks like the interrupt doesn't occur for some reason every 10 or 15 minutes, it's not periodic, it happens randomly.

There is nothing nearby that make noise or something similar
and I programmed CKOPT fuse that activated internal capacitors and make oscillator Full swing

can the code affect the interrupt ? or the interrupt must occur whatever the processor is doing ?