Confusion on CTC Mode (Atmega328p

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So im learning about timers and the "Normal Mode" timer was pretty straightforward, so I thought i'd take a shot at CTC mode looking purely at the datasheet (seemed easy enough). My chip is running at the default 1MHz. Here is my code:

 

/*
 * 328p_Timer_CTC_Mode.c
 *
 * Created: 11/9/2018 7:32:35 PM
 */ 


#include <avr/io.h>

/* LED Definitions */
#define LED			PINB1
#define LED_PORT	PORTB
#define LED_DDR		DDRB



/***
We are going to use the Atmega's Timer1 (16-bit timer) in Clear Timer on Compare Match (CTC)

For Timer1:
- Setting the mode to (CTC) mode we use OCR1A to set Resolution 
- TCNT1 is cleared when the counter matches the value in OCR1A
- Setting Clock prescaler to clk/1024 = 1MHz/1024 = 1.024 (ms) per tick

***/

static inline void initTimer1CTC(void) {
	TCCR1A |= (1 << WGM12);					/* Set CTC Mode, see page: 141 on Datasheet */
	TCCR1A |= (1 << COM1A0);				/* Toggle OC1A Pin (Pin 12, PD6) after each "cycle" after matching OCR1A */
	TCCR1B |= (1 << CS12) | (1 << CS10);	/* Set Timer1 to clk/1024 prescaler */
}




int main(void)
{
	initTimer1CTC();
	LED_DDR |= (1 << LED) ;			/* PB1 set to output (LED), for OC1A pin to toggle */
	uint16_t duration =  5000;
	OCR1A |= duration;
	while (1)
	{
		/* Toggle should happen after OCR1A value is reached each time */   
	}


	return 0;
}

 

So this is indeed working by toggling PB1 every so often, according to my calculation of clock speed and then steps to OCR1A it should be blinking every 5 seconds....but it's blinking more like every 30 seconds or something. Im guessing im mis-understanding how the timing is calculated, but hoping someone could point out where I went wrong. (As a sidenote: I wish there was a good poster or something listing all the AVR pinouts, that'd be a good buy! haha)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mercfh wrote:

... CTC mode:

static inline void initTimer1CTC(void) {
	TCCR1A |= (1 << WGM12);					/* Set CTC Mode, see page: 141 on Datasheet */
	TCCR1A |= (1 << COM1A0);				/* Toggle OC1A Pin (Pin 12, PD6) after each "cycle" after matching OCR1A */
	TCCR1B |= (1 << CS12) | (1 << CS10);	/* Set Timer1 to clk/1024 prescaler */
}

 

WGM12 lives in TCCR1B so you are actually setting a reserved bit to 1.

Also it's better to initialize with an = instead of |= since the latter will

leave any other '1' bits set:

 

static inline void initTimer1CTC(void) {
    TCCR1A = (1 << COM1A0);                             // output toggle
    TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);  // CTC + /1024
}

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yikes thats embarrassing lol! also good point about |= vs =. I wonder why my device was still blinking the LED though...i guess it was in normal mode? but I thought the TOV1 flag had to be cleared before it could be set again?....i mean the LED was def. blinking but just super slowly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OCR1A =5000;

You want a direct assignment, not |=

TOF1 is only of concern if you have the associated interrupt turned on or you are polling that bit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mercfh wrote:

.... the LED was def. blinking but just super slowly.

 

Probably 13.10458 times slower?

 

Since you turned the timer on it was still counting

in normal mode, just not resetting when the count

reached OCR1A.  Eventually it overflowed and came

back around to OCR1A again for another toggle of

the output.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-mike wrote:

Mercfh wrote:

.... the LED was def. blinking but just super slowly.

 

Probably 13.10458 times slower?

 

Since you turned the timer on it was still counting

in normal mode, just not resetting when the count

reached OCR1A.  Eventually it overflowed and came

back around to OCR1A again for another toggle of

the output.

 

--Mike

 

 

Yeah thats prolly right. Also Kartman I meant TOV1 flag (which I had to reset when doing normal mode) or do you not need to reset it?

 

btw why 13.1 times slower (I must be missing something)?

 

ah wait nm......65,535/5000 derp.

Last Edited: Sun. Nov 11, 2018 - 04:08 AM