1 second counter

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

Hi all,

I'm trying to create a 1 second counter or something close to that. I'm using atmega 2561, external ossilator 7372800. Coding in C, using avr studio.
I was able to get timer1 to interrupt about every 2 seconds, but my problem is I can't use an interrupt, because I want to count everytime the timer goes off, but I use other interrupts and I noticed, like if I pushed a button, the timer count wouldn't increase( it basically won't go into the interrupt, since it was in an interrupt).

How would I read the data, without having to use the ISR? I'm currently using 256 prescaler (TCCR1B = 0x04)

Thanks in advance

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

Exact 1 second -> 1/(1024/7372800)=7200 timer ticks.

RES

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

RES, ty for the reply, thanks I was able to get the 1 second interrupts, but how do I read the data without using interrupts?

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

Something's a little fishy here. Maybe you're spending way too much time in your interrupt handler(s). It shouldn't be too difficult to accomplish what you want (provided I am understanding it). If you'd post some code and/or be a little more specific, we'd be able to offer more help.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

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

Quote:

Maybe you're spending way too much time in your interrupt handler(s).

"Maybe"?!? It has to be about 2 seconds, or consistently over 1 second, for a 1-second timer to "fail".

Lee

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

Sure Chuck:

Timer init:
TCCR1A = 0x00;	
TCCR1B = 0x00;
TCCR1C = 0x00;
TCNT1H = 0xE3;
TCNT1L = 0xDF;
CLEARBIT(TIMSK1, TOIE1);

Set timer function:
void SET_TIMER1() {
SETBIT(TIMSK1, TOIE1);
TCCR1B = 0x05;
TCNT1H = 0xE3; //0F
TCNT1L = 0xDF; //82
}
Timer off:
void TIMER1_OFF()
{
TCCR1B = 0x00;
CLEARBIT(TIMSK1, TOIE1);
}

ISR:
ISR(TIMER1_OVF_vect) {
CLEARBIT(TIFR1, TOV1);
printf("\n\rTICK\n\r");
timeTicks++;
TCNT1H = 0xE3; 
TCNT1L = 0xDF;
}
btn6 interrupt
SIGNAL(SIG_INTERRUPT6) {
CLEARBIT(EIFR, INTF6);
printf("\n\rtimeTicks=%i", timeTicks);
}

I also use INT 1 , 5 ,and 6 for buttons, but they just start, stop, and read the timer data respectively.
When I press btn 6, to read the data and then let it continue, I miss a few ticks.

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

Found a work around, decided to poll the push buttons instead and let the timer still interrupt, works good enough now. Thanks everyone!

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

I need to comment that you really, really, really don't want to be calling printf inside an interrupt routine. What you can do instead is to set a flag (i.e. a volatile uint8_t) in the ISR and check that flag in your main idle loop. When the flag gets set by the ISR then do the printf in the idle loop and reset the flag.

Mike

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

Quote:

ISR: 
ISR(TIMER1_OVF_vect) { 
CLEARBIT(TIFR1, TOV1); 
printf("\n\rTICK\n\r");


printf() in an ISR? That is a very, very bad idea - printf() can take 10's or even 100's of ms.

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

printf removed, I was just using it for testing, just to see if the ticks were close to on time(1 second ticks).

Question though, is it just printf that take up some much time or is it any printing period? Like if I were to print directly to the uart (UDRx = ch) ?

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

An ISR should aim to complete in an absolute maximum of 100 cycles (if that) because while an ISR is being serviced (usually) interrupts are disabled and so if two interrupts on another source occur during that time one will be lost. The bottom line is "lean and mean". Do any "long work" in the main() code that has all the time in the world. Just have the ISR set a flag to say that there is some work to be done.

On the other hand I guess you can do UDR=c in a few cycles but it's the waiting for UDRE to be set before you can do this that could take 100's

Cliff

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

Makes perfect sense, thanks for the info

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

If you're just immediately stuffing a char in UDRx that's fine. If you're looping waiting for the TX buffer to be empty that's another matter, and I wouldn't do that. Either check the buffer empty flag just once each INT, or set a flag and have a background task (in your main idle loop) check the flag and stuff the UART. Or just set up a UART ISR that stuffs the next char every time the buffer is empty, with no time wasted busy looping at all.

Mike

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

Oh, I see Mike, much easier to just set a flag and print in the main and avoid any timing issues.

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

bootloadernoob wrote:
Oh, I see Mike, much easier to just set a flag and print in the main and avoid any timing issues.

Right. Writing interrupt code is always a juggling act. You do what you absolutely must do in the interrupt, and you leave the rest to be done by code outside of the interrupt routine. This makes your interrupt routine responsive, and also keeps your entire system (including all the other interrupts that may occur) responsive as well.

Sometimes, with simple systems, you may have the luxury to spend lots of time inside an interrupt routine, but in general you want to train yourself to avoid that, because it's almost always not the right thing to be doing.

Mike