Electronics > Microcontrollers

Help on Atmega168/328 PWM with Interrupts

(1/3) > >>

I am really stuck trying to get a useful interrupt from Timer 2 in Fast or Phase Correct 8 bit PWM. The processor is an Atmega 168 or 328. I am using an Arduino, if that has anything to do with it.

I am using the interrupt so I can change the PWM value from cycle to cycle. The Atmega168 has double buffering so the change will only occur at the start of a PWM cycle.

If I use the interrupt generated from the counter match with the PWM value, then with the double buffering of the PWM value, I do not know if the new value will be set on the next cycle or the one after. That makes it pretty useless.

If I can get the interrupt always occurring at the start of a new PWM cycle, then I know the updated PWM value will be active at the start of the following cycle.

I can get an interrupt out on the match of the counter with the set PWM value, but  For this I need an interrupt when the PWM reaches the TOP value (ie 0xFF) and supposedly the TOV2 flag gets set. Then by setting the TOIE2 flag in the TIFR2 register, then in theory this should happen. In practice there is no interrupt.

The documentation talks of the TOV2 interrupt flag being set in both the Fast and Phase Correct PWM modes at TOP or at 0x00, but I cannot get any interrupt to be generated.

Here is the settings for setting up fast PWMs on Timer2 which I think should work, but I must be missing something.

The _BV(COM2A1) macro seems to do the same thing as ( 1 << COM2A1) - generates a byte with the wanted flag bit set and all others not set.

--- Code: ---  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // Fast PWM
  TCCR2B = _BV(CS20) ;  //No Prescaler
  TIMSK2 = _BV(TOIE2);   // Set for interrupt when Timer reaches TOP (Fast PWM) or BOTTOM (Phase Correct PWM)
   sei() ; // Enable interrupts

--- End code ---

Here is the data sheet: http://www.atmel.com/Images/doc8161.pdf

I have tried setting and clearing the TOV2 bit in TIFR2 top see if that helps, but it doesn't.



such a question has a good chance to get an answer in the avrfreaks.net forums. Plenty of AVR gurus there.


Thanks Markus,  I will take a look at the forum.


Richard, I don't see any obvious problems with your code.  How is your ISR declared?  I'm not sure how you're supposed to do that on an Arduino (I have one but never mess with it.)  Maybe the interrupt is occurring but going elsewhere. 

The only other thing is the Arduino angle like you mentioned.  Maybe that timer is being used for something else.

The ISR vector for compare is TIMER2_COMP_vect but TIMER2_OVF_vect for overflow - did you change this?


[0] Message Index

[#] Next page

There was an error while thanking
Go to full version