suggestions on handling timer interrupt for a clock

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

Hello all I just got a atmega16 board part of my first task is going to make a clock display on my LCD i have a 8Mhz system clock. SO i have 2 questions
1) my question is about how to do this my current process i setup interrupt, my interrupts are 8Mhz/64 = 8us , im using TCNT0 so max count is 255 but im actually counting to 250 boosting my count now to 2us, from there another count of 500 gets my a 1sec count. once i get the 1 sec count im not sure how i should handle the timer update. what im thinking is increment a minutes variable exit the interrupt. and let a task update the LCD. does anyone know a better approach since interrupts are suppose to be short im not sure i can do anything else there.

--below is a sample of my code

ISR(TIMER0_OVF_vect)
{
	/* count of 250 is what is needed to get 1sec delay 255 - 6 = 250 remember 0 is included in the count */
	TCNT0 = 6;

	/* will give a 1sec delay */
	if(timecountms++ >= 500)
	{
		timecountsecs++;
		timecountms = 0;
	}
}
/* the task is currently just a while(1) in main */
		if(timecountsecs >= 60)
		{
			//reset timecountsecs
			timecountsecs = 0;
			// update time on LCD
			if((minutes - 60) <= 0 &&(minutes >= 0)) //only update when minutes is 0-59
			{
				if(ledOn == NO)
				{
					turnOnLED(LED1);
					ledOn = YES;
				}else
				{
					turnOffLED(LED1);
					ledOn = NO;
				}
			minutes += 1;	// ever 60secs update minutes
			}
			else if((hours - 12) <= 0 &&(hours >= 0))
			{
				hours += 1;	//every 60 minutes update hours
			}
			else if((hours) < 0 &&(hours > 60))
			{
				hours = 0;	//reset if hours are invalid
			}
			else if((minutes) < 0 &&(minutes > 60))
			{
				minutes = 0;	//reset if minutes are invalid
			}
		}
	}

2) does anyone know how to use Eclipse as a debugger i keep getting errors it builds fine in eclipse but i have to port the .elf over to avr studio for debugging also it only shows me the dissembler not the actual c code.

thanks in advance[/code]

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

Quote:

1) my question is about how to do this my current process i setup interrupt, my interrupts are 8Mhz/64 = 8us

On 8MHz that means the CPU has just 64 cycles to service the interrupt. As long as the AVR is doing virtually nothing else you should be OK but I'd check the worst case path through your ISR and make sure it can complete in 64 cycles. Personally I'm dubious. Why on earth don't you prescale the timer s it only ticks once every ms (perhaps 10ms, 100ms or even 1s)

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

I think you can make use of the 16 bit timer in 'Clear Timer on Compare' mode to get accurate delay of 1 sec or else you can make use of the Real time Counter. You can connect an external RC(32.768KHz) as input for the RTC. Dividing the 32.768KHz with a prescaler of 128 and having the 8-bit timer overflow interrupt will give you the exact delay.

For processing the hours, minutes and second you can wirte nested if s rather than if else if. After processing the timer variables you can set a flag which could be monitored for updating in the LCD.

-Krishna Balan S

-------------------------------------------------------------------------

"Heroes are ordinary people with extraordinary commitment"

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

clawson wrote:
Quote:

1) my question is about how to do this my current process i setup interrupt, my interrupts are 8Mhz/64 = 8us

On 8MHz that means the CPU has just 64 cycles to service the interrupt. As long as the AVR is doing virtually nothing else you should be OK but I'd check the worst case path through your ISR and make sure it can complete in 64 cycles. Personally I'm dubious. Why on earth don't you prescale the timer s it only ticks once every ms (perhaps 10ms, 100ms or even 1s)

To get that type of tick i would need to use the 16bit timer right?
so you would recommend using the 16bit timer for this type of excerise?

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

Quote:

To get that type of tick i would need to use the 16bit timer right?

What "type"?

First, what is the source of your "8MHz system clock"? Internal oscillator? How accurate do you think that will be?

With /1024 the reach of an 8-bit timer at 6MHz is 32ms. Thus, 10, 20, 25 milliseconds are convenient.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

That is a poor way to limit count, please use Clear On Compare feature so the hardware counts from 0..249 (250 ticks) instead of 0..255 (256 ticks) or whatever you like. That makes it spot on accurate.

Also you better have a crystal or at least a resonator, if you only use the internal clock you have a very poor wall clock that does not keep time.

But what is the purpose of interrupting so often? You could keep time as good even if you interrupted once per minute or once per microsecond, just both extremes do not make any sense.

You can tweak the prescaler and count limit to create nice even human readable frequency for timer overflow.

Another way of keeping time is also to count oscillator ticks. At 8 MHz, 1024 prescaler, 256 counts, that means you can have a minimum timer frequency of about 30 Hz. Every overflow, you know 1024*256 counts has happened, and you know 8000000 counts means 1 second.

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

I dont care about the accuracy it doesnt have to be dead on as long as its within a few minutes its just something to do on the board as a part of a starting experiment. the clock is internal i want to limit the amount of extra items i need to buy for this board until i come up with a good project to do on it and i get more comfortable programming on it. thanks for the input ill change my prescaler to allow more time for other routines. Does anyone know how to get Eclispe to do debugging?

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

Eclipse will need to use avraice to act as a go between from avr-gdb to the debug interface. How you actually configure this I haven't a clue but if you search "avr-gdb avraice eclipse" here or in Google you may find something.

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

Along with everyone else's suggestions, you should read the tutorial [TUT] [C] Newbie's Guide to AVR Timers

Since you are doing this as an exercise, we'll forget about the accuracy arguments. When you become annoyed about how far off it is, look into using a 32.768 KHz crystal. On the larger AVRs, the oscillator for this crystal is tied to a 16-bit timer so getting a 1 second interrupt is trivial.

BTW, you should check out Newbie? Start here! since there are all kinds of cool pointers in there for you!

Have fun!

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

lol @ When you become annoyed Thanks for the tips

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

If accuracy is unimportant, you pretty much get the same accuracy if you just increase seconds after delaying one second like delay_ms(1000), instead of using timers the way you now do.

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

Quote:
TCNT0 = 6;

if you ever hope to have accurate (long-term) timing, you shouldn't "set" timer/counter from within the isr. because of latency / overhead, it is likely that when you start to execute your code in the isr, the timer/counter already has a value in it.

so instead of setting it, increment it like this:

   TCNT0 += 6; 

going back to your issue, I would set up a counter to do the counting separately. like this:

tmer_isr:
time_count+=0x100;  //for 8-bit timer. 0x10000 for 16-bit timer
if (time_count > TIME_COUNT_MAX) { //reached pre_set time?
  time_count-=TIME_COUNT_MAX;  //decrement time, retain timing errors
  time_update_flag=1;  //set update flag
}
...

main() loop:
  if (time_update_flag) {
    time_update_flag=0;  //reset time_update_flag
    update_time();  //update time

this approach utilizes a free running clock, retains timing errors so that it is accurate over a long period of time.

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

Quote:

so instead of setting it, increment it like this:

But if you ever find yourself doing that you are using the wrong timer mode anyway - use CTC - it's cycle accurate because the timer counts to N-1 then resets to 0 automatically - no jitter or over-head getting into an ISR to make a TCNT adjustment.

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

clawson wrote:
Quote:

so instead of setting it, increment it like this:

But if you ever find yourself doing that you are using the wrong timer mode anyway - use CTC - it's cycle accurate because the timer counts to N-1 then resets to 0 automatically - no jitter or over-head getting into an ISR to make a TCNT adjustment.
If timer issues get sufficiently hairy,
I leave the timer in free-running mode and adjust compare match values in ISRs.
Rather complex adjustable patterns are possible.
That said, when it works, which is often, CTC is tidier.

Iluvatar is the better part of Valar.

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

In my clock:
http://www.hoevendesign.com/#Net...
I use a timer to generate a 1ms 'tick'.
And evertything else is derived from that 'tick'.
But maybe the project is a bit complex for newbies.

But I tried pretty hard to make the code easy to understand.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

thanks for the tips. having new issues with my dev board now ill try to work through them first though