Go Down

Topic: Timer 2 CTC mode without interruption (Read 1 time) previous topic - next topic

raulcomander

Hello.
I would like to use timer2 to count an amount of time and set a flag after this time has elapsed.
But no interruptions.

I find that CTC mode is what I want so I configure it like that:
Code: [Select]

void configureTimer2(void) {
  // initialize timer2
  noInterrupts();           // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
 
  TCCR2A |= (1 << WGM21); // Configure timer 2 for CTC mode
  TCCR2B |= (1 << CS22);  // 1024 prescaler
  TCCR2B |= (1 << CS20);  // 1024 prescaler
  TIMSK2 &= ~(1<<OCIE2A);   //Disable timer compare interrupt.
  OCR2A = 163;     //163       // compare match to achieve 96Hz. Xtal 16Mhz, Prescaler 1024.
  interrupts();
}


The timer is supposed to set to 1 some flag bit in the TIFR2 register.

Now what I do not know is which one of the bits is supposed to be on.
OCF2B,   OCF2A or    TOV2

My guess is that it is OCF2A but I had unexpected behaviours using that approach.

Something else sounds wierd to me:
"OCF2A can also be cleared by writing a logic one to the flag."
-To clear it, a 1 has to be written into, sound a bit extrange for me.


To check for this flag, what I do is:
*Polling for the bit OCF2A until it is 1.
*Clear the flag by writting again 1 into it.
*Do the stuff....
*Again Polling for the bit OCF2A until it is 1...
This way the "stuff" is done at a frequency of timer2 but with no Timer2 interruption.

Is it sensible, for some reasson it is not working and I will try to dig into it a little bit more tomorrow, I just wanted to share it to have a 2nd oppinion.

Ill post back if I find a solution.

jremington

#1
Apr 12, 2017, 12:59 am Last Edit: Apr 12, 2017, 01:26 am by jremington
Quote
Now what I do not know is which one of the bits is supposed to be on.
OCF2B,  OCF2A or TOV2
According to the datasheet, OCF2A.

Quote
OCF2A can also be cleared by writing a logic one to the flag.
Correct. To clear that flag, use the instruction
Code: [Select]
TIFR2 = (1<<OCF2A);  // do NOT use the bitwise OR operation

It would probably be a good idea to clear the TIMSK2 register, unless you are planning on overflow or OCF2B interrupts.
Code: [Select]
TIMSK2 = 0; //no interrupts from this timer

raulcomander

Thanks.

Just another question.

I have no plans to overflow the timer, if I am not wrong, in CTC mode, the TCNT2 is reloaded to 0 after a success match with OCR2A.

raulcomander

After applying the sugested changes:
Code: [Select]

void configureTimer2(void) {
  // initialize timer2
  noInterrupts();           // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
 
  //TCCR2B |= (1 << WGM12);   // CTC mode---- WRONG
  TCCR2A |= (1 << WGM21); // Configure timer 2 for CTC mode
 
  //TCCR2B |= (1 << CS12);    // 1024 prescaler
  //TCCR2B |= (1 << CS10);    // 1024 prescaler
  TCCR2B |= (1 << CS22);  // 1024 prescaler
  TCCR2B |= (1 << CS20);  // 1024 prescaler
 
  //TIMSK2 |= (1 << OCIE2A);  // enable timer compare interrupt
  TIMSK2 =0;   //Disable timer compare interrupt. and everything unles overflow or OCF2B interrupts are used
  OCR2A = 163;     //163       // compare match to achieve 96Hz.
  interrupts();
}

and

In the loop I check the flag this way:
Code: [Select]

void countAndCheckInput(void) {
  if ((TIFR2 & (1 << OCF2A)) == 0) {
    return;  //The flag is not set, so return
  } else {  //The flag is set.
    //digitalWrite(TRIGGERPIN, digitalRead(TRIGGERPIN) ^ 1);  //Measuring here with the oscope T=1.3ms
    countForNewFrame++;
    TIFR2 = (1 << OCF2A); // This is to clear the bit.
      ...
      ...
      ...
 

The tick time is 1.3ms !! But based on calculations I expect a tick time arround 10.4ms

16.000.000Hz /(1024*163)=96Hz --> Period = 10.4ms

How is possible the big difference?
I would understand if the result was bigger than expected, but this much smaller I am totally lost here.

jremington

These two lines select 128 as the clock prescaler, not 1024:

Code: [Select]
  TCCR2B |= (1 << CS22);  // 1024 prescaler
  TCCR2B |= (1 << CS20);  // 1024 prescaler

raulcomander

OMG, rookie mistake, I checked a table from the Atmega168 datasheet instead of the 328p.

Aniway 10.4ms/1.3ms = 8 should have given me some information about what was happening.

Code: [Select]
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);  // 1024 prescaler


Solved.
Thanks for your help.

Go Up