[TUT] [C] Newbie's Guide to AVR Timers

Go To Last Post
482 posts / 0 new

Pages

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

What you are after is called Software PWM. It's fairly easy to do, the program structure would be:

Set up LED hardware
Set up timer
Initialise counter to 0

WHILE forever
  IF timer value IS EQUAL TO 1 sec THEN
    Increment counter
    Reset timer
    IF counter value IS EQUAL TO 20 seconds THEN
      Turn LED On
    END IF
    IF counter value IS EQUAL TO 60 seconds THEN
      Turn LED Off
      Reset Counter
    END IF
  END IF
END WHILE

Which would turn the LED on for 20 seconds, and off for 40 seconds - so a total period of 60 seconds, with a 30% duty cycle. In actual code, this looks like:

#include 

int main (void)
{
   unsigned char ElapsedSeconds = 0; // Make a new counter variable and initialise to zero

   DDRB |= (1 << 0); // Set LED as output

   TCCR1B |= ((1 << CS10) | (1 << CS11)); // Set up timer at Fcpu/64

   for (;;)
   {
      // Check timer value in if statement, true when count matches 1 second
      if (TCNT1 >= 15624)
      {
         TCNT1 = 0; // Reset timer value
         ElapsedSeconds++;

         if (ElapsedSeconds == 20) // Check if the duty cycle has elapsed
         {
            PORTB &= ~(1 << 0); // Led ON
         }
         else if (ElapsedSeconds == 60) // Check if one minute has elapsed
         {
            ElapsedSeconds = 0; // Reset counter variable

            PORTB |= (1 << 0); // Led OFF
         }
      }
   }
}

Where the duty cycle (on time for the LED, the 20 seconds in this example) is equal to or less than the timer period, the 60 seconds in this example.

You can extend this and combine it with other techniques I've discussed in the tutorial to have multiple software PWM channels from the one physical timer, like I've done in this project of mine:

https://code.google.com/p/lufa-l...

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Dean:

Could you possibly make a tutorial for using a 16-bit timer? I know it is very similar to the 8-bit, but I am having a lot of trouble with the "Low" and "high" concepts.

Thanks,

Alex

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

For C, just use the whole 16 bit register (e.g. instead of TCNT1L and TCNT1H, use TCNT1).

Regards,
Steve A.

The Board helps those that help themselves.

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

Hi, i've been wanting to ask you about the timers.
I am using an Atmega32 with an lcd screen at 8Mhz external clock crystal.

So, here's the thing: according to the tutorial to get a 1 sec or 1hz delay, i use a target timer count of 31249 with a prescaler of 256.
Here's the problem: The timer doesn't work as intended. I get a pretty big error rate at the time i want to display.
The code is as follows

#define F_CPU 8000000UL

#include 
#include 
#include "lcd.h"

int sec = 0;
int min = 0;
int hour = 0;
char sm[3];
char sh[3];

int main(void)
{

TCCR1B |= (1 << CS12);

lcd_init(LCD_DISP_ON);
lcd_clrscr();
itoa (min, sm, 3);
lcd_puts(sm);
lcd_puts(":");
itoa (hour, sh, 3);
lcd_puts(sh);
TCNT1 = 0;

	while(1)
	{
	  	if (TCNT1 == 34286)
		{
			TCNT1 = 0;
			if (sec < 60)
	  		{
	  			sec = sec + 1;
	  		}
	  		else if (sec == 60)
	  		{
	  			sec = 0;
	  			min = min + 1;
	  			lcd_clrscr();
	  			itoa (min, sm, 10);
	  			lcd_puts(sm);
	  			lcd_puts(":");
	  			itoa (hour, sh, 10);
	  			lcd_puts(sh);
	  			if (min == 60)
	  			{
	  				min = 0;
	  				hour = hour + 1;
	  				lcd_clrscr();
	  				itoa (min, sm, 10);
	  				lcd_puts(sm);
	  				lcd_puts(":");
	  				itoa (hour, sh, 10);
	  				lcd_puts(sh);
	  				if (hour == 24)
	  				{
	  					hour = 0;
	  					lcd_clrscr();
	  					itoa (min, sm, 10);
	  					lcd_puts(sm);
	  					lcd_puts(":");
	  					itoa (hour, sh, 10);
	  					lcd_puts(sh);
	  				}; 	
	  			};
	  		};
		};		
	};

}

(don't mind the way i show things on the lcd screen)
I am using Winavr GCC compiler and AVR studio 4.# with stk500 and a 5volt power supply. The lcd is at PORTB.
What am i doing wrong?

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

My first guess is that you are taking soooo long processing, you are missing many of the timer count events. So, if (TCNT1 == 34286) is getting hit less often than you think!) (If (TCNT1 > some_number), may get you better resolution).
The ';'s' after your closing braces are not necessary.
There is a fair degree of repetition in your code. Refactor. (Make routines to handle similar/identical code and call them where needed, possibly with arguments where necessary)
Put your 'initialisation' code in a function. It's easier to see what you intend.
I'm also not a big fan of your ... if..else..if..if.. construct.
Try to map out your algorithm in pseudo code and translate that to 'c'.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

Actually, i had an epiphany yesterday. I thought of placing the compare part of the timer in an overflow event and then the rest in a function as you said. Thanks for the info.

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

:s
help....?
I'm using a Atmega328P with 20MHz Clock
Unless I messed up the math ( and that is something I wouldn't rule out) the timer_init() should give a interrupt every 25uS.
And the ISR should toggle pin B5 every 1mS.
The thing is, it's toggling every 150mS.

static void timer_init()
{
TIMSK1 = 0x00;	// disable timer1 OCR1A interrupt
TCCR1A |= 0x00;	// CTC, Immediate / MAX
TCCR1B &= 0x08;	// OCR1A
TCCR1B |= 0x01;	// timer 1 ticks at 20 MHz (prescaler = 1)

OCR1A = 249;
TIFR1 = 0x02;	// clear timer1 OCR1A flag
TIMSK1 = 0x02;	// enable timer1 OCR1A interrupt
sei();		// enable global interrupts
}

ISR(TIMER1_COMPA_vect)
{
msCounter++;
	if ( msCounter == 40 )
		{
			set_digital_output( IO_B5, LOW ); // PD0 goes low
		}
	else if ( msCounter == 80 )
	{
		set_digital_output( IO_B5, HIGH ); // PD0 goes low
		msCounter = 0;
	}

}

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

Just out of interest, why use the prescaler in the ISR rather than using the prescaler that the timer hardware provides? To check your timer sums search "avrcalc" here, download and use it.

EDIT avrcalc says 20MHz, 25us needs an OCR of 0x1F4 with CTC mode that would be 0x1F3. For 1ms with no prescale it says 0x4E20/0x4E1F

Last Edited: Sun. May 1, 2011 - 06:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nevermind the pre-edit
the "if's" on the ISR are only for debug, I just need the "msCounter" to update every 25uS so I can check how long takes a function to run.
something like

Quote:

start_tick = msCounter;
function();
last_function_time = msCounter - start_tick;

Last Edited: Sun. May 1, 2011 - 06:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

did I get it wrong?


Yes, Each timer has it's own prescale bits. For timer0 they are CS0n, for timer1 they are CS1n

To be honest, general questions about timer use (not comments about the tutorial in this thread) should really be posted as separate threads in AVR Forum, not on the end of this tutorial

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

you are absolutely right and I shall do that

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

Hi all...Sorry for my bad english.This is my first comment here :) I have a problem with my Atmega8 timer0. I want to blink one led with 0.5Hz and this is the code there i used:

#include  
#include  

unsigned int count = 0; 

ISR(TIMER0_OVF_vect){ 
    
   
   count++;    
   if(count == 10000){ 
      PORTD ^= ( 1 << PORTD0); 
      count=0; 
   } 
   
   TCNT0 = 0x9C; 
} 


int main(){ 
   TCCR0 |= (1<<CS00); 
   TIMSK |= ( 1 << TOIE0); 
   TCNT0 = 0x9C; 
    
   DDRD |= (1 << DDD0); 
   PORTD &= ~(1 << PORTD0);
  
   sei();
   while(1){ 
    
   } 

return 0; 
} 

LED is blink with greather than 1s/on/ and 1s/off/.
May be I'am the problem, byt I can't fix it.

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

Why not use a prescaler and CTC mode and, if necessary a 16 bit timer.

By the way this thread is only to make corrections/suggestions to the original article - not to diagnose every last timer problem. PM with a subject title you would like to use for your question and I'll split it from this thread and move it to AVR Forum.

Cliff (moderator)

In the meantime I'm going to lock this trhead - if anyone has further changes for the original tutorial article then PM 'js', 'plons' or 'clawson' and one of us will temporarily unlock this trhead to allow your contribution to be added.

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

Sorry if this is not the place, but I've been looking for a long time to find a way to do such thing with atmega2561 and I'm not able. I was hoping you guys could help me out with this. I would like to do something similar to this but in atmega2561:

#include 

int main (void)
{
   DDRB |= (1 << 0); // Set LED as output

   TCCR1B |= ((1 << CS10) | (1 << CS11)); // Set up timer at Fcpu/64

   for (;;)
   {
      // Check timer value in if statement, true when count matches 1 second
      if (TCNT1 >= 15624)
      {
         PORTB ^= (1 << 0); // Toggle the LED

         TCNT1 = 0; // Reset timer value
      }
   }
}

Thanks a lot!

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

Remind us again why that doesn't simply work in 2561?

(it's a bad example, it'd be better using CTC anyway)

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

Better than most books I have read. I'm using a Mega2560 breakout and had no trouble modifying the examples and getting the expected results.

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

Hi,

I like this tutorial a lot, and am thankful for the effort by Dean and others to educate the masses and ease us into AVR development.

On the more practical side, I believe there is still a point or two missing, which would enrich the tutorial even more. I looked but did not find any quick examples or explanations for my questions, and would greatly appreciate more experienced help. If Dean would add any possible answers to his primer, that would be even better. So here goes...

The tutorial explains very well how to use timers in the straightforward way. There is no mention however, what to do if one needs a timer reset before the timer actually triggers/overflows/etc. As example consider displaying a message on a LCD screen for 10 seconds. When the 10 seconds expire, the message is automatically cleared from the screen. So I would figure out the correct prescaler, start the timer and wait for any event to display a message. Here is the first gotcha. By nature events are asynchronous, so the message could be displayed in the middle of the counting period, or just before the timer expires. Question: Do I reset the timer just by writing my actual BOTTOM value to TCNT1? And then, if I were using interrupts, I would obviously want to disable the selected timer interrupt before I set the message until after I reset the timer counter, so I wouldn't be displaying the message text possibly in the same time when the interrupt handler is trying to clear it. Question: How would I go about that and does this need to be an atomic operation?

The same questions apply, if a second event/message arrives before the timer clears the first one. Obviously the second message will override the first one and the timer will need to be restarted for the new text displayed. Then the message is cleared after 10 seconds expire, or if the next message arrives before that. And so on, ad-infinitum.

And there is another question to consider, which also fits the topic of the tutorial: What do I need to do to have one-shot timers? Is it more resource-intensive to start and stop the timer every time or disable the timer interrupt vector, or just let them run (obviously not an option in the case where I would need my display to show something else as long as no event like an error message arrives...)?

I would greatly appreciate answers to these questions from the knowledgeable, and I think that would be a good addition to the tutorial.

Thanks.

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

Quote:

There is no mention however, what to do if one needs a timer reset before the timer actually triggers/overflows/etc. As example consider displaying a message on a LCD screen for 10 seconds. When the 10 seconds expire, the message is automatically cleared from the screen. So I would figure out the correct prescaler, start the timer and wait for any event to display a message. Here is the first gotcha. By nature events are asynchronous, so the message could be displayed in the middle of the counting period, or just before the timer expires. Question: Do I reset the timer just by writing my actual BOTTOM value to TCNT1?

This is somewhat mode dependent, but yes, you can just overwrite TCNT to your bottom value. It would be a good idea to stop the timer first, so that you don't end up with a timer event during the update. Note that the AVR hardware will cache the 16-bit register write until the lower half is written. That will prevent atomicity issues in the update.

Quote:

And then, if I were using interrupts, I would obviously want to disable the selected timer interrupt before I set the message until after I reset the timer counter, so I wouldn't be displaying the message text possibly in the same time when the interrupt handler is trying to clear it. Question: How would I go about that and does this need to be an atomic operation?

To stop the timer, just remove the clock source - clear the CSxy bits in the timer's control B register. After the update, restore the bits to restart the timer.

Quote:

And there is another question to consider, which also fits the topic of the tutorial: What do I need to do to have one-shot timers? Is it more resource-intensive to start and stop the timer every time or disable the timer interrupt vector, or just let them run (obviously not an option in the case where I would need my display to show something else as long as no event like an error message arrives...)?

The best way is probably to stop the timer when not in use - to start the period reset the timer before restarting it. Once the period has elapsed (detected either via polling of the compare flag bits or via the compare ISR you would turn off the timer and perform your desired action.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

from the tutorial's last chapter:

ISR(TIMER1_OVF_vect) 
 { 
    PORTB ^= (1 << 0); // Toggle the LED 
    TCNT1  = 49911; // Reload timer with precalculated value 
 }

i am not an expert, but i think this is wrong.
loading the timer counter should be the 1st thing inside the interrupt, to keep the timer accurate.
if we do other things before setting TCNT1 here, these things will add to the timer period.

for example, try adding a 200ms delay before or after the timer reloading and see the difference.
- Chris

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

Quote:

i am not an expert, but i think this is wrong.
loading the timer counter should be the 1st thing inside the interrupt, to keep the timer accurate.
if we do other things before setting TCNT1 here, these things will add to the timer period.

for example, try adding a 200ms delay before or after the timer reloading and see the difference.

Indeed, it is better to be done first. That said, the overflow-as-CTC method is not recommended if you can avoid it, as there are other hidden cycle costs that you can't easily guard against; specifically, the time taken to fire the interrupt (it may be delayed due to other ISRs or atomic sections of code in the main thread) as well as the time to run the ISR preamble (variable depending on the code inside the ISR) and the time taken to read, modify and write the timer count. That means that even in the best-case scenario, it won't give you super-accurate results.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:
... there are other hidden cycle costs that you can't easily guard against; specifically, the time taken to fire the interrupt (it may be delayed due to other ISRs or atomic sections of code in the main thread) as well as the time to run the ISR preamble (variable depending on the code inside the ISR) ...
Not true. If you really want/must use the reload method, then do this in the ISR:

TCNT1 -= CLOCKS_PER_OVERFLOW;

This gives you a much better accuracy because the above "hidden cycle costs" don't have an effect any longer. And if you incorporate the cycles between read and write of TCNT1, then you have even (almost) the same "super-accuracy" as with CTC.

"almost" because I am not really sure about the case the timer works with a prescaler.

Stefan Ernst

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

[PORTB ^= (1 << 0);]

hei can u xplain this.

*** ***

*********************

the more is see,less i know

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

Quote:

[PORTB ^= (1 << 0);]

hei can u xplain this.


All explained here:

Bit manipulation 101 (also here in the Tutorial Forum - well worth reading through the titles and taking a look at any you think sound interesting!)

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

good one
ya i found another gud explanation also in the web with eg:

00101010
11000100
--------- OR
11101110

3 << 2
3: 00000011
00001100 = 12

*** ***

*********************

the more is see,less i know

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

Hello, I am also a newbie in AVR and I just have one question " Why do we not use delay functions provided in library of WinAVR r Codevision for time delays as it also provides accurate time delay and why we use timer for this purpose?"

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

Because when you use software delays the program can do nothing else.

Regards,
Steve A.

The Board helps those that help themselves.

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

Thank you very much for this tutorial! It is very useful!

Although, one thing isn't clear for me. Why do I have to subtract 1 when I determine OCR value?

For example (in CTC mode): the MCU's frequency is 1Mhz. Prescale value is 8. Then the timer's frequency is 125kHz, so one clock means 8us.
If I want 2ms delay then I will need 250 cycles, because 250 * 8us = 2ms.
The counter's starting value is 0, and every cycle increments it by 1 and we have to count up to 250.
So my OCR value is 250 or not?

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

B_Adam wrote:
So my OCR value is 250 or not?
No. Imagine you set it to 2, then the timer counts:
0,1,2, 0,1,2, 0,1,2, ...
As you see there are 3 timer steps per cycle, thus dividing the clock by 3.

Stefan Ernst

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

Thanks for your answer!
I thought about that, because in the programmers world counting always starts from 0. :)
But I thought, as the timer default value is 0, after the first cycle its value 1 and so on... And when OCR value matches timer value then timer will be automatically modified to 0 - without a new cycle, this is why I thought that 0 is not included.
With other words: at start TCNT0 = 0, OCR0 = 2. After the first cycle TCNT0's value is 1, isn't it?

I am confused by this a little bit. :S

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

Don't fret. It's simply the case that 0 *is* a whole "tick" in CTC mode so you do set OCR to the calculated N-1 not N.

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

Okay, thank you!

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

Great tutorial! You let me finish my job today! Flawless victory :D Thanks a lot. Ciao ;)

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

That's an awesome tutorial Dean. I am new to use AVR. Can you clarify me about one thing, Does we need to provide any external clock source at T0/T1 pins of ATMEGA32 in normal mode either with or with out Prescaler value's.

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

Quote:

Can you clarify me about one thing, Does we need to provide any external clock source at T0/T1 pins of ATMEGA32 in normal mode either with or with out Prescaler value's.

No, you can drive all the timers from the CPU clock, either prescaled or unprescaled if you wish. The external clock (or, in some cases, external asynchronous crystal) timer clocking options are there only if you want to use them.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I have tried the same program in ATMEGA32 but i am not getting the delay as per the calculations. So can some one help me out please.

What is the frequency of the clock that is provided with in the Micro-Controller ATMEGA32. If possible can you reply with the calculation procedure.

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

Quote:

What is the frequency of the clock that is provided with in the Micro-Controller ATMEGA32. If possible can you reply with the calculation procedure.

If you have not done anything (specifically changed CKSEL fuse bits) then it is around 1MHz as with most AVRs when they ship from the factory.

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

Thanks a lot for this tutorial!

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

Great tutorial!, Im starting with AVRs and it really helped me out to understand timers, now Im want to undestand PWM. I understand the theory in counters, but Im try to execute the example codes in atmel studio 6 and nothing happens I mean, the program starts and the cycle counter counts up to 1 million (1 Mhz in the speed) and I wait a while and it never toggles the port... should I have any extra considerations?..

Thanks!! and sorry about the poor english.

Alex

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

Are you talking about simulation? Don't trust it - especially in the area of PWM.

But if it won't work in a real AVR maybe start a thread including your code in AVR formum.

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

clawson wrote:
Are you talking about simulation? Don't trust it - especially in the area of PWM.

But if it won't work in a real AVR maybe start a thread including your code in AVR formum.

Im waiting for a stk600 to arrive, until then I'm trying to learn all I can.

Im not testing PWM in the simulator, what I want to do its a simple blinkin led within 1 sec delay. I am using abcminiuser's tutorial from his website.

should I post a new threat or it is correct to post it here.

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

New thread - this one is only for feedback on the article in the first post.

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

Dean and anyone else reading,
I am quite new to AVRs and I used your excellant tutorial once before with a Tiny 13 and got it to work fine, but am now trying to do same with a mega48 and can't get it to fire interupt.
Any ideas - code below

#define F_CPU 8000000UL
#include
#include
#include
#include

void ctc_init(void);

volatile unsigned char CRA=99;
volatile unsigned int Sec_count=0;

int main(void)
{
	DDRD|=(1<<PD0)|(1<<PD3);//output leds 
	PORTD &=~(1<<PD0);//set output low if in any doubt!!
	PORTD |=(1<<PD3);//led on
	ctc_init;
	sei();
	
	
    while(1)
    {
       _delay_ms(250);
	   _delay_ms(250);
	   PORTD ^=(1<<PD0);//So I can see something happening 
    }
}
void ctc_init(void)//initiate ctc
	{
	TCCR0A|=(1<<WGM01);//Set timer for CTC mode  
	OCR0A=CRA;//99 for 40MHzInitial value to match in output compare register =24in decimal.
	TIMSK0|=(1<<OCIE0A);//This should enable Output compare Interupt on Match
	TCCR0B|=(1<<CS00);// setting pre-scaler bits- I want no pre-scaler 001 = no pre-scaler
	//TCCR0A|=(1<<COM0A0);//Switch on the Compare register output
	}
		
ISR(TIMER0_COMPA_vect)//timer interrupt routine - wont overflow because in CTC mode it is reset.
{
	Sec_count++;
		if (Sec_count >=4000)
		{
			Sec_count=0;
			PORTD^=(1<<PD3);
		}
}

Thanks
Mark

markah

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

Your ctc_init() function won't be called, because you are missing brackets around the invocation here:

   PORTD |=(1<<PD3);//led on
   ctc_init;
   sei(); 

This causes the compiler to assume you want the function address rather than a function call, which it then sees you don't use and so the line is assumed to have no effect and is discarded.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Schoolboy error! Thanks so much.
Mark

markah

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

Hi,

I wondered how to change of frequency in CTC mode ?
In fact, I create a 3125Hz(tim0) during 62.5ms(tim1) then a 3945Hz during 62.5ms but in my case the second frequency is incorrect.
In my opinion, I forgot a detail between my two config.
Is there any way to reset timer and create a new config ?

Thanks for your help.

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

First of all, Thank you so very much, Dean, for this tutorial, helped me a lot!

I have one, probably silly, question. On the pure hardware CTC, I noticed that in the final example, CTC flag is not being cleared. In the interrupt mode, it gets clear automatically, but without interrupt, you had to clear it with "TIFR = (1<<OCF1A)". In the pure hardware example, does it also automatically get cleared like in interrupts? I found only statements about the "auto-clear in interrupts" and "setting it to clear" parts in the datasheet of ATmega32u4.

Thanks again.

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

Quote:
In the pure hardware example, does it also automatically get cleared like in interrupts?
No, it does not get cleared, but this is inconsequential since nowhere in code is that flag being used.

Regards,
Steve A.

The Board helps those that help themselves.

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

Oh, yeah. Thanks!

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

Great article, I just started developing firmware and this has given me so much information to build USART and PWM for a ATTiny48.

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

I have to say, this is the absolute best tutorial on anything which I have ever read. Thanks so so very much for this! I will go over this a few times to make sure I understand everything, but it is so well organized and explained that I am certain I will understand everything perfectly.

Pages