[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

Thanks for the heads up on chapter 7, Dean.
Superman has no need to apologize to us mortals for being faster than a speeding bullet.

Dean thanks so much for all you do for the Freaks,
John

Resistance is futile…… You will be compiled!

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

Dean,

Wonder if I'm the only one who thinks more easily in terms of timer period rather than timer frequency? The 16bit, 1MHz overflow table would therefore be:

Prescaler Value | Overflow Frequency | Overflow period
              1 |  15.259 Hz         |   65.5  ms
              8 |  1.907 Hz          |   0.524 s
             64 |  .2384 Hz          |   4.195 s
            256 |  .0596 Hz          |   16.78 s
           1024 |  .0149 Hz          |   67.11 s

I can get more excited about "67 seconds - like wow!" than I can about 0.0149 Herz which is very difficult for a human brain to "visualise"

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

Quite right Cliff - I've updated the tutorial. Thanks for the feedback guys!

- Dean :twisted:

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

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

This is the code I am using. When I run it, portb jsut stays low. Is it possible there are some fuse settings that would mess this up?

#include 
#include 

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

   	//TCCR1A = 0;
   	TCCR1B |= (1 << WGM12);
   	OCR1A   = 15625;
	TCCR1B |= ((1 << CS10) | (1 << CS11));
	sei();
   	while(1)
   	{
      	if (TIFR & (1<<TOV1))
      	{
          	PORTB ^= (1 << PB0); // Toggle the LED

          	TIFR = (1 << OCF1A); // clear the CTC flag (writing a logic one to the set flag clears it)
      	}
   	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're using the CTC mode of the timer, but polling the overflow interrupt bit (TOV1). You want to instead check for the compare match bit, which is OCF1A.

- Dean :twisted:

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

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

first sorry for bad english and thanks for this tut.

but i have some problems with chapter 7
in your final code there is TIMSK1

Quote:
TIMSK1 |= (1 << TOIE1); // Enable overflow interrupt

why TIMSK1 and not TIMSK, TIMSK1 causes compiler warnings ?

and when i compile without

#include 

there are warnings too.

greets from germany

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

You're right, the first was a typo, the second an error of omission. You do need the header file, and it is indeed just TIMSK, not TIMSK1 as I wrote down.

Thanks for the feedback, I've corrected the tutorial.

- Dean :twisted:

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

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

hi, I,m just started learning the AVR and i having some problem to understand the following code so can anyone give me a help or guidance . thanks

i)if (TIFR & (1 << OCF1A)) // can explain what this condition mean?

ii)for 16bits timer , is this after counter to 65535 then it will restart over again from 0? unless the overflow setting is select then i will exceed the limet .

Location : Singapore

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

1) that line is simply checking whether the OCF1A bit is set in the TIFR register. You probably need to read the "101" thread in the Tutorial Forum to really understand the syntax

2) not quite sure what you are asking but yes a 16 bit timer counts 0 to 65535 and then overflows back to 0 (unless it's in one of the modes that sets a low limit for it to count to)

Cliff

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

hi Dean,

wow what a detailed guide you have in this topic... it's really cool... looking forward for your PWM posting... how do i keep a update of what you have posted? i worried that i missed it and as a result i have to read all your post and editing at one whole shot... which will spend me lots of time to understand and follow...

so can anyone tell me how to keeop myself update for Dean's or anyone's new tutorial posted?

will*

hi wish to learn more about programming stuffs so do add me in msn for me to learn for you better... :)

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

Next time you post a message to a thread you want to monitor put a tick in that box to the left that says "notify me when a reply is posted"

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

o ok.. hi clawson again.. thanks.. hehe... em actually i wanted to know is like when someone, eg you, dean, etc, have a new topic being posted in AVR and when you all do the 1st posting, i will be notify about it... so i can go take a 1st quick look at the start of the tutorial posted...

thanks again :)
will*

hi wish to learn more about programming stuffs so do add me in msn for me to learn for you better... :)

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

i'm newbie
thank you very much! :P

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

abcminiuser, I wanted to thank you for putting together this amazing tutorial. It is very easy to read and quickly got me up and running using timers. They really aren't as mysterious and difficult as I originally thought they were. :)

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

Thanks for the compliments guys! Rest assured that when I get some free time, the next chapter will be written. I think it's about time to start on the PWM side of things....

- Dean :twisted:

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

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

Hey guys, I'm rather new to AVRs, anyways this might not be the most appropriate place to ask this, but I have an stk500 board with a mega8515 installed on it right now. And I'm only able to set the STK500 oscillator to 921.6 kHz. (I've tried typing in 1Mhz and writing to the chip, but once I read it I get 921.6 kHZ back)

Is there anyway I can force the chip to run at 1 Mhz? Or is the 921.6 kHz the closest I can get?

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

hello,

am i the only one who gets a error on this sentence code :

TCCR1B |= (1 << CS10); // Set up timer 

i get undefind symbol CS10, do i have to include someting to get it work?

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

What AVR?
you did include atleast avr/io.h?

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

bloody-orc,

That was actually a cross-post that's been answered in AVR Forum - his problem is that he's using CV where the reg names (TCCR1B etc.) are defined but the bit names (CS10 etc.) are not. For anyone reading this later the solution (as posted to the other thread) is to use xmlconvert to generate a set of .h files with bit definitions.

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

Hey Dean good work on all of this. Just wondering if you have completed your PWM tut or if it's posted. I didn't find it in search. I am looking for a PWM tutorial to reference; don't want to 'rewrite the wheel'.

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

Quote:

Hey Dean good work on all of this. Just wondering if you have completed your PWM tut or if it's posted. I didn't find it in search. I am looking for a PWM tutorial to reference; don't want to 'rewrite the wheel'.

Sorry, not yet. I've been (and still am) busy trying to complete all my end-of-year Uni assignments so I can pass the course for this year. I'll try to start writing it next week, but my time is very limited until the holidays in about four weeks, so don't expect it to be all done for at *least* two weeks. Sorry for the inconvenience.

- Dean :twisted:

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

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

Quote:
Sorry for the inconvenience.

Are you kidding?? Your readers should be apologizing for the inconvenience! Keep up in school it should come first. Cheers.

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

Thanks for the marvelous tutorial. This was written perfectly, and with a good understanding.

Many tutorials go over my head and assume I know what TOIE or OCR1H is. But you did a very good job at explaining what the functions are, and how to handle them - in normal basic terms.

If you write a book, I would probably buy it!

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

Hi guys,

This is my first attempt to post, as I'm a total newbie both to AVR and forums,

I've been watching this forum for some time, and i have learned a lot, and when I found this excellent tutorial,
I was amazed with the simplicity of it that guided me, I did all the experiment I found here with no problem, then I combined a code, which drove me nuts :shock: I realized that I'm not even a newbie

here it is , I'm trying to make an 8 bit counter on the stk500, I'm using the following
AVR Studio 4.13.557 Service Pack 1
GUI Version 4, 13, 0, 557
JTAGICE mkII 1, 0, 1, 140
ATmega644 77

the code I wanted to run is this.

Code display:

code
#include 
#include 

uint8_t led;

ISR(TIMER1_OVF_vect) {
	led++;
	PORTD = ~led;	
}

int main(void) 
{
	DDRD=0xff;
	TIMSK1 = 1<<TOIE1; 	 // enable timer overflow interrupt enable
	TCNT1 = 0 ; 	         // set timer counter   initial value
	TCCR1B = (1<<CS11  );    // start timer with FPU / 8
	sei();			 // enable interrupts
	led = 0x00 ;		 //Initial led value

	for (;;) {}		 // loop forever timer interupts will change the led value 
}

This works with no problem, I geta an 8bit LED counter at near 1 second intervals.
but when i move the "PORTD = ~led;" to the for loop, interrupts work, led var increments, but the LEDs won't change state,
I tried by clickin on the PORTD bits in the I/O view interface , it's Ok LEDs state change , but for some reason the instruction "PORTD = ~led;" does nothing inside the for loop;

here is the zombie code:
Code display:

#include 
#include 

uint8_t led;

ISR(TIMER1_OVF_vect) {
	led++;
}

int main(void) 
{
	DDRD=0xff;
	TIMSK1 = 1<<TOIE1;    //enable timer overflow interrupt enable
	TCNT1 = 0 ; 	      //set timer counter   initial value
	TCCR1B = (1<<CS11  ); // start timer with FPU / 8
	sei();		      // enable interrupts
	led = 0x00 ;	      // Initial led value

	for (;;) {	      // loop forever timer interupts will change the led value
        PORTD = ~led;    /**led var counts but  NOTHING CHANGES **/
        }
}

How comes the instruction cannot change the data on the port?
before I call myself a total idiot :oops: rather than total newbie,Can anyone please explain me why is this happening?

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

What optimisation level do you use?
With no optimisation it should work.
With -oS it won't.
The reason is that with higher levels of optimisation the compiler will guess (wrongly) that led never changes and so remove your code. Cheeky isn't it?

the 'volatile' keyword is what you want when you declare led. This is generally the case when a variable is changed/used in an ISR and the main thread.

The other time it is commonly needed is if you are setting up an external memory mapped peripheral, such as a UART or a SCSI chip. Here you might send multiple commands to the same address, and the last thing you want is for the compiler to decide, "the last value written was 0x3b, I don't need to write the earlier ones". That is wrong.

volatile uint8_t led;

'volatile' tells the compiler, "I know what I'm doing. Don't get fancy and change anything to do with this variable. OK?"

Inspect the disassembled code to check this.

see FAQ#1 at the end of any posting from clawson (you won't have to wait long!!)

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

Wow! thank you Broxbourne, You're fast, I wouldn't have guessed the answer, not at all, not in my lifetime....
so tricky, so the compiler says " you don't know what you're doing and I know better"???

I just added 'volatile', and it worked, but still the configuration is selected -oS,
where can I find more details about this optimization and compiler behavior ?
and thanks again and again..... :D

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

Quote:
where can I find more details about this optimization and compiler behavior ?

Some of the big guns can probably explain the differences between the various optimisation settings, but it is out of my league. The manuals are the ultimate reference if you really want to know it all, but sometimes a pointer helps to direct your learning.
I'm always glad to find a question I can actually answer correctly :wink:

'volatile' works for all settings. The idea is that a volatile variable can change at any time, independent of how the program is running, so it must be left untouched (as written by you).

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

Alain,

Believe it or not but the volatile question is answer number 1 in the FAQ section of the avr-gcc manual:

http://www.nongnu.org/avr-libc/u...

If you haven't read the manual yet now might be a good time to have a skim through.

By the way those should be / and not \ in your #include's

Cliff

PS both PDF and HTML copies of that user manual exist on your hardrive in \winavr\doc\avr-libc\

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

Hi Dean,

After reading your article, I decided to try it out with my ATmega16 which runs on a 16 MHz clock source. I decided to go with the CTC mode to toggle an LED at 1 Hz.

My calculations are as follows:
Input frequency = 16 MHz

Timer Resolution = 1/(Input frequency/Prescale)
= Prescale/Input frequency

Prescale Resolution @ 16 Mhz
1 1/16MHz = 0.0625 uS
8 8/16MHz = 0.5 uS
64 64/16MHz = 4 uS
256 256/16MHz = 16 uS
1024 102/16 MHz = 64 uS

Target frequency = 1 Hz

Target timer count = (1/target frequency) / (Prescale/Input frequency)

Using the above formula I got the following values:

Prescale Target timer count
1 16000000
8 2000000
64 250000
256 62500
1024 15625

Using a 16-bit timer I decided to go with a prescale of 1024

This is the code I have used:

#include 

int main(void){

	DDRB |= _BV(0);

	TCCR1B |= ((1 << CS12) | (1 << CS11) | (1 << CS10));	//fCPU/1024
	
	TCCR1B |= (1<<WGM12);	// Configure timer 1 for CTC mode

	OCR1A = 15625;	// Set CTC compare value to 1Hz at 16MHz AVR clock, with a prescaler of 1024

	for(;;){
		if(TIFR & (1 << OCF1A)){

			PORTB ^= _BV(0);	//toggle LED

			TIFR = (1 << OCF1A); // Clear the CTC flag (writing logic one to the set flag clears it)
		}
	}
	return (0);
}

However, the LED did not toggle at all.

What could be the problem?Do you think the calculations are wrong?

Thanks for your help.
Regards,
Sumair

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

Hi Dean,

After reading your article, I decided to try it out with my ATmega16 which runs on a 16 MHz clock source. I decided to go with the CTC mode to toggle an LED at 1 Hz.

My calculations are as follows:
Input frequency = 16 MHz

Timer Resolution = 1/(Input frequency/Prescale)
= Prescale/Input frequency

Prescale Resolution @ 16 Mhz
1 1/16MHz = 0.0625 uS
8 8/16MHz = 0.5 uS
64 64/16MHz = 4 uS
256 256/16MHz = 16 uS
1024 102/16 MHz = 64 uS

Target frequency = 1 Hz

Target timer count = (1/target frequency) / (Prescale/Input frequency)

Using the above formula I got the following values:

Prescale Target timer count
1 16000000
8 2000000
64 250000
256 62500
1024 15625

Using a 16-bit timer I decided to go with a prescale of 1024

This is the code I have used:

#include 

int main(void){

	DDRB |= _BV(0);

	TCCR1B |= ((1 << CS12) | (1 << CS11) | (1 << CS10));	//fCPU/1024
	
	TCCR1B |= (1<<WGM12);	// Configure timer 1 for CTC mode

	OCR1A = 15625;	// Set CTC compare value to 1Hz at 16MHz AVR clock, with a prescaler of 1024

	for(;;){
		if(TIFR & (1 << OCF1A)){

			PORTB ^= _BV(0);	//toggle LED

			TIFR = (1 << OCF1A); // Clear the CTC flag (writing logic one to the set flag clears it)
		}
	}
	return (0);
}

However, the LED did not toggle at all.

What could be the problem?Do you think the calculations are wrong?

Thanks for your help.
Regards,
Sumair

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

EDIT: The post below by me is not correct. I am leaving it here only so as not to disturb the flow of the thread, but please be aware that the information given is not correct.

ORIGINAL POST:

   DDRB |= _BV(0); 

If you want to set PORTB pin 0 as output the above wont do it. This will:

   DDRB |= _BV(1<<0); 

For more information on things like "1<<0" look in the tutorials forum for the tutorial named Bit manipulation (AKA "Programming 101").

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Nov 4, 2007 - 09:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Johan,

I tried your suggestion, but still couldn't get it working. I tried both the statements without much luck :(

DDRB |= (1<<0);

DDRB |= _BV(1<<0);

I am not sure what else could be wrong?
Sumair

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

you are moving 12 0 places to the left. so this is hardly doing anything... What are you actually trying to do? turn PB0 an output?

DDRB |= (1<<PB0);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys,

Actually I realised my mistake now. My actual clock source which comes from a 16 MHz crystal was running at 1 MHz speed. I found this out from the following extract in the ATmega16 datasheet:

Quote:

The device is shipped with CKSEL = “0001” and SUT = “10”. The default clock source setting is
therefore the 1 MHz Internal RC Oscillator with longest startup time. This default setting ensures
that all users can make their desired clock source setting using an In-System or Parallel
Programmer.

So I then modified the code as below, and there I got my LED toggling :)

#include 

int main(void){

	DDRB |= (1 << 0);	//set PB.0 as LED output

	TCCR1B |= (1 << WGM12);	// Configure timer 1 for CTC mode

	OCR1A = 15625;	// Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64

	TCCR1B |= ((1 << CS11) | (1 << CS10));	//start timer at fCPU/64

	for(;;){
		if(TIFR & (1 << OCF1A)){

			PORTB ^= (1 << 0);	//toggle LED

			TIFR = (1 << OCF1A); // Clear the CTC flag (writing logic one to the set flag clears it)
		}
	}
	return (0);
}

All this time I was thinking that my code was running at 16 MHz crystal clock source....silly me.
But thanks for all your help guys, appreciate you all replying to my queries :)

It would be really nice if someone could explain how to use the actual supplied clock source (in my case 16 MHz crystal).

Regards,
Sumair

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

Did you change the MEGA16's fuses from their default settings? If not, your AVR will still be running from its internal 1MHz RC oscillator, even if you have a 16MHz clock source of some description set up. That would cause the program to run at 1/16 the speed, so your 1Hz timer would take a full 16 seconds to reach your compare value.

- Dean :twisted:

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

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

Hi Dean,

Well I haven't changed the ATmega16's fuse settings as I don't know how. Earlier I was just experimenting assuming that it was running @ 16MHz.But i changed the code as above, and I got an exact 1 sec delay for toggling the LED.

Is there a tutorial you can point me to for programming those fuses?You see I am a newbie and still learning :)

Thanks,
Sumair

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

Sorry, no tutorials that I know off the top of my head (and I'm glad my timers tutorial worked out for you!). It's quite easy however if you're using AVRStudio for your programming - the fuses tab makes it as simple as checking the desired setting's box and pressing program.

- Dean :twisted:

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

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

Great tutorial! It got me going into timer events in no time!
Just a small remark about your counter calculations:
If you'r using a 1MHz clock this means you have 1,000,000 cicles per second ;-)
So you will have to count until 1,000,000 to have an event for each second. Of course your counter will overflow because you only have 16 bits, so you have to use the frequency division but as you program in C you can write down:
// CTC value to 1Hz at 1MHz clock, prescaler of 64
OCR1A = 1000000 / 64;

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

The complete code for my last comment would be:
// CTC value to 1Hz at 1MHz clock, prescaler of 64
OCR1A = 1000000 / 64;
// Start timer at Fcpu/64
TCCR1B |= ((1 << CS10) | (1 << CS11));

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

Hi Dean,

I did change the fuse settings to run @ 8 MHz and I could get my LED toggling at 1 Hz with a few calculation and code changes.Thanks for letting me know that.

However, I have created a new problem for myself :(
I accidentally clicked on some fuse setings for the clock settings and now I am unable to program my AVR. I tried erasing the device too, but I keep getting this error:

Entering programming mode.. FAILED!
Leaving programming mode.. OK!

I am using the AVR Studio version 4.13.I am using the ISP mode to program the AVR. I get an "ISP Mode Error" pop-up each time I click on program or erase the device.Appreciate any help on this as I am unable to proceed due to these errors.Please see the attached screen shot of the error pop-up.

Thanks,
Sumair

Attachment(s): 

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

I wrote:

   DDRB |= _BV(0); 

If you want to set PORTB pin 0 as output the above wont do it. This will:

   DDRB |= _BV(1<<0); 

Upon returning from the weekend trip I re-read this, and realized what a load of crap this posting of mine is. I honestly can not figure out what part of my brain actually did that. Sorry for any confusion I might have created...

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Sumair,

Did you catch which fuse setting you changed your AVR to? Chances are you changed it to use an external *clock* rather than an external *crystal*. They're two seperate things, and one will not work with the other attached.

To fix your AVR, you could either use a Dragon/STK500 in parallel programming mode, or feed in a fast clock into XTAL1 via an external source (such as a square wave oscillator made from a NES555). Just remember to reduce your ISP programming speed to at most 1/4 of the speed of the clock you input into the AVR when taking the latter route.

Once you regain communications with your AVR, change the fuses to use an external crystal and resume normal operations.

- Dean :twisted:

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

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

Hi Dean,

I guess I'll try feeding in an external 1 Mhz clock using a 555 timer. Hope it works otherwise I'll have to replace my microcontroller with a new one :) as I don't have parallel programming capability on my development board.

Thanks for your help.
Sumair

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

Hi Dean,
Just wanted to say "hats off" for that great, easy to follow tutorial.:lol: You really should write a book. I'd buy it sight unseen.

Your style of changing only one variable at a time and fully explaining every parameter and each step of the process makes seemingly complex things, easy to understand. Keep up the great work!

Lachlan

What we need to learn,
we learn by doing.

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

Cheers Lachlan!

I try to write my tutorials in a way that I would understand, which is usually simple and verbose enough for the majority to learn from. I do like changing only one variable at a time; I've had years of maths texts doing multiple operations in one step, which causes me to get lost quite easy.

No plans on writing a book at the moment, but it's certainly not out of the question. I'd hate to muscle in on the fellow forum's members livelihoods (such as Smokey) and don't currently have the time.

- Dean :twisted

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

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

hi everyone ,

I have a question.Regarding the Part Five - CTC Mode using Interrupts , by changes [/code] OCR1A , I able to control the interval of interrupt...But is that a way for me to control when I wan to start my interrupt, other then let the interrupt fired thoughout the whole program ?

Location : Singapore

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

You have plenty of control over the timer. You could turn the timer on and off (via the prescaler bits - turn them off to disconnect any clock to the timer circuitry) which would halt the count. You could change the TOP register in CTC mode to change the interval.

If what you want is to allow the timer to keep running but block the CTC interrupt until you want it to occur (defeating the point of having a known interval in the first place), you could just disable the CTC interrupt enable bit in the timer control registers. When you're ready to process it again, re-enable the bit and if the CTC event occurred while the CTC interrupt was disabled, it will immediately fire the ISR.

- Dean :twisted:

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

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

Hi Dean, thanks for the prompt reply, but now we have another problem. We have programmed our interrupt function to calculate a value. Is it possible to return a variable from the interrupt function or can we just declare the value as a global variable?

Location : Singapore

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

ISR's can't return values directly - where would the return value go to? You need to use a global, and mind that you make the variable volatile (do a search on 'Freaks for an explanation) if you want to share the value between the ISR and your main code.

- Dean :twisted:

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

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

Hi Dean,
thanks for ur advice..
We have declared our variables below:

unsigned volatile int verticalspeed=0; 
int volatile reference=0;
int volatile altitudeR_int=0;

int main(void)
{
// initialise interrupt here
while(1)     
{
// at here the altitudeR_int  changes according to our sensor 


printf("Pump ON \n" );
printf("Altitude= %d ft \n", altitudeR_int);
printf("reference= %d mb \n",reference);
printf("verticalspeed:%u ", verticalspeed);
}

}


ISR(TIMER1_COMPA_vect) 
{ 
verticalspeed=((altitudeR_int-reference)*60);
		
reference = altitudeR_int;
  	
} 

Is this the correct way of using voletile global variables to return the verticalspeed into the main?

Location : Singapore

Pages