Go Down

Topic: Timer2 OCR2A OCR2B Interrupts - Atmega328 (Read 3 times) previous topic - next topic

jaquelino

May 25, 2012, 06:21 pm Last Edit: May 25, 2012, 06:41 pm by jaquelino Reason: 1
Hi!
I'm trying to use the Timer2 on the Atmega328 (actually on Arduino Duemilanove) and I need the timer to generate 3 interrupts (on OCRA and OCRB compares and on overflow). Besides, OC2A and OC2B outputs should toggle on compare match.

The thing is that it really generates the interrupts, but only at timer maximum value, i.e. all the output compare waveforms toggle just when TCNT2 reaches TOP (every 16.4 ms) and so do the toggle of the pins defined on ISR. Inside ISR I'll need to put some functions but the pin toggle is just fine for experimentation purposes.

I tried the CTC (clear time on compare match) before but without results because in that mode I believe just OCR2A is used (to define the timer range).

I've searched on many forum and sites but all I can find is COMPA interrupts not both COMPA and COMPB. Does the normal mode support the OCR2A and OCR2B as well as overflow interrupts?

And I don't really know what FOC2A and FOC2B bits in TCCR2B register are used for. The datasheet says "The FOC2A bit is only active when the WGM bits specify a non-PWM mode". But either with them set to 1 or clear to 0 the result I get is the same.

Thanks


Code: [Select]
void setup() {
 cli();  // disable global interrupts

 DDRB |= (1 << DDB3) | (1 << DDB0);  // PB3(OC2A) and PB0 as output
 PORTB |= (1 << DDB3) | (1 << DDB0);
 DDRD |= (1 << DDD7) | (1 << DDD6) | (1 << DDD3);  // PD7 PD7 and PD3 (OC2A) as output
 PORTD |= (1 << DDD7) | (1 << DDD6) | (1 << DDD3);
 
 TCCR2A = 0x00;   // clear timer registers
 TCCR2B = 0x00;
 TIMSK2 = 0x00;
 
 TIMSK2 |= (1 << OCIE2B) | (1 << OCIE2A) | (1 << TOIE2);  // OCRA OCRB OVF Interrupts enableded
 TCCR2A |=  (1 << COM2A0) | (1 << COM2B0);   // Normal mode & toogle on OC2A & OC2B

 OCR2A = 0x64;
 OCR2B = 0x80;
 
 TCCR2B |=  (1 << CS22) | (1 << CS21) | (1 << CS20);  //Set prescaller 1024 and start timer

 sei();  // enable interrupts
}

ISR(TIMER2_COMPA_vect) {
 PORTD ^= (1 << PORTD6);    // toggle PD6
}

ISR(TIMER2_COMPB_vect) {
 PORTB ^= (1 << PORTB0);    // toggle PB0
}

ISR(TIMER2_OVF_vect) {
 PORTD ^= (1 << PORTD7);    // toggle PD7
}

void loop() {
 // main code goes here
}


Coding Badly

Does the normal mode support the OCR2A and OCR2B as well as overflow interrupts?


From the datasheet...

Quote
17.7.1 Normal Mode
...The Output Compare unit can be used to generate interrupts at some given time...


Yes, Normal Mode generates output compare interrupts.

Coding Badly


What do you have connected to D6 and B0?

jaquelino

#3
May 25, 2012, 08:12 pm Last Edit: May 25, 2012, 08:26 pm by jaquelino Reason: 1


What do you have connected to D6 and B0?


For now just oscilloscope probes to see the pin output changes.

Jack Christensen

That's really got that little timer cookin' on all burners, but I don't see any reason it shouldn't work. Code looks ok, just from visual inspection.

There's a statement I don't understand in the datasheet, section 18.7.1:
Quote
The Output Compare unit can be used to generate interrupts at some given time. Using the Output
Compare to generate waveforms in Normal mode is not recommended, since this will
occupy too much of the CPU time.


Not sure why it would use CPU time.

Have you tried disabling the two output compare interrupts, just leaving the overflow interrupt, then looking at the waveforms on PB3 (OC2A), PD3 (OC2B) and PD7? Seems to me the compare ISRs just do the same thing that the timer output compare does, just on different pins. Not that that should be an issue, just sort of grasping at straws here.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

jaquelino

It's working now!!! I don't really know what I did because the code seems pretty much the same I posted here. But it's perfect for me xD


Seems to me the compare ISRs just do the same thing that the timer output compare does, just on different pins.


Yes they do, but that was the easiest thing I tried to know if the interrupts were working. In the future I'll place some functions there.



There's a statement I don't understand in the datasheet, section 18.7.1:
Quote
The Output Compare unit can be used to generate interrupts at some given time. Using the Output
Compare to generate waveforms in Normal mode is not recommended, since this will
occupy too much of the CPU time.



I also did read that and didn't understand why... Does anyone know why?
I tried to do the same with fast PWM mode and manage to do the thing. Is it better to use this mode? Because there's nothing about too much CPU time written on datasheet for PWM mode.

Jack Christensen

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Coding Badly

Using the Output
Compare to generate waveforms in Normal mode is not recommended, since this will
occupy too much of the CPU time ... I also did read that and didn't understand why... Does anyone know why?


My guess is they are referring to code that adjusts TCNT in the interrupt service routine to simulate a hardware PWM mode.  Or, it was included to appease a fellow employee: "Maybe if we include that warning he'll quit yammering-on."

In any case, the guidance is always the same: keep your interrupt service routines short.

Jack Christensen


My guess is they are referring to code that adjusts TCNT in the interrupt service routine to simulate a hardware PWM mode.  Or, it was included to appease a fellow employee: "Maybe if we include that warning he'll quit yammering-on."


Gotta be one of the two. It sure seems like the way jaquelino has it set up could be interpreted as "generating waveforms in Normal mode" but there sure to heck ain't any CPU involved, else I'm seriously missing something! XD
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Nick Gammon


I also did read that and didn't understand why... Does anyone know why?


I think I do ...

From my page on timers here:

http://www.gammon.com.au/forum/?id=11504

I experimented with different modes. This is the one for "normal" mode:

Code: [Select]
#include <TimerHelpers.h>

// Timer 0

// input     T0     pin  6  (D4)
// output    OC0A   pin 12  (D6)
// output    OC0B   pin 11  (D5)

const byte timer0Input = 4;
const byte timer0OutputA = 6;
const byte timer0OutputB = 5;
 
void setup() {
   pinMode (timer0OutputA, OUTPUT);
   pinMode (timer0OutputB, OUTPUT);
   TIMSK0 = 0;  // no interrupts
   Timer0::setMode (0, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE | Timer0::TOGGLE_B_ON_COMPARE);
   OCR0A = 150;
   OCR0B = 200;
}  // end of setup

void loop() {}


Produces:



Now in this example the period is only 32 uS, and the "compare match" interrupts (if you had both set up) would have to fire every 32 uS. And since an interrupt takes close to 3 uS to set up and tear down, and you would have two of them, that is 6 uS out of the 32 uS used, plus whatever the interrupt itself actually does that is useful.

So say you spent 8 uS on the interrupts, then that is 25% of your CPU time dedicated to handling the compare matches. I suppose that is what they are getting at.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up