Search code examples
cavratmega

ATMega48 - how to register an external PCINT2 interruptor?


I'm currently trying to create a simple program for an ATMega48 emulator that has a PCINT2 external interruptor listening on PORTD input and changing the output based on its value.

Here's the code of the interruptor:

unsigned int d; // a variable that has to change based on the input

ISR(PCINT2_vect) {
  if (PORTD % 2 == 0) {
    if (d <= 8000) {
        d += 500;
    }
  } else {
    if (d >= 1000) {
        d -= 500;
    }
  }
}

the main() function:

int main(void)
{
  DDRD = 0x00; // set PORTC for input
  DDRB = 0xFF; // set PORTB for output
  PORTB = 0x00; // Initial value is 0
  PCMSK0 = 0b00000100;
  d = 4000;
  sei();

  while (1) {
    // Enable\Disable the LED with an initial delay
    if (PIND == 0b00000000) {
        PORTB = 0b00100000;
    } else {
        PORTB = 0b00000000;
    }

    // Delay for N seconds (determined by interrupt)
    delay_stuff(d);
  }

  return 1;
}

Currently it's not calling the interruptor no matter what happens to any port, my assumption is that I'm not registering some magical ATMega listeners to call the interruptor. How to register the interruptor then, what am I missing here?


Solution

  • According to datasheet page 75-76, you must enable Pin Change Interrupt in PCICR register and select which pin will be enabled on the corresponding IO in PCMSK2 for PCINT2 (PCMSK0 is for PCINT0, i.e PINB).

    int main(void)
    {
        DDRD = 0x00; // set PORTC for input
        DDRB = 0xFF; // set PORTB for output
        PORTB = 0x00; // Initial value is 0
    
        PCICR |= _BV(PCIE2);  //or, PCICR |= 0x04;
        PCMSK2 |= 0xFF;       //any changes in PIND will trigger interrupt
        d = 4000;
        sei();
    
        //other codes...
    }