Control AVR 8 bit Timer-Counter2 using WINAVR

Error message

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls in menu_set_active_trail() (line 2405 of /home/minmaro3/domains/

AVR ATmaga8 Timer/Counter2 is little more advanced timer counter than Counter0 as it includes more features like:

  • Single Channel Counter

  • Clear Timer on Compare Match (Auto Reload)

  • Glitch-free, phase Correct Pulse Width Modulator (PWM)

  • Frequency Generator

  • 10-bit Clock Pre-scaler

  • Overflow and Compare Match Interrupt Sources (TOV2 and OCF2)

  • Allows Clocking from External 32 kHz Watch Crystal Independent of the I/O Clock

So we have there another register included OCR2, which is used to compare timer counter register TCNT2 register value and react on compare match. Wee see that there is Auto-reload ability what means that timer can be cleared automatically on compare match.

On compare match there is OCF2 flag set in and if Output compare interrupt bit OCIE2 is set in TIMSK register then interrupt is generated (it clears OCF2 bit then). If no interrupt is enabled, then you have to clear OCR2 flag by writing 1 to it. Output compare may be used to generate waveform according to WGM21:0 bits in TCCR2 register.


Note that OCR2 register is double buffered when using PWM mode. The double buffering synchronizes the update of the OCR2 Compare Register to either top or bottom of the counting sequence. The synchronization prevents the occurrence of odd-length, non-symmetrical PWM pulses, thereby making the output glitch-free.

If non PWM waveform generation mode on compare match comparator can be forced by writing one to FOC2 bit in TCCR2. Force Output Compare – this mode is not affecting OCF2 or reload timer, but updates OC2 pin (regarding to COM21:0 settings the pin is set, clear or toggled).

It is good to remember that writing to TCNT2 register with value that matches at next clock cycle will block Compare match. This allows to initialize OCR2 to same value as TCNT2 without triggering an interrupt.

Operation modes of Timer/Counter2:

  • Normal Mode – In this mode counter direction is always up and no counter clear is performed. Timer overflows and writes one to flag register bit TOV2 and if interrupt is enabled in TIMSK register then overflow interrupt is generated. New counter value may br written any time. This is the same as in Timer0.

  • Clear timer on compare match – CTC mode (WGM21:0=2 in TCCR2). In CTC mode counter is cleared to zero on match TCNT2=OCR2. OCR2 defines the top value. An

 interrupt is generated each time the compare matches. This mode is convenient in generating waveform on pin OC2 when FOC2 bit is set in TCCR2. Waveform frequency can be calculated using this formula:


 fclk_I/O – clock source frequency; N – prescaler value (1, 8, 32, 64, 128, 256, or 1024), OCRn the value of register OCR2. If OCR2 is set to 0, then output frequency will be half of clock frequency.

  • Fast PWM mode – (WGM21:0=3 in TCCR2) is a high frequency PWM. It is because of single slope operation.

      The diagram explains how it works. The diagram shows non inverting (regarding to COM21:0 settings in TCCR2 register) and inverting OCN2 outputs, OC2 pin is cleared on match and set at the bottom of TCNT2.

    • Phase correct PWM mode – (WGM21:0=1). This is dual slope PWM and is so callec high resolution correct phase PWM.


      This mode is preferred for motor control because of symmetric feature. Note that in this case and earlier pin OC2 has to be set as output by setting 1 to DDR register.

    Now its time for an example. Lets write simple routine for Phase correct PWM:

    #include <avr\io.h>

    #include <avr\iom8.h>

    #define outp(a, b) b = a

    int main(void) {

    /* set OC2 for PWM output*/

    outp((1<<PINB3), DDRB);

    /*set timer counter initial value*/


    /*Set timer output compare register*/


    /*start timer:

    without presscaler

    Non inverted mode in OC2 pin;

    phase corect PWM*/

    outp((1<<FOC2)|(1<<COM21)|(1<<COM20)|(1<<WGM20)|(1<<CS00), TCCR2);

    for (;;) {

    /* loop forever timer does the job*/





    You may download and try this code with VMLAB simulator.