Katze1.jpgKatze1b.jpgKatze2.jpgKatze2b.jpgKatze3.jpgKatze3b.jpgKatze4.jpgKatze4b.jpg

Grundlagen

Pin Change Interrupts - Grundlagen

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

 

Arduino mit Breadboard und 4 Tastern

 

 

 

Die vier Taster für den Sketch können auf einem Prototype-Shield aufgebaut werden.

Software

Der Sketch erzeugt folgende Ausgabe im Serial Monitor:

Serielle Ausgabe des Sketch

 

 

 

 

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!

© 2012 Familie Kriwanek
Joomla templates by a4joomla