Is it possible to use Timer1 on an ATMega to generate a compare interrupt on OCR1A and PWM output on OCR1B? I've tried with similar to the following, but neither work with everything I've tried.

TCCR1A = _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
OCR1B = 0;

// set compare match register for 1000Hz 
OCR1A = 2000;
// turn on CTC mode
TCCR1B |= _BV(WGM12);

Side note: I know this is extremely similar to another question of my own, but that was regarding PWM on one timer and interrupts on another. This time I'm having trouble getting both out of the SAME timer.


Your code sets the counter for phase correct PWM operation with top value 0x3FF so the first problem you'll face is that the compare match interrupts will not be triggered in equal intervals because of the way that this mode works which is count to the top and then change direction and count backwards.

The other problem is that the counter counts up to 1023 (0x3ff) and back to 0 so there is no way to ever get a match interrupt for a value of 2000 (OCR1A = 2000)

phase correct PWM operation:

enter image description here

This is a minimum code for mega328 running @16MHz that sets Timer 1 to generate a fast PWM with a frequency of about 1KHz (frequency set by ICR1 and duty set by OCR1B) and also gives a timer 1 overflow interrupt with a 1KHz rate

#include <avr/io.h>
#include <avr/interrupt.h>

// Timer1 overflow interrupt service routine
    PORTB ^= 1; // invert PORTB.0

int main(void)

    // Port B initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=In Bit0=Out
    DDRB = 0x05;

    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 2000,000 kHz
    // Mode: Fast PWM top=ICR1
    // OC1A output: Disconnected
    // OC1B output: Non-Inverted PWM
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer Period: 1,0245 ms
    // Output Pulse(s):
    // OC1B Period: 1,0245 ms Width: 0,12806 ms
    // Timer1 Overflow Interrupt: On
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
    TCCR1B = (0 << ICNC1) | (0 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
    TCNT1 = 0;
    ICR1 = 2048;
    OCR1A = 0;
    OCR1B = 256;

    // Timer/Counter 1 Interrupt(s) initialization
    TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (1 << TOIE1);

    // Global enable interrupts

        // Place your code here

  • \$\begingroup\$ Could I use Fast PWM instead? Not that I'm entirely sure how to do that :P \$\endgroup\$ – Adam Haile Dec 18 '13 at 22:56
  • \$\begingroup\$ @AdamHaile Depends what you want to do, if you want to get equal intervals for the compare match then yes, if it is just to set a higher top value (which will result in a lower PWM frequency) then you can use both modes with a custom top value set to the ICR1 register by selecting the appropriate PWM mode (using the WGM register values) \$\endgroup\$ – alexan_e Dec 18 '13 at 23:19
  • \$\begingroup\$ Yes... definitely want equal intervals. The Compare match is for doing multiplexing between different LEDs using the PWM signals. Any chance you could show some example code? \$\endgroup\$ – Adam Haile Dec 18 '13 at 23:28
  • \$\begingroup\$ @AdamHaile what is your specific MCU? And what about the PWM frequency? PWM can give a timer overflow interrupt once per period (TOV1 flag), maybe you can use that for your refresh \$\endgroup\$ – alexan_e Dec 18 '13 at 23:40
  • \$\begingroup\$ ATMega328P-PU. Have no idea what the PWM frequency is. Was using 8 prescaler, so 2MHz? I'm trying to get an interrupt at roughly 1000 Hz. \$\endgroup\$ – Adam Haile Dec 18 '13 at 23:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.