{"id":18785,"date":"2023-09-16T12:26:34","date_gmt":"2023-09-16T12:26:34","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/?p=18785"},"modified":"2023-10-13T15:54:09","modified_gmt":"2023-10-13T15:54:09","slug":"interrupts-part-2-pin-change-interrupts","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts","title":{"rendered":"Interrupts &#8211; Part 2: Pin Change Interrupts"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this post<\/h2>\n\n<p>In this sequel of <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-1-external-interrupts\" target=\"_blank\" rel=\"noopener\">my last post<\/a>, I will cover pin change interrupts. AVR microcontrollers and Arduino boards based on them are relatively sparsely equipped with those external interrupts that you can set up via <code>attachInterrupt()<\/code>. The good news, however, is that pin change interrupts are available to you on all I\/O pins instead. They are not quite as convenient and also a bit more difficult to configure, since you have to deal with the registers of the underlying microcontrollers. But don&#8217;t worry, it&#8217;s not rocket science, either.<\/p>\r\n<p>I will explain the use of pin change interrupts in detail on the ATmega328P (Arduino UNO, Nano, Pro Mini) and then show on the example of the ATtiny85 that the systematics behind it is very similar on all AVR microcontrollers.<\/p>\r\n\n<p>These are the topics I will discuss:<\/p>\r\n<ul>\r\n<li><a href=\"#atmega_328p_insights\">A look inside the ATmega328P<\/a><br>\r\n<ul>\r\n<li><a href=\"#ports_pins_pcint\">Ports, Pins and PCINT<\/a><\/li>\r\n<li><a href=\"#328p_relevant_registers\">Pin Change Interrupts using the ATmega328P &#8211; the relevant registers<\/a><\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><a href=\"#328p_examples\">Practical examples for the ATmega328P<\/a> <br>\r\n<ul>\r\n<li><a href=\"#single_pcint\">A single pin change interrupt pin<\/a><\/li>\r\n<li><a href=\"#several_pcints_several_ports\">Multiple pin change interrupt pins on different ports<\/a><\/li>\r\n<li><a href=\"#several_pcints_one_port\">Multiple pin change interrupt pins on one port<\/a><\/li>\r\n<li><a href=\"#entire_port\">Using an entire port<\/a><\/li>\r\n<li><a href=\"#high_low__low_high\">Tracking HIGH-LOW and LOW-HIGH changes<\/a><\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><a href=\"#other_mcus\">Pin change interrupts on other AVR microcontrollers<\/a>\r\n<ul>\r\n<li><a href=\"#attiny85\">Example: ATtiny85<\/a><\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><a href=\"#minievb\">Pin Change Interrupts on MiniEVB Boards<\/a><\/li>\r\n<\/ul>\r\n\n<h2 class=\"wp-block-heading\" id=\"atmega_328p_insights\">A look inside the ATmega328P<\/h2>\n\n<h3 class=\"wp-block-heading\" id=\"ports_pins_pcint\">Ports, Pins and PCINT<\/h3>\n\n<p>The I\/O pins of the ATmega328P are arranged in the three ports PORTB, PORTC and PORTD, each comprising up to 8 pins. The pins are named accordingly: PB[7:0], PC[6:0], PD[7:0]. Here the notation &#8220;PB[7:0]&#8221; means: PB7, PB6, PB5 &#8230; PB1, PB0. Each pin has a unique pin change interrupt number, namely PCINT[23:0]<em>.<\/em><\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO-1024x495.png\" alt=\"Pinout ATmega328P vs. Arduino Pins (UNO, Nano, Pro Mini) \" class=\"wp-image-4356\" style=\"width:840px;height:406px\" width=\"840\" height=\"406\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO-1024x495.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO-300x145.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO-768x371.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO-1320x637.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/12\/Pinout-Atmega-328P-vs-Arduino-UNO.png 1495w\" sizes=\"auto, (max-width: 840px) 100vw, 840px\" \/><\/a><figcaption class=\"wp-element-caption\">Pinout ATmega328P vs. Arduino Pins (UNO, Nano, Pro Mini)<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\" id=\"328p_relevant_registers\">Pin Change Interrupts using the ATmega328P &#8211; the relevant registers<\/h3>\n\n<p>Only one pin change interrupt is available for each port, but it can be triggered on any individual pin of the port, provided the pin has been set up for this purpose. To enable a pin for change interrupts, set the associated bit in the relevant pin change mask register PCMSK[2:0]. Here is an overview:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1-1024x244.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"244\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1-1024x244.png\" alt=\"Pin Change Interrupt Mask Register PCMSK[0:2]\" class=\"wp-image-18655\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1-1024x244.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1-300x71.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1-768x183.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcmsk_registers-1.png 1238w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Pin Change Interrupt Mask Register PCMSK[2:0]<\/figcaption><\/figure>\n\n<p>Furthermore, you have to activate the interrupt itself. This is done by setting the associated Pin Change Enable Bit PCIE[2:0] in the Pin Change Interrupt Control Register PCICR.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr-1024x83.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"83\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr-1024x83.png\" alt=\"Pin Change Interrupt Control Register PCICR\" class=\"wp-image-18630\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr-1024x83.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr-300x24.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr-768x62.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcicr.png 1183w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Pin Change Interrupt Control Register PCICR<\/figcaption><\/figure>\n\n<p>PCIE0 is responsible for PORTB, PCIE1 for PORTC and PCIE2 for PORTD.<\/p>\r\n\n<p>In case of an interrupt, the corresponding flag PCIF[2:0] is set in the Pin Change Interrupt Flag Register PCIFR:<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr-1024x89.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr-1024x89.png\" alt=\"Pin Change Interrupt Flag Register PCIFR\" class=\"wp-image-18632\" style=\"width:840px;height:73px\" width=\"840\" height=\"73\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr-1024x89.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr-300x26.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr-768x67.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcifr.png 1181w\" sizes=\"auto, (max-width: 840px) 100vw, 840px\" \/><\/a><figcaption class=\"wp-element-caption\">Pin Change Interrupt Flag Register PCIFR<\/figcaption><\/figure>\n\n<h2 class=\"wp-block-heading\" id=\"328p_examples\">Practical examples for the ATmega328P<\/h2>\n\n<h3 class=\"wp-block-heading\" id=\"single_pcint\">A single pin change interrupt pin<\/h3>\n\n<p>In the first example, we set up only a single interrupt pin. We choose Arduino pin 6 (PD6 \/ PCINT22), whose level is to change from HIGH to LOW when the button is pressed. For this purpose, we use the internal pull-up resistor. As a result of pressing the button, the board LED should light up for half a second.<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_D6-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_D6-1.png\" alt=\"Pin Change Interrupt at D6\" class=\"wp-image-18726\" style=\"width:450px;height:292px\" width=\"450\" height=\"292\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_D6-1.png 856w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_D6-1-300x195.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_D6-1-768x499.png 768w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/a><figcaption class=\"wp-element-caption\">Pin Change Interrupt at D6<\/figcaption><\/figure>\n\n<p>Here is the example sketch for it:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pcint_interrrupt_basic.ino\" data-enlighter-title=\"pcint_interrrupt_basic.ino\">const int ledPin = 13;  \/\/ = LED_BUILTIN\r\nconst int interruptPin = 6;\r\nvolatile bool event = false;\r\n \r\nISR (PCINT2_vect){ \/\/ PCINT2_vect: interrupt vector for PORTD\r\n  event = true;\r\n}\r\n\r\nvoid setup() {\r\n    pinMode(interruptPin, INPUT_PULLUP);\r\n    PCICR = (1&lt;&lt;PCIE2);    \/\/ enable PCINT[23:16] interrupts\r\n    PCMSK2 = (1&lt;&lt;PCINT22); \/\/ D6 = PCINT22\r\n}\r\n \r\nvoid loop() {\r\n    if(event){\r\n        digitalWrite(ledPin, HIGH);\r\n        delay(500);\r\n        digitalWrite(ledPin, LOW);\r\n        event = false;\r\n    }\r\n}<\/pre>\r\n\n<p>Explanation to the sketch:<\/p>\r\n<ul>\r\n<li>With <code>PCICR = (1&lt;&lt;PCIE2)<\/code> pin change interrupts at PORTD are allowed.<\/li>\r\n<li><code>PCMSK2 = (1&lt;&lt;PCINT22)<\/code> enables the pin change interrupt at PD6 (= Arduino pin 6).<\/li>\r\n<li>We pass the associated interrupt vector <code>PCINT2_vect<\/code> to the ISR. As most people probably already guessed correctly, <code>PCINT1_vect<\/code> would be the relevant vector for PORTC and <code>PCINT0_vect<\/code> the vector for PORTB.<\/li>\r\n<\/ul>\r\n<p>In this first, minimalistic example, no distinction is made between level changes from HIGH to LOW and from LOW to HIGH. If you press the button down for longer than 500 milliseconds, the LED will light up again when you release it.<\/p>\r\n<p>Bouncing is not perceptible with this setting. Since I already went into detail about bouncing and debouncing in <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-1-external-interrupts#debouncing\" target=\"_blank\" rel=\"noopener\">my last post<\/a>, I won&#8217;t repeat that here.<\/p>\r\n<p>And if you still need to catch up on the topic of binary operations (e.g. <code>1&lt;&lt;PCIE2<\/code>) you could take a look at <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/logical-operations-and-port-manipulation\" target=\"_blank\" rel=\"noopener\">this article<\/a>.<\/p>\r\n\n<h3 class=\"wp-block-heading\" id=\"several_pcints_several_ports\">Multiple pin change interrupt pins on different ports<\/h3>\n\n<p>In the next step, we will monitor the level of three pushbuttons. This time we output on the serial monitor when an interrupt was triggered and at which pin it happened. For this, we use three pins from different ports:<\/p>\r\n<ul>\r\n<li>PB1 = Arduino Pin 9 = PCINT1<\/li>\r\n<li>PC2 = Arduino Pin A2 = PCINT10<\/li>\r\n<li>PD5 = Arduino Pin 5 = PCINT21<\/li>\r\n<\/ul>\r\n\n<p>This is the circuit:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports.png\"><img decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports.png\" alt=\"3 pin change interrupts on 3 ports\" class=\"wp-image-18719\" style=\"width:500px\" width=\"500\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports.png 1052w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports-300x177.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports-1024x604.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_3_ports-768x453.png 768w\" sizes=\"(max-width: 1052px) 100vw, 1052px\" \/><\/a><figcaption class=\"wp-element-caption\">3 pin change interrupts on 3 ports<\/figcaption><\/figure>\n\n<p>And here is the corresponding sketch:<\/p>\r\n\n<div class=\"scroll-paragraph\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"three_pcint_interrupts_at_three_ports.ino\" data-enlighter-title=\"three_pcint_interrupts_at_three_ports.ino\">const int interruptPin_1 = 9; \/\/PB1\r\nconst int interruptPin_2 = A2; \/\/PC2\r\nconst int interruptPin_3 = 5; \/\/PD5\r\nvolatile bool event_1 = false;\r\nvolatile bool event_2 = false;\r\nvolatile bool event_3 = false;\r\n \r\nISR (PCINT0_vect){   \r\n    event_1 = true;\r\n}\r\n\r\nISR (PCINT1_vect){   \r\n    event_2 = true;\r\n}\r\n\r\nISR (PCINT2_vect){   \r\n    event_3 = true;\r\n}\r\n\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    pinMode(interruptPin_1, INPUT_PULLUP);\r\n    pinMode(interruptPin_2, INPUT_PULLUP);\r\n    pinMode(interruptPin_3, INPUT_PULLUP);\r\n    PCICR = (1&lt;&lt;PCIE2) | (1&lt;&lt;PCIE1) | (1&lt;&lt;PCIE0);\r\n    PCMSK0 = (1&lt;&lt;PCINT1);\r\n    PCMSK1 = (1&lt;&lt;PCINT10);\r\n    PCMSK2 = (1&lt;&lt;PCINT21); \r\n}\r\n \r\nvoid loop() {\r\n    if(event_1){\r\n        Serial.println(\"Interrupt at pin 9\");\r\n        delay(300); \r\n        event_1 = false;\r\n    }\r\n    if(event_2){\r\n        Serial.println(\"Interrupt at pin A2\");\r\n        delay(300);\r\n        event_2 = false;\r\n    }\r\n    if(event_3){\r\n        Serial.println(\"Interrupt at pin 5\");\r\n        delay(300);\r\n        event_3 = false;\r\n    }   \r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<h4 class=\"wp-block-heading\">Explanations to three_pcint_interrupts_at_three_ports.ino<\/h4>\n\n<ul>\r\n<li>With <code>PCICR = (1&lt;&lt;PCIE2) | (1&lt;&lt;PCIE1) | (1&lt;&lt;PCIE0);<\/code> interrupts are allowed at PORTB, PORTC and PORTD.<\/li>\r\n<li>The three pins are set up as interrupt pins in their associated PCMSK[2:0] register.<\/li>\r\n<li>For each pin change interrupt pin, we have a separate ISR.<\/li>\r\n<li>The 300-millisecond delays conceal the bouncing and the additional interrupt when the button is released.<\/li>\r\n<\/ul>\r\n\n<h3 class=\"wp-block-heading\" id=\"several_pcints_one_port\">Multiple pin change interrupt pins on one port<\/h3>\n\n<p>In the next example we use pin change interrupts for three pushbuttons connected to pins 5, 6 and 7, i.e. PCINT21, PCINT22 and PCINT23. Now we have to consider that all three pins belong to PORTD and therefore only one interrupt is available. But since we know the levels of the pins in the ground state, we simply check in the ISR which pin is deviating using <code>digitalRead()<\/code> and thus is &#8220;the culprit&#8221;.<\/p>\r\n<p>To add a little variety, we pull pin 5 and pin 7 to LOW with pull-down resistors. Pin 6 uses the internal pull-up resistor.<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_one_port.png\"><img decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_one_port.png\" alt=\"3 pin change interrupt pins on one port\" class=\"wp-image-18729\" style=\"width:500px\" width=\"500\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_one_port.png 1021w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_one_port-300x183.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit_3_pcints_one_port-768x469.png 768w\" sizes=\"(max-width: 1021px) 100vw, 1021px\" \/><\/a><figcaption class=\"wp-element-caption\">3 pin change interrupt pins on one port<\/figcaption><\/figure>\n\n<p>Please note, that the connections located on the top left and bottom left or top right and bottom right of the pushbuttons are connected permanently.<\/p>\r\n<p>This is the sketch:<\/p>\r\n\n<div class=\"scroll-paragraph\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"three_pcint_interrupts_at_one_port.ino\" data-enlighter-title=\"three_pcint_interrupts_at_one_port.ino\">const int interruptPin_1 = 5;\r\nconst int interruptPin_2 = 6;\r\nconst int interruptPin_3 = 7;\r\nvolatile bool event_1 = false;\r\nvolatile bool event_2 = false;\r\nvolatile bool event_3 = false;\r\n \r\nISR (PCINT2_vect){   \r\n    if(digitalRead(interruptPin_1)){\r\n        event_1 = true;\r\n    }\r\n    else if(!digitalRead(interruptPin_2)){\r\n        event_2 = true;\r\n    }\r\n    else if(digitalRead(interruptPin_3)){\r\n        event_3 = true;\r\n    }\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    pinMode(interruptPin_1, INPUT);\r\n    pinMode(interruptPin_2, INPUT_PULLUP);\r\n    pinMode(interruptPin_3, INPUT);\r\n    PCICR = (1&lt;&lt;PCIE2);\r\n    PCMSK2 = (1&lt;&lt;PCINT23)|(1&lt;&lt;PCINT22)|(1&lt;&lt;PCINT21); \r\n}\r\n \r\nvoid loop() {\r\n    if(event_1){\r\n        Serial.println(\"Interrupt at pin 5\");\r\n        delay(300); \r\n        event_1 = false;\r\n    }\r\n    if(event_2){\r\n        Serial.println(\"Interrupt at pin 6\");\r\n        delay(300);\r\n        event_2 = false;\r\n    }\r\n    if(event_3){\r\n        Serial.println(\"Interrupt at pin 7\");\r\n        delay(300);\r\n        event_3 = false;\r\n    }   \r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<p>By checking the pin level using <code>digitalRead()<\/code>, the interrupts triggered by releasing the pushbuttons are ignored (unless the pushbutton jumps when released). This may be desirable &#8211; or not. In the next but one example, I will come back to how you can detect pin changes in both directions when using one port.<\/p>\r\n\n<h3 class=\"wp-block-heading\" id=\"entire_port\">Using an entire port <\/h3>\n\n<p>Now we will use (almost) the entire PORTD. This includes Arduino pins 0 to 7. Pins 0 and 1 are not suitable for pin change interrupts because they are RX and TX. We therefore restrict the interrupts to pins 2 to 7 or PD[7:2].<\/p>\r\n<p>The following circuit is used for this purpose:<\/p>\r\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit.png\"><img decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit.png\" alt=\"Pin Change Interrupt Test Circuit\" class=\"wp-image-18627\" style=\"width:600px\" width=\"600\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit.png 935w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit-300x147.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/pcint_test_circuit-768x377.png 768w\" sizes=\"(max-width: 935px) 100vw, 935px\" \/><\/a><figcaption class=\"wp-element-caption\">Pin Change Interrupt Test Circuit<\/figcaption><\/figure>\n<\/div>\n<p>I have added pull-down resistors to pins 3, 5, and 7, and pins 2, 4, and 6 are pulled HIGH with their internal pull-up resistors. If you just want to evaluate buttons, then it would be much easier to pull all pins to the same level. However, the buttons used here are only meant to be representative of <em>any<\/em> interrupt triggers, and this could be a mixture of LOW-active and HIGH-active ones.<\/p>\r\n\n<p>With six pins, it would be a bit unwieldy to query all pin states in case of an interrupt with <code>digitalRead()<\/code> and to use individual flags <code>event_[1:6]<\/code>. This can be solved in a smarter way &#8211; like this, for example:<\/p>\r\n\n<div class=\"scroll-paragraph\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pcint_interrupt_generalized.ino\" data-enlighter-title=\"pcint_interrupt_generalized.ino\">int interruptPin[6] = {2,3,4,5,6,7};\r\nvolatile bool event = false;\r\nvolatile byte changedPin = 0;\r\nvolatile unsigned long lastInterrupt = 0;\r\nconst byte interruptPinMask = 0b11111100;\r\nconst byte intPinPolarityMask = 0b01010100;\r\n \r\nISR (PCINT2_vect){   \r\n    if(millis()-lastInterrupt &gt; 300){\r\n        byte interruptPinsStatus = PIND &amp; interruptPinMask;\r\n        interruptPinsStatus ^= intPinPolarityMask;\r\n        if(interruptPinsStatus){\r\n            changedPin = log(interruptPinsStatus)\/log(2); \/\/ short, but slow! Alternative below:\r\n\/\/            changedPin = 0;\r\n\/\/            while(!(interruptPinsStatus &amp; 1)){\r\n\/\/                changedPin++;\r\n\/\/                interruptPinsStatus = (interruptPinsStatus &gt;&gt; 1);\r\n\/\/            }\r\n            event = true;\r\n        }\r\n        lastInterrupt = millis();\r\n    }\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    \r\n    pinMode(interruptPin[0], INPUT_PULLUP);\r\n    pinMode(interruptPin[1], INPUT);\r\n    pinMode(interruptPin[2], INPUT_PULLUP);\r\n    pinMode(interruptPin[3], INPUT);\r\n    pinMode(interruptPin[4], INPUT_PULLUP);\r\n    pinMode(interruptPin[5], INPUT);\r\n    \r\n    PCICR = (1&lt;&lt;PCIE2);\r\n    PCMSK2 = interruptPinMask; \r\n}\r\n \r\nvoid loop() {\r\n    if(event){\r\n        Serial.print(\"Interrupt at pin \");\r\n        Serial.println(changedPin);\r\n        event = false;\r\n    }\r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<h4 class=\"wp-block-heading\">Explanation of pcint_interrupt_generalized.ino<\/h4>\n\n<ul>\r\n<li>The interrupt pins are defined as an array.<\/li>\r\n<li>The <code>interruptPinMask<\/code> indicates which PORTD pins serve as interrupt pins (&#8220;1&#8221;) and which are ignored (&#8220;0&#8221;).<\/li>\r\n<li><code>intPinPolarityMask<\/code> contains the default level of the PORTD pins (button not pressed).<\/li>\r\n<li>In case of an interrupt, the current level of the pins is determined with PIND. This replaces all queries using <code>digitalRead()<\/code>.\r\n<ul>\r\n<li>By <code>PIND &amp; interruptPinMask<\/code> we ignore the state of pins 0 and 1.<\/li>\r\n<li>By <code>interruptPinsStatus ^= intPinPolarityMask<\/code> we find out which pin deviates from the default state. The logical operator &#8220;^&#8221; (XOR, exclusive OR) returns 1 if <em>exactly<\/em> one of the operands is 1.\r\n<ul>\r\n<li>For example, if the interrupt was triggered at PD4 (4), <code>interruptPinsStatus<\/code> would be 0b00010000 after the bit operations.<\/li>\r\n<\/ul>\r\n<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li>The condition <code>if(interruptPinsStatus){...<\/code> catches cases where no triggering interrupt pin can be determined.<\/li>\r\n<\/ul>\r\n<p>In the case of PORTD, the fact that PD<em>x<\/em> corresponds to Arduino pin <em>x<\/em> helps us. To find <em>x<\/em> (<code>changedPin<\/code>), we need to find where the 1 is located in <code>interruptPinsStatus<\/code>. There are several ways to do this:<\/p>\r\n<ul>\r\n<li>x = log<sub>2<\/sub>(interruptPinsMask). But since no logarithm to base 2 is available as a function, we apply the logarithm rule: log<sub>2<\/sub>(x) = log<sub>10<\/sub>(x)\/log<sub>10<\/sub>(2). This is a nice, short code, but calculating a logarithm is computationally intensive and therefore correspondingly slow. I have determined a good hundred microseconds for this calculation.<\/li>\r\n<li>You move <code>interruptPinsStatus<\/code> to the right until its value is 1 (see commented out code).<\/li>\r\n<li>You divide <code>interruptPinsStatus<\/code> by 2 until the remainder is 1.<\/li>\r\n<\/ul>\r\n<p>Otherwise, of course, you can also use <code>switch...case<\/code> structures.<\/p>\r\n\n<h3 class=\"wp-block-heading\" id=\"high_low__low_high\">Tracking HIGH-LOW and LOW-HIGH changes<\/h3>\n\n<p>In the last two sketches, we only considered level changes in one direction, i.e. deviations from the default state. To evaluate changes in both directions, we introduce the variable <code>lastInterruptsPinStatus<\/code>, in which we store the status of PIND (after adjusting for the ignored pins 0 and 1) at the respective time of the last interrupt. On a new interrupt, we compare the new state (<code>currentInterruptPinsStatus<\/code>) with the previous one (instead of <code>intPinPolarityMask<\/code>).<\/p>\r\n<p>Whether a HIGH-LOW or LOW-HIGH change has taken place can be recognized by whether the new status value is smaller or larger.<\/p>\r\n<p>Here is the sketch:<\/p>\r\n\n<div class=\"scroll-paragraph\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pcint_interrupt_generalized_with_level_change.ino\" data-enlighter-title=\"pcint_interrupt_generalized_with_level_change.ino\">int interruptPin[6] = {2,3,4,5,6,7};\r\nvolatile bool event = false;\r\nvolatile byte changedPin = 0;\r\nconst byte interruptPinMask = 0b11111100;\r\nvolatile byte lastInterruptPinsStatus = 0b01010100;\r\nvolatile bool risingEdge = false; \r\n \r\nISR (PCINT2_vect){   \r\n    byte currentInterruptPinsStatus = PIND &amp; interruptPinMask;\r\n    \r\n    if(currentInterruptPinsStatus &gt; lastInterruptPinsStatus){\r\n        risingEdge = true;\r\n    }\r\n    else{\r\n        risingEdge = false;\r\n    }\r\n    \r\n    byte statusCopy = currentInterruptPinsStatus;\r\n    currentInterruptPinsStatus ^= lastInterruptPinsStatus;\r\n    lastInterruptPinsStatus = statusCopy;\r\n    \r\n    if(currentInterruptPinsStatus){\r\n        changedPin = 0;\r\n        while(!(currentInterruptPinsStatus &amp; 1)){\r\n            changedPin++;\r\n            currentInterruptPinsStatus = (currentInterruptPinsStatus &gt;&gt; 1);\r\n        }\r\n    event = true;\r\n    }\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    \r\n    pinMode(interruptPin[0], INPUT_PULLUP);\r\n    pinMode(interruptPin[1], INPUT);\r\n    pinMode(interruptPin[2], INPUT_PULLUP);\r\n    pinMode(interruptPin[3], INPUT);\r\n    pinMode(interruptPin[4], INPUT_PULLUP);\r\n    pinMode(interruptPin[5], INPUT);\r\n    \r\n    PCICR = (1&lt;&lt;PCIE2);\r\n    PCMSK2 = interruptPinMask; \r\n}\r\n \r\nvoid loop() {\r\n    if(event){\r\n        Serial.print(\"Interrupt at pin \");\r\n        Serial.println(changedPin);\r\n        Serial.print(\"Pin went: \");\r\n        if(risingEdge){\r\n            Serial.println(\"HIGH\");\r\n        }\r\n        else{\r\n            Serial.println(\"LOW\");\r\n        }\r\n        event = false;\r\n    }\r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<p>If you try the sketch, you&#8217;ll probably notice that I removed the debouncing. It doesn&#8217;t fit well with this concept, as status changes triggered by bouncing fall under the radar. On the other hand, the sketch in this form does not work well with bouncing pushbuttons, since new interrupts can occur during output to the serial monitor (<code>Serial.print()<\/code> is quite slow). However, the Sketch works reliably with hardware-debounced pushbuttons (see <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-1-external-interrupts#rc_circuit_debouncing\" target=\"_blank\" rel=\"noopener\">last post<\/a>) or other interrupt sources that do not trigger too quickly one after the other.<\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"other_mcus\">Pin change interrupts on other AVR microcontrollers <\/h2>\n\n<p>Since we are accessing the microcontroller&#8217;s registers directly, the code for pin change interrupts is specific to the microcontroller. However, the &#8220;translation&#8221; of the code for other AVR microcontrollers is not particularly difficult. Take a look at the data sheet and search for chapter External Interrupts, subitem: Pin Change Interrupts.<\/p>\r\n\n<h3 class=\"wp-block-heading\" id=\"attiny85\">Example: ATtiny85<\/h3>\n\n<p>We try this for the ATtiny85, which is used e.g. on the Digispark board. It has only one pin change interrupt, which you enable by setting the Pin Change Enable Bit PCIE in the Global Interrupt Mask Register GIMSK:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk-1024x95.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"95\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk-1024x95.png\" alt=\"Global Interrupts Mask Register GIMSK\" class=\"wp-image-18649\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk-1024x95.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk-300x28.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk-768x71.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_gimsk.png 1189w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Global Interrupts Mask Register GIMSK<\/figcaption><\/figure>\n\n<p>You activate the pins for change interrupts in the Pin Change Mask Register PCMSK.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"91\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcmsk-1024x91.png\" alt=\"Pin Change Interrupt Mask Register PCMSK\" class=\"wp-image-18651\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcmsk-1024x91.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcmsk-300x27.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcmsk-768x68.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/09\/register_pcmsk.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Pin Change Interrupt Mask Register PCMSK<\/figcaption><\/figure>\n\n<p>A sketch could then look like this:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pcint_attiny85.ino\" data-enlighter-title=\"pcint_attiny85.ino\">const int ledPin = 4;\r\nconst int interruptPin = 3;\r\nvolatile bool event = false;\r\n \r\nISR (PCINT0_vect){\r\n    event = true;\r\n}\r\n\r\nvoid setup() {\r\n    pinMode(ledPin, OUTPUT);\r\n    pinMode(interruptPin, INPUT_PULLUP);\r\n    GIMSK |= (1&lt;&lt;PCIE); \/\/ General Interrupt Mask Register\r\n    PCMSK = (1&lt;&lt;PCINT3); \/\/ 3 = PCINT3\r\n}\r\n \r\nvoid loop() {\r\n    if(event){\r\n        digitalWrite(ledPin, HIGH);\r\n        delay(500);\r\n        digitalWrite(ledPin, LOW);\r\n        event = false;\r\n    }\r\n}<\/pre>\r\n\n<h2 class=\"wp-block-heading\" id=\"minievb\">Pin Change Interrupts on MiniEVB Boards<\/h2>\n\n<p>The <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/minievb-boards-an-overview\" target=\"_blank\" rel=\"noopener\">MiniEVB boards<\/a> based on the LGT8F328P show a high compatibility with the ATmega328P. Porting sketches for ATmega328P based Arduinos to the <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/lgt8f328p-lqfp32-boards\" target=\"_blank\" rel=\"noopener\">LQFP32-MiniEVB <\/a>board is especially easy. You can adopt the sketches 1:1. For the LQFP48-based MiniEVB boards only some pins are available, whereas for the SSOP20-based representatives some pins are not available. Apart from that, it&#8217;s all the same.<\/p>\r\n\n<h2 class=\"wp-block-heading\">Outlook<\/h2>\n\n<p><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-3-timer-interrupts\" target=\"_blank\" rel=\"noopener\">In my next post<\/a>, I will discuss timer interrupts. In contrast to the pin change interrupts, which are a special feature of the AVR microcontrollers (and the LGT8F328P family), the timer interrupts are again relevant for all microcontrollers.<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.<\/p>\n","protected":false},"author":1,"featured_media":18563,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[543,567],"tags":[556,707,2183,2060,2111,2182,2184,2178,2179,2180,2185,2181,2186],"class_list":["post-18785","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-boards-and-microcontrollers","category-other-stuff","tag-arduino-en-2","tag-attiny85-en","tag-gimsk-en","tag-lgt8f328p-en","tag-minievb-en","tag-pcicr-en","tag-pcie0-en","tag-pcint-en","tag-pcmsk-en","tag-pcmsk0-en","tag-pin-change-enable-bit-en","tag-pin-change-interrupt-en","tag-pin-change-interrupt-control-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2023-09-16T12:26:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-10-13T15:54:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"950\" \/>\n\t<meta property=\"og:image:height\" content=\"950\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"Interrupts &#8211; Part 2: Pin Change Interrupts\",\"datePublished\":\"2023-09-16T12:26:34+00:00\",\"dateModified\":\"2023-10-13T15:54:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts\"},\"wordCount\":1800,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/postimage_interrupts.jpg\",\"keywords\":[\"Arduino\",\"ATtiny85\",\"GIMSK\",\"LGT8F328P\",\"MiniEVB\",\"PCICR\",\"PCIE0\",\"PCINT\",\"PCMSK\",\"PCMSK0\",\"Pin Change Enable Bit\",\"Pin Change Interrupt\",\"Pin Change Interrupt Control\"],\"articleSection\":[\"Boards and Microcontrollers\",\"Other stuff\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts\",\"name\":\"Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/postimage_interrupts.jpg\",\"datePublished\":\"2023-09-16T12:26:34+00:00\",\"dateModified\":\"2023-10-13T15:54:09+00:00\",\"description\":\"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/postimage_interrupts.jpg\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/postimage_interrupts.jpg\",\"width\":950,\"height\":950},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/interrupts-part-2-pin-change-interrupts#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Interrupts &#8211; Part 2: Pin Change Interrupts\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste","description":"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts","og_locale":"en_US","og_type":"article","og_title":"Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste","og_description":"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts","og_site_name":"Wolles Elektronikkiste","article_published_time":"2023-09-16T12:26:34+00:00","article_modified_time":"2023-10-13T15:54:09+00:00","og_image":[{"width":950,"height":950,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg","type":"image\/jpeg"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"Interrupts &#8211; Part 2: Pin Change Interrupts","datePublished":"2023-09-16T12:26:34+00:00","dateModified":"2023-10-13T15:54:09+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts"},"wordCount":1800,"commentCount":2,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg","keywords":["Arduino","ATtiny85","GIMSK","LGT8F328P","MiniEVB","PCICR","PCIE0","PCINT","PCMSK","PCMSK0","Pin Change Enable Bit","Pin Change Interrupt","Pin Change Interrupt Control"],"articleSection":["Boards and Microcontrollers","Other stuff"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts","url":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts","name":"Interrupts - Part 2: Pin Change Interrupts &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg","datePublished":"2023-09-16T12:26:34+00:00","dateModified":"2023-10-13T15:54:09+00:00","description":"Part 2 of my series about interrupts deals with pin change interrupts. These are specific for AVR based Arduino and MiniEVB boards.","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/08\/postimage_interrupts.jpg","width":950,"height":950},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/interrupts-part-2-pin-change-interrupts#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"Interrupts &#8211; Part 2: Pin Change Interrupts"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/18785","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=18785"}],"version-history":[{"count":0,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/18785\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/18563"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=18785"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=18785"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=18785"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}