Grundlagen
Pin Change Interrupts - Grundlagen
- Details
- Hauptkategorie: Arduino
- Zuletzt aktualisiert am Donnerstag, 14. Juni 2012 14:08
In Arbeit!
Der Arduino stellt nur zwei externe Interrupts zur Verfügung, welche von der IDE unterstützt werden. Die Atmel CPU bietet aber die Möglichkeit, nahezu jeden Prozessor-Pin für Interrupts zu verwenden. Insgesamt sind 20 Interrupts verfügbar:
| Arduino-Pin | Pin# | Port# | Port Cmd | PCIE | PCMASK | INT | IRQ Service | Bemerkung |
| Hinweis 1 | Hinweis 2 |
Hinweis 3 | Hinweis 4 | Hinweis 5 | Hinweis 6 | Hinweis 7 | Hinweis 8 | --- |
| Digital Pin 0 | 0 | D | PIND | PCIE2 | PCMASK2 | PCINT16 | PCINT2_vect | Seriell Rx |
| Digital Pin 1 | 1 | D | PIND | PCIE2 | PCMASK2 | PCINT17 | PCINT2_vect | Seriell Tx |
| Digital Pin 2 | 2 | D | PIND | PCIE2 | PCMASK2 | PCINT18 | PCINT2_vect | ext. INT0 |
| Digital Pin 3 | 3 | D | PIND | PCIE2 | PCMASK2 | PCINT19 | PCINT2_vect | ext. INT1 |
| Digital Pin 4 | 4 | D | PIND | PCIE2 | PCMASK2 | PCINT20 | PCINT2_vect | DFRobots Shield |
| Digital Pin 5 | 5 | D | PIND | PCIE2 | PCMASK2 | PCINT21 | PCINT2_vect | DFRobots Shield |
| Digital Pin 6 | 6 | D | PIND | PCIE2 | PCMASK2 | PCINT22 | PCINT2_vect | DFRobots Shield |
| Digital Pin 7 | 7 | D | PIND | PCIE2 | PCMASK2 | PCINT23 | PCINT2_vect | DFRobots Shield |
| Digital Pin 8 | 8 | B | PINB | PCIE0 | PCMASK0 | PCINT0 | PCINT0_vect | DFRobots Shield |
| Digital Pin 9 | 9 | B | PINB | PCIE0 | PCMASK0 | PCINT1 | PCINT0_vect | DFRobots Shield |
| Digital Pin 10 | 10 | B | PINB | PCIE0 | PCMASK0 | PCINT2 | PCINT0_vect | DFRobots Shield |
| Digital Pin 11 | 11 | B | PINB | PCIE0 | PCMASK0 | PCINT3 | PCINT0_vect | verfügbar |
| Digital Pin12 | 12 | B | PINB | PCIE0 | PCMASK0 | PCINT4 | PCINT0_vect | verfügbar |
| Digital Pin13 | 13 | B | PINB | PCIE0 | PCMASK0 | PCINT5 | PCINT0_vect | interne LED |
| Analog Input 0 | 14 | C | PINC | PCIE1 | PCMASK1 | PCINT8 | PCINT1_vect | DFRobots Shield |
| Analog Input 1 | 15 | C | PINC | PCIE1 | PCMASK1 | PCINT9 | PCINT1_vect | verfügbar |
| Analog Input 2 | 16 | C | PINC | PCIE1 | PCMASK1 | PCINT10 | PCINT1_vect | verfügbar |
| Analog Input 3 | 17 | C | PINC | PCIE1 | PCMASK1 | PCINT11 | PCINT1_vect | verfügbar |
| Analog Input 4 | 18 | C | PINC | PCIE1 | PCMASK1 | PCINT12 | PCINT1_vect | I2C-Bus SDA |
| Analog Input 5 | 19 | C | PINC | PCIE1 | PCMASK1 | PCINT13 | PCINT1_vect | I2C-Bus SCL |
Die beiden externen Interrupts sollten mit den Befehlen der IDE bearbeitet werden. Verwendet man die serielle Schnittstelle oder den I2C-Bus, verringert sich die Anzahl der verfügbaren Interrupts. Soll für das Projekt ein DFRobots Shield eingesetzt werden fallen ebenfalls einige Pins weg. Frei verfügbar sind die Pins:
- Digital Pin 11
- Digital Pin 12
- Analog Input 1
- Analog Input 2
- Analog Input 3
ddd
Hardware
![]() |
Die vier Taster für den Sketch können auf einem Prototype-Shield aufgebaut werden. |
Software
Der Sketch erzeugt folgende Ausgabe im Serial Monitor:
![]() |
Der Serial Monitor ist auf 9600 Baud einzustellen. |
Sketch
/***************************************************************************** * Sketch: PC_IRQ_SINGLE.pde * Author: A. Kriwanek: http://www.kriwanek.de/arduino/komponenten.html * Version: 1.0 26.06.2011/14:35 * * This sketch is waiting for a pin change interrupt on an Arduino pin. If an interrupt * occurs, the interrupt service routine is called. The routine increments a counter- * The main program sends the counter value over the serial port. The interrupt * service routine debounces the input signal (e.g. for a switch contact). * * This sketch is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * *****************************************************************************/ //----------------------------------------------------------------------------- // Define values for the interrupt counter: volatile int counter1 = 0; // Counter incremented by pin change interrupt volatile int bounceTime = 20; // Switch bouncing time in milliseconds volatile unsigned long IRQ1PrevTime; // Last time in milliseconds IRQ1 arrived volatile int IRQ1PrevVal = 0; // Contact level last IRQ1 volatile int irqFlag1 = 0; // 1=display counter after IRQ1; 0=do nothing // Setup and Main: void setup(){ Serial.begin(9600); // Initialize serial interface with 9600 Baud Serial.write("Waiting for an interrupt...\n"); // Make Arduino Pin 7 (PCINT23/PD7) an input and set pull up resistor: pinMode(7, INPUT); digitalWrite(7, HIGH); // This is ATMEGA368 specific, see page 75 of long datasheet // PCICR: Pin Change Interrupt Control Register - enables interrupt vectors // Bit 2 = enable PC vector 2 (PCINT23..16) // Bit 1 = enable PC vector 1 (PCINT14..8) // Bit 0 = enable PC vector 0 (PCINT7..0) PCICR |= (1 << PCIE2); // Set port bit in CICR // Pin change mask registers decide which pins are enabled as triggers: PCMSK2 |= (1<<PCINT23); // Set pin interrupt for digital input IRQ1PrevTime=millis(); // Hold actual time interrupts(); // Enable interrupts } void loop() { // Place your main loop commands here (e.g. output to LCD) if (irqFlag1==1) // Flag was set by IRQ1 routine { Serial.write("IRQ rising edge, Counter = "); Serial.println(counter1); irqFlag1=0; // Reset IRQ1 flag } } //----------------------------------------------------------------------------- // Subs and Functions: ISR(PCINT2_vect) { // You have to write your own interrupt handler. Don't change the name! // This code will be called anytime when PCINT23 switches high to low, // or low to high. byte PVal; // Port value (8 Bits) byte IRQ1ActVal; // Actual IRQ1 value long unsigned IRQ1ActTime; PVal = PIND; // Read port D (8 bit) IRQ1ActVal = PVal & (1<<PCINT23); // Mask out all except IRQ1 IRQ1ActVal = IRQ1ActVal >> PCINT23; // shift to right for bit0 position IRQ1ActTime=millis(); // Read actual millis time if(IRQ1ActTime - IRQ1PrevTime > bounceTime) // No bouncing anymore: { // No contact bouncing anymore: if(IRQ1PrevVal==0 && IRQ1ActVal==1) // Transition 0-->1 { // Place your command for rising signal here... counter1++; if(counter1>255) counter1 = 0; IRQ1PrevTime=IRQ1ActTime; IRQ1PrevVal=IRQ1ActVal; irqFlag1=1; } if(IRQ1PrevVal==1 && IRQ1ActVal==0) // Transition 1-->0 { // Place your command for falling signal here... IRQ1PrevVal=IRQ1ActVal; } } }
Das Programm befindet sich Download-Bereich!










