2

According to the datasheet:

enter image description here

we could think that, if we want to have a pin change interrupt for 3 pins, we have to create multiple instances:

ISR(PCINT0_vect){
   ...
}

ISR(PCINT1_vect){
   ...
}

ISR(PCINT2_vect){
   ...
}

void setup(){
  GIMSK = 0b00100000;
  PCMSK = 0b00000111; 
}

However, this does not work, and I read here and here that we have to define just one interrupt function:

ISR(PCINT0_vect){
   if (digitalRead(0) == LOW) 
     ...
   if (digitalRead(1) == LOW) 
     ...
   if (digitalRead(2) == LOW) 
     ...
}

Why is that so? What is PCINT1, 2, 3, ... made for then in this pinout schematics, if we don't have to use it?

3 Answers 3

3

You are confusing Pin Change Interrupt pins with Pin Change Interrupt vectors. The two are very different.

Many Pin Change Interrupt pins are associated with just one Pin Change Interrupt vector.

You use the pin number (the value shown in the pinout) to decide if you want that pin to respond or not. You use the vector to respond any of the pins that are assigned to that vector.

In the ATTiny chips, since there are so few Pin Change Interrupt pins (8 or less) you only need one Pin Change Interrupt vector to handle them.

You can know if "PCINT4" corresponds to a pin or a vector by the context. If you see it on a pin then it is a pin. If you see it in code with _vect after it then it's a vector.

1
  • Perfect answer, thanks!
    – Basj
    Nov 20, 2019 at 14:56
4

That is simply the difference between an external interrupt INTx and a pin change interrupt PCINT. The first is an interrupt for a single pin. The second is an interrupt for a complete group of pins. Normally this group is a complete port. As the Attiny85 only has one port, this is the case here. So the whole group is only 1 single interrupt source. Thus it only has one interrupt vector named PCINT0_vect.

A pin change interrupt triggers, when any of the pins under it's supervision changes. You can remove pins from it's supervision by masking them with the PCMSK register.

So the interrupt vector PCINT_vect will be triggered by every change on any of the pins, that are not masked out. It is up to you to check, which one changed it's level.


On bigger microcontrollers, there are more pins and mostly also most of them are connected to a pin change interrupt. Here mostly every complete port is connected to a single pin change interrupt. Thus the corresponding registers are additionally marked with a number (PCINT0_vect as the interrupt vector for the first port, ...)

7
  • Ok, so in fact for ATtiny45, PCINT0_vect works for all the pins 0..5? Then why put "PCINT1", "PCINT2" on the pinout schematics? Then PCINT0_vect should be called PCINT_vect0, don't you think so? Because it's the the "first" vector of pin change interrupts... With a naming like PCINTx_vect, we could think it's relative to the pin x since the pinout schematics shows PCINTx for every pin x=0..5.
    – Basj
    Nov 20, 2019 at 14:46
  • I cannot say, why they named them as such, that is only known by Atmel. A PCINT_vect0 doesn't exist, because their naming convention is <Interrupt Name>_vect for the interrupt vectors. For the pin description I think, they wanted to keep it short. On bigger microcontrollers, the PCINT pins are numbered completely though, so on the Atmega328P (from the Uno) there are pins up to PCINT20
    – chrisl
    Nov 20, 2019 at 14:52
  • Basically you need to understand what Pin Change interrupts are. Those things are normally explained rather detailed in the datasheet. For example this sentence from the External Interrupt section of the datasheet: "Pin change interrupts PCI will trigger if any enabled PCINT[5:0] pin toggles."
    – chrisl
    Nov 20, 2019 at 14:52
  • I know what they are, and I do understand they are grouped, but I don't understand the naming...
    – Basj
    Nov 20, 2019 at 14:53
  • For example for the 328p, PCINT0_vect covers which group of pins? Idem for PCINT1_vect? I can imagine they can handle up to 8 pins each?
    – Basj
    Nov 20, 2019 at 14:55
1

You can enable/disable Pin Change INTerrupts for individual pins using the Pin Change Mask Register PCMSK.

The names on the pins map the bit in PCMSK to the physical pin.

You find more information in section 9.3.4 on p. 52 in the ATtiny85 Data Sheet

4
  • I did this with PCMSK = 0b00000111; indeed. But why don't we use PCINT1_vect? The pinout schematics mentions "PCINT1", why don't we use it?
    – Basj
    Nov 20, 2019 at 14:41
  • 1
    Section 9.1 lists all available interrupt vectors. Pin Change Interrupts are grouped to not waste resources. Only INTx is dedicated to a single pin. It is also much more powerful, als it can be triggered on rising or falling edges instead of each change. ATtiny85 only has with INT0 one dedicated pin for that.
    – Kwasmich
    Nov 20, 2019 at 14:45
  • I understand that they are grouped to not waste resources @Kwasmich, but then if all pins can be handled with just PCINT0_vect alone, isn't this a mistake in the schematics to write PCINT0, PCINT1, ..., PCINT5?
    – Basj
    Nov 20, 2019 at 14:48
  • 1
    No, again, it is to show you wich bit in PCMSK corresponds to which physical pin. Otherwise you would not know what pin is affected. The naming is ambiguos, for sure.
    – Kwasmich
    Nov 20, 2019 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.