AVR Timer: CTC mode

Thread Starter

Athul S Nair

Joined Dec 24, 2016
23
Hello,

I learning AVR programming,

I have made a code to toggle AVR pin at an interval using interrupts

Here' the code

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

// initialize timer, interrupt and variable
void timer1_init()
{
    // set up timer with prescaler = 64 and CTC mode
    TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);

    TIMSK1 |= (1 << OCIE1B);        // Output Compare B Match Interrupt Enable
    // initialize counter
    TCNT1 = 0;

    // initialize compare value
    OCR1B = 7812;
    sei();
}


ISR(TIMER1_COMPB_vect) { 
    PORTC ^= (1 << 0);
}

int main(void)
{
    // connect led to pin PC0
    DDRC = 0XFF;

    // initialize timer
    timer1_init();

    // loop forever
    while(1)
    {

    }
}
But pin is not toggling? Why?

But when i change to OCR1A, it works
Code:
#include <avr/io.h>
#include <avr/interrupt.h>

// initialize timer, interrupt and variable
void timer1_init()
{
// set up timer with prescaler = 64 and CTC mode
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);

TIMSK1 |= (1 << OCIE1A); // Output Compare A Match Interrupt Enable
// initialize counter
TCNT1 = 0;

// initialize compare value
OCR1A = 15625;
sei();
}

ISR(TIMER1_COMPA_vect) {
PORTC ^= (1 << 1);
}


int main(void)
{
// connect led to pin PC0
DDRC = 0XFF;

// initialize timer
timer1_init();

// loop forever
while(1)
{

}
}
 

mckenney

Joined Nov 10, 2018
125
But pin is not toggling? Why?
But when i change to OCR1A, it works
In CTC mode, TCNT counts up to OCR1A. In the first example OCR1A=0, since you haven't set it, so it doesn't count very far. If you set OCR1A equal (or maybe +1, I forget) to OCR1B it should count properly.

You didn't mention what AVR variant, so I can't quote you a Table number, but there should be a Table of WGM settings in the Timer 1 chapter of the data sheet.
 

Thread Starter

Athul S Nair

Joined Dec 24, 2016
23
In CTC mode, TCNT counts up to OCR1A. In the first example OCR1A=0, since you haven't set it, so it doesn't count very far. If you set OCR1A equal (or maybe +1, I forget) to OCR1B it should count properly.

You didn't mention what AVR variant, so I can't quote you a Table number, but there should be a Table of WGM settings in the Timer 1 chapter of the data sheet.
My chip is AtMega168
Thanks for the reply, Even when I set OCR1B = 7812 and OCR1A = 15764, It counts up to OCR1A, not OCR1B. One guy in other forum told me in CTC mode OCR1B register won't work. Is that true??
 

mckenney

Joined Nov 10, 2018
125
My chip is AtMega168
Thanks for the reply, Even when I set OCR1B = 7812 and OCR1A = 15764, It counts up to OCR1A, not OCR1B. One guy in other forum told me in CTC mode OCR1B register won't work. Is that true??
Per data sheet (2545W) Table 20-6 and Section 20.12.2, you can use OCR1A (or ICR1) for the CTC "TOP" value. OCR1B is not in the list. Also, Figure 20-1 doesn't show any arrow path from OCRnB back up to the Control Logic box.
 

Thread Starter

Athul S Nair

Joined Dec 24, 2016
23
I understand what you are saying and agree with it, But I am asking this out of curiosity

Code:
#include <avr/io.h>                        // Defines pins, ports, etc
#define F_CPU 1000000UL

#define LED1 PB1
#define LED2 PB2
#define LED_PORT PORTB
#define LED_DDR DDRB

static inline void initTimer(void) {
    TCCR1B |= (1 << WGM12);                                  // CTC mode
    TCCR1A |= (1 << COM1A0);           // Toggles OC1A pin each cycle through
    TCCR1A |= (1 << COM1B0);           // Toggles OC1B pin each cycle through
    TCCR1B |= (1 << CS10) | (1 << CS11);               // CPU clock / 64, 15625 tick every Sec
}

int main(void) {
    // -------- Inits --------- //
    initTimer();
    LED_DDR |= (1 << LED1);
    LED_DDR |= (1 << LED2);

    OCR1A = 15625;                        // around 1000ms delay
    //OCR1B = 15625;

    // ------ Event loop ------ //
    while (1) {

    }                                                   //End event loop
    return 0;                            // This line is never reached
}
When running this, both LED's will toggle alternatively(Don't know why not toggling at the same time?), but if introduce OCR0B in to the program, and set it at a different value that OCR0A, say OCR0B = 7812. You can see a change in blink pattern. Doesn't that mean OCR0B has somehow affecting the execution?
 

mckenney

Joined Nov 10, 2018
125
When running this, both LED's will toggle alternatively(Don't know why not toggling at the same time?),
It's because you're starting the timer, then setting OCR1A. Until you do that, TCNT is idling at 0 and matching both OCR1A/B. On the tick when OCR1A changes, TCNT matches OCR1B(=0) but not OCR1A, so they are mismatched for the entire cycle. At the end of the cycle TCNT matches OCR1A, then one tick later (at =0) matches OCR1B, so they stay out of phase.

The usual recommendation is to set the OCRs before starting the timer (the CS1x bits).There's also the FOCn bits if you want to put them deliberately out of phase.
but if introduce OCR0B in to the program, and set it at a different value that OCR0A, say OCR0B = 7812. You can see a change in blink pattern. Doesn't that mean OCR0B has somehow affecting the execution?
OCR1B affects the visible LED(s) pattern, but not how TCNT1 counts.

[Edit: Added note on FOC bits.]
 
Last edited:

mckenney

Joined Nov 10, 2018
125
https://www.avrfreaks.net/forum/attiny85-timer0-weirdness-how-use-ocr0b See this post too, I will quote one section int he reply, you can search for it
"If you want to change freq. in CTC you can by adjusting OCR0A, and OCR0B changes D.C. for OC0B"​
The AVRFreaks people know their stuff, but the reference to "D.C" (Duty Cycle) isn't strictly correct. In CTC mode the Duty Cycle for OCR0A/B (both) is 50% -- each stays high for 1 CTC cycle, then low for one cycle. What setting OCR0A and OCR0B differently does is change the phase between them.
 

Jony130

Joined Feb 17, 2009
5,488
When running this, both LED's will toggle alternatively
Did you build the circuit in real life ? I ask about this because this is not what I see on my ATmega32a.
I use this code
C:
#include <avr/io.h>
#include <util/delay.h>

#define LED1 PD4
#define LED2 PD5
#define LED_PORT PORTD        
#define LED_DDR  DDRD

static inline void initTimer( void ) {
    TCCR1B |= ( 1 << WGM12 );                                // CTC mode
    TCCR1A |= ( 1 << COM1A0 );         // Toggles OC1A pin each cycle through
    TCCR1A |= ( 1 << COM1B0 );         // Toggles OC1B pin each cycle through
    TCCR1B |= ( 1 << CS12 );           // CPU clock /256 , 15625 tick every 500ms (2Hz)
}



int main( void ) {
    // -------- Inits --------- //


    initTimer();
    LED_DDR |= ( 1 << LED1 );
    LED_DDR |= ( 1 << LED2 );
    OCR1A = 15624;                        //  Toggles 1Hz pin PD5
    OCR1B = 7812;                         //  Toggels 1Hz pin PD4


    // ------ Event loop ------ //
    while ( 1 ) {


    }                                                   //End event loop
    return 0;                            // This line is never reached
}
And my FCPU is 8MHz and this is why I use 256 as prescaler.

And ths what I see on the oscope with OCR1B = 0

NewFile32.png

And with OCR1B = 7812

NewFile33.png

This schematic shows the situation

12a.png
Now we can use interrupt from Output Compare B Match Interrupt and change this phase shift via a button. Try it yorself.
 
Last edited:

Thread Starter

Athul S Nair

Joined Dec 24, 2016
23
Yeah I think I got it

Did you build the circuit in real life ? I ask about this because this is not what I see on my ATmega32a.
WHat I meant is for both OCR1A & OCR1B set to 15624, they toggle alternatively. BUt when set as OCR1A = 15624 & OCR1B = 7812. each toggle at 1 Sec but there is a phase difference. I think That's what you are seeing too

I'm using AtMega168 and following code is for TIMER1

Code:
#include <avr/io.h> // Defines pins, ports, etc
#define F_CPU 1000000UL

#define LED1 PB1
#define LED2 PB2
#define LED_PORT PORTB
#define LED_DDR DDRB

static inline void initTimer(void) {
TCCR1B |= (1 << WGM12); // CTC mode. TOP = OCR1A
  TCCR1A |= (1 << COM1A0); // Toggles OC1A pin each cycle through
TCCR1A |= (1 << COM1B0); // Toggles OC1B pin each cycle through
TCCR1B |= (1 << CS10) | (1 << CS11); // CPU clock / 64, 15625 tick every Sec
}

int main(void) {
// -------- Inits --------- //
initTimer();
LED_DDR |= (1 << LED1);
LED_DDR |= (1 << LED2);

OCR1A = 15624; // around 1000ms delay
OCR1B = 7812; // around 500ms delay

// ------ Event loop ------ //
while (1) {

} //End event loop
return 0; // This line is never reached
}
This is the waveform generation table







In my code I have chosen CTC mode with OCR1A a s TOP

So it determines the frequency, which for a complete ON-OFF cycle is 2 Seconds, i.e.., 0.5Hz

For the below image is for TIMER0 where I assumed OCR0A = 9 and OCR0B = 5





Both OC1A and OC1B toggle at same frequency, and the instant of toggle for OC1B is determined by OCR1B

Following are the signal that I obtained from Proteus for different value of OCR1B

Yellow : OC1B
Blue : OC1A

OCR1A = 15624, OCR1B = 0



OCR1A = 15624, OCR1B = 1






OCR1A = 15624, OCR1B = 3906


OCR1A = 15624, OCR1B = 7812


OCR1A = 15624, OCR1B = 11718


OCR1A = 15624, OCR1B = 15623


From all these images This is what I am getting

Frequency: Determined by TOP, which is OCR1A for TIMER1 mode 4

OC1A toggles at TOP(OCR1A), i.e., TCNT1 == OCR1A
OC1B toggles when Match occur TCNT1 == OCR1B
If any value is not given it is 0
 
Last edited:

Thread Starter

Athul S Nair

Joined Dec 24, 2016
23
It's because you're starting the timer, then setting OCR1A. Until you do that, TCNT is idling at 0 and matching both OCR1A/B. On the tick when OCR1A changes, TCNT matches OCR1B(=0) but not OCR1A, so they are mismatched for the entire cycle. At the end of the cycle TCNT matches OCR1A, then one tick later (at =0) matches OCR1B, so they stay out of phase.

The usual recommendation is to set the OCRs before starting the timer (the CS1x bits).There's also the FOCn bits if you want to put them deliberately out of phase.

OCR1B affects the visible LED(s) pattern, but not how TCNT1 counts.

[Edit: Added note on FOC bits.]
I notice the difference

initTimer() before setting compare values
c1.PNG

initTimer() after setting compare values
c2.PNG

Did you build the circuit in real life ? I ask about this because this is not what I see on my ATmega32a.{/QUOTE]
But it should toggle alternatively for OCR1A = 15624 and OCR1B = 0.
I don't how accurate simulator is but it alternatively toggle for above value and in phase for OCR1A = OCR1B = 15624 after making above mentioned correction

Your signal schematic indicates this too
gh.png


But in hardware(I have arduino UNO), both toggle same time for both OCR1B = 0 & OCR1B = 62499(for 16Mhz & 256 prescale). BUt setting OCR1B = 1, you can see the difference
 
Top