Pin change interrupt (low)

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

Hello!

I am working in a pin change interrupt code with an atmega168. whenever it is high, it will light up an LED, however, I don't know how to trigger an interrupt whenever the pin goes low.
Does someone knows how to do this?
This is my code:

volatile int32_t count = 0;
int count2 = 0;
void setup() {

PCMSK2 |= (1<<PCINT18);

PCICR |= (1<<PCIE2);
PCIFR = (1<<PCIF2);
sei();
}

ISR(PCINT2_vect)
{
   count=1;
}


int main() {
 setup();

//While loop is constantly turning off the LED until the //interrupt is fired
  while(1) {
   if( count ==1 )
   {
  DDRB |= (1<<PB3);
   }
   else DDRB &= ~(1<<PB3);

   if( count2 >= 2 && count2 <= 4 )
   {
       //DDRB |= (1<<PB3);
   }


   count = 0;
  }

  return 0;
}
Last Edited: Fri. Dec 25, 2009 - 06:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You failed to say which AVR chip you are working with.

Pin change interrupts toggle both on rising and falling edges. It takes an INT type interrupt to control/select the interrupt edge. A pin that is enabled for pin change interrupt use may be an AVR output pin (for an AVR software pin change interrupt) or an AVR input pin (for external pin change interrupt).

Tell us which AVR you are using.

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

I am sorry. I forgot to tell that crucial information.
I am working with the atmega168 chip

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

It looks like it should work, except being a pin change interrupt it will trigger on both rising and falling edge PD2 changes. The PD2 pin also has INT0. If you disable the pin change and enable INT0, you will be able to select the trigger edge in the EICRA register. Make sure your edge interrupt triggers are not too fast for the human eye to detect. Also make sure your external interrupt trigger is debounced in hardware or software (unless it is already a clean signal without an bounces).

However, there is one hidden flaw in your program logic. The interrupt trigger edge will set count=1. But, on the next pass through your while(1) loop will have count=0. So, after the interrupt trigger PB3 will only be an output pin for the the time it takes to pass one time through the while(1) loop. A very small amount of time that your eye will never see. You need a long delay or a different method of turning the LED both on and off.

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

I used pin change interrupts at one point for button inputs. I just had the first thing the ISR did was check to see which if any of my buttons was high using a switch case statement. In your case I guess you could do the same thing with an if else statement checking for low.

Self proclaimed Captain Link

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

Mike B wrote:
It looks like it should work, except being a pin change interrupt it will trigger on both rising and falling edge PD2 changes. The PD2 pin also has INT0. If you disable the pin change and enable INT0, you will be able to select the trigger edge in the EICRA register. Make sure your edge interrupt triggers are not too fast for the human eye to detect. Also make sure your external interrupt trigger is debounced in hardware or software (unless it is already a clean signal without an bounces).

However, there is one hidden flaw in your program logic. The interrupt trigger edge will set count=1. But, on the next pass through your while(1) loop will have count=0. So, after the interrupt trigger PB3 will only be an output pin for the the time it takes to pass one time through the while(1) loop. A very small amount of time that your eye will never see. You need a long delay or a different method of turning the LED both on and off.

OK, I understand. I'll try that, thanks! Do you think a 100Hz digital signal will work with this method?

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

Personman wrote:
I used pin change interrupts at one point for button inputs. I just had the first thing the ISR did was check to see which if any of my buttons was high using a switch case statement. In your case I guess you could do the same thing with an if else statement checking for low.

MAN! That's true!!

you mean like:

ISR(PCINT2_vect)
{
   //DDRB |= (1<<PB3);
if(PIND & (1<<PD2)) {
      // do something if PD2 is high
      count = 1;
} else {
      // do something else if PD2 is low
      count =0;
}

}

:o awesome!!! I think it works!!