problem: program keep running in the ISR

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

hi all,

When i try to simulate my code using AVR studio, i found that after the first time the program enter the ISR, instruction will go lost.

The result from my PORTA just keep blinking.Why my counter wont continue counting until 10?

#include 
#include 
#define F_CPU 4000000

volatile int counter=0;

int main(void)
{
	
	DDRA= 0xFF;
	PORTA = 0xFF;

	TIMSK |= (1 << TOIE1);
	sei();
	
	//Preloaded value
	TCNT1 = 64535;

	TCCR1B |= (1<<CS11);

	while(1)
	{
	
	}

}

ISR(TIMER1_OVF_vect)
{
	
   counter++;

   TCCR1B = 0X00;	//OFF TIMER

switch(counter)
{
  case 10:	PORTA ^= (1 << 0);
  TCNT1 = 64535;

TCCR1B|= (1<<CS1);
break;					
}

PORTA ^= (1 << 0);
TCNT1 = 64535;
TCCR1B |= (1<<CS11);
}

thank you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      TCCR1B<<CS11);

What is that line supposed to be doing? Did you mean:

      TCCR1B &= ~(1<<CS11);

to stop the timer?

Also, rather than resetting TCNT1 in the ISR you'd be far better off using CTC mode.

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

Quote:
Also, rather than resetting TCNT1 in the ISR you'd be far better off using CTC mode.

do u mean dont use the overflow function but change it to CTC function mode for my timer1?

thanks.

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

If your intention here is to just have the timer 1 count from 64335 to 65535 and then overflow each time (that is count 1,200 ticks) then you'd be better off running in CTC mode with OCR1A set to 1200 (actually probably 1199 in fact because 0 counts too). Then TCNT1 will start at 0, count to 1199 then generate a compare interrupt and AUTOMATICALLY reset TCNT1 back to 0. This way there is no "jitter" (your present code has a delay between the start of the overflow interrupt process and the time at which you actually reset TCNT1 - CTC removes this "jitter")

Cliff

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

hi clawson,

i would like to get some advice on the programming style.

#include 
#include 
#define F_CPU 4000000

volatile int counter=0;

int main(void)
{
	
	DDRA= 0xFF;
	PORTA = 0xFF;

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

	TIMSK |= (1 << OCIE1A); // Enable CTC interrupt 
	sei();//global interrupt
	
	//CTC compare value
	OCR1A   = 1000;

	TCCR1B |= (1<<CS11);

	while(1)
	{
		switch(counter)
		{
			case 1 :	PORTA = 0x00;
						break;

			case 10:	PORTA =0XFF;
						counter = 0;
						break;
		}
	}

}

ISR(TIMER1_COMPA_vect) 
{
	
	counter++;

}

instead of put the switch function in the ISR, is it better if i put in the while loop?

thank you.

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

hi,
another question is, i change another way to write the switch function which is:

switch(counter)
		{
			case 1 :	PORTA = ~PORTA;
						break;
			//case 2 :	

			case 10:	PORTA = ~PORTA;
						counter = 0;
						break;
		}

i just try to invert the PORTA signal. But why i get a different result with the one which i put in a logic 0 or a logic 1 to my PORTA.

thank you.

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

Have a read of this:
https://www.avrfreaks.net/index.p...

Your counter variable has an atomic access problem. You probably havent seen the effect yet, but it will happen.

To toggle the bits, I would normally write:

PORTA ^= 0xff;

where ^ is the 'c' xor function.

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

Were I writing it, I'd put the work in the ISR, since there's so little of it. Also, you don't need to use an awkward 16-bit integer for "counter" if it never needs to hold values bigger than ten. Also, your switch statement doesn't have any default clauses for handling values *between* 1 and ten. But then this would be a good time to break the habit of writing switch statements, and just use:

   if (0 == --counter) { counter = 10; PORTA = ~PORTA; }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But then this would be a good time to break the habit of writing switch statements

thanks for the advices. I use this switch function is because this is just the first stage of my whole program which is just to test the output of the timer and counter. For further programming, i'll need to add in a few cases for different interrupt time.
Agree with your point in the awkward 16-bit int counter.will correct it.

actually my program will continue to create more interrupt in different time. This is because the purpose of this program is to produce different degree for my several servos. Since Kartman gave some advice on my counter i'll check the link very soon although i not understand what is the atomic that u mean.

thanks alot.

thank you.