Timer interrupts ATMega32 [solved: logic issue]

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

Hello, I wrote a program that is suppose to blink a LED on PORTA pin 0 on and off every second. Simultaneously the program is suppose to check PORTB pin 0 to see if a button has been pressed. If the button has been pressed and released the LED on PORTA pin 1 is suppose to turn on and stay on. If the button is pressed again the LED on PORTA pin 1 is suppose to turn off. The blinking of the LED on pin 0 works fine. But the LED on pin 1 is only on if I hold the button down. Can someone please tell me what is wrong with my program?

#define F_CPU 8000000
#include 
#include 
#include 

int flag=0; //flag to indicate whether button on PB0 has been pressed or not

int main(void)
{	
	DDRB &= ~(1 << PINB0); //PB0 IS INPUT, BUTTON LOCATED HERE
	PORTB |= 1 << PINB0;  //PULLUP RESISTOR ACTIVATED
	
	sei(); //enable global interrupts
	
	DDRA |= 1<<PINA0; //PortA pin 0 is ouput
	DDRA |= 1<<PINA1; //PortA pin 1 is ouput
	PORTA |= 1 << PINA1;//LED IS OFF, 0 turns LED on 1 turns LED off
	
	TCCR1B |= 1<<CS10 | 1<<CS12 | 1<<WGM12;//timer in ctc mode prescaler 1024
	TIMSK |= 1<<OCIE1A;//active output on compare interrupt
	OCR1A = 7812;//blink every second
	
	while(1)
	{
		if (bit_is_clear(PINB, 0)) //if button is depressed flag is 1
		{
			flag = 1;
			_delay_ms(250);//debounce delay
			}else{	//if button is not pressed flag is 0
		 	flag = 0;
			_delay_ms(250);
		}
	}
	
	
}

ISR(TIMER1_COMPA_vect)
{
   PORTA ^= 1<<PINA0;//toggle LED on PORTA pin 0
   
   if(flag==0)
   {
    PORTA |= 1<<PINA1; //if flag is 0 LED on PORTA pin 1 is turned OFF
   }else{
	PORTA &= ~(1 << PINA1);//if flag is 1 LED on PORTA pin 1 is turned ON, note: 0 turns LED ON, 1 turns LED OFF
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Flag must be declared volatile - you're the second person trapped by this today. Check oht the tutorial section for Clawson's the importance of volatile tutorial.

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

Hmm, still same problem.

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

Why don't you read Button debounce in software, I don't think the delays by themselves are sufficient for debouncing.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

In main() you have this:

}else{   //if button is not pressed flag is 0 
flag = 0; 

In ISR(TIMER1_COMPA_vect)

if(flag==0) { 
PORTA |= 1<<PINA1; //if flag is 0 LED on PORTA pin 1 is turned OFF 

Isn't it working exactly like you coded it? :?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Umm, whoops! You are right, I inadvertently coded it to do that. How would I code it to stay on once pressed and released and turn off when pressed and released again?

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

This how I toggle pin 0 on PORTA in another program:

while(1)
{
if(bit_is_clear(PINB,0))
{
PORTA ^= 1<<PINA0;
_delay_ms(250);
}
}

Is there a way to toggle flag?

while(1)
{
if(bit_is_clear(PINB,0))
{
flag ^= flag;
_delay_ms(250);
}
}

does that make any sense?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   if (bit_is_clear(PINB, 0)) 
      { 
         flag = 1; 

Try this

   if (bit_is_clear(PINB, 0)) 
      { 
         flag ^= 1; //toggle flag

Or you can directly

   if (bit_is_clear(PINB, 0)) 
      { 
         PORTA ^= (1<<PA1); //toggle Led on PORTA1
...
...
ISR(TIMER1_COMPA_vect) 
{ 
   PORTA ^= 1<<PINA0;//toggle LED on PORTA pin 0 
}

Edit:
You have dicovered it meanwhile.

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

It works, thank you!