PIN CHANGE interrupt by software

Hi,

I am starting to program Arduino interrupts, and I have this problem. How I have seen in the datasheet of ATMEGA328 (Arduino UNO), it is possible to generate software interruption, so I have tried it with the pins PINB1 (PCINT1) and PINB2 (PCINT2). Here is the code:

#include <avr/io.h>
#include <avr/interrupts.h>
#define LED 13

ISR(PCINT2_vect){
PORTB ^= (1<<PINB5);
}

ISR(PCINT1_vect){
PORTB ^= (1<<PINB5);
}

void setup(){
cli();

// Configure PCINT1 and PCINT2 as output for software interrupts
// PCINT1 - PB1 → PIN 9 Arduino
// PCINT2 - PB2 → PIN 10 Arduino
// PB5 → PIN 13 Arduino - LED

DDRB |= (1<<DDB1) | (1<<DDB2) | (1<<DDB5); // Ports as output
//PORTB = B00000000; // fix to 0 all ports B

// Allow pins to act as external interrupt
PCICR |= (1<<PCIE0);

PCMSK0 &= ~(1<<PCINT0);
PCMSK0 |= (1<<PCINT1);
PCMSK0 |= (1<<PCINT2);

sei();
}

void loop(){
PORTB |= (1<<PINB1);
delay(500);
PORTB &= ~(1<<PINB1);
delay(2000);

PORTB |= (1<<PINB2);
delay(500);
PORTB &= ~(1<<PINB2);
delay(5000);
}

But it does not work. And the strange thing which happens, if I use ISR(PCINT0_vect) instead of the other one, the code works, and both pin changes PINB1 and PINB2 generate this interruption.

Could someone show me the light about that?

Thank you very much,
Antonio.

Interrupts are always difficult to debug and it would take me a long time to become familiar with what your code is trying to do as you have little or no explanation in it.

Also you refer to "ISR(PCINT0_vect)" but I don't see any code for that.

I read (skimmed) the Datasheet stuff about what you are trying to do some time ago. I thought all that would be necessary to trigger an interrupt would be digitalWrite(pin, HIGH) or it's equivalent - in other words the interrupt mechanism doesn't care what causes the pin to go HIGH (or LOW, I presume).

...R

PCINT0 does port B (pins 8 to 13) PCINT1 does port C (pins A0..A5) PCINT2 does port D (pins 0 to 7).

If i am not wrong the interrupt type you try to use it is for check (fire the interrupt routine) when a pin goes from high to low or reverse, but the pin must be as INPUT and not OUTPUT (use external buttons) if you want every some ms to do something you need the TIMER interrupt.

tasosstr: If i am not wrong the interrupt type you try to use it is for check (fire the interrupt routine) when a pin goes from high to low or reverse, but the pin must be as INPUT and not OUTPUT (use external buttons) if you want every some ms to do something you need the TIMER interrupt.

pin change interrupts fire when any of the pins in that port that aren't masked-out change, whether or not they are inputs or outputs.

For instance you can use a PWM pin to trigger a pin-change interrupt that will fire everytime the PWM output transistions.

Thank you very much for your answer!

MarkT, what you have said, it's the same what I have experimentally. As I see, the PCINT23-0 have not individual interrupts, but they are grouped in three banks corresponded with PCINT0, PCINT1 and PCINT2, as you have said. I was confused because they have the same name and I thought, we can have 24 possible interrupts. Is there any way for getting individual interrupts?

Regards, Antonio.

There are only 2 individual interrupts, for which you use attachInterrupt().

Antonio wrote "Is there any way for getting individual interrupts?"

No, I don't think so when it comes to pin change interrupts. You need to know the state of the pins before, and the state of the pins afterwards, and compare. There even could be multiple pins that changed.