www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega2560 + PCINT


Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein kleines Problem, und zwar ich möchte bei meinem STK600 mit 
Atmega2560 die PCINT Interrupts nutzen. Aber irgendwie funktioniert es 
nicht. Es soll so ablaufen, dass sobald ich einen Taster drücke ein 
Interrupt auslöse und dann z.B. die LEDs angehen.
Hier wäre mein Code:

#include <avr/io.h>
#include <avr/interrupt.h

void ir_int_init(void)

int main(void)
{
   int k = 0;
   DDRJ = 0x00;
   DDRC = 0xff;
   PORTC = 0xff;
   ir_int_init();
   sei();
   for(;;)
      k++;
}

void ir_int_init(void) //Initialize interrupt
{
   PCICR = (1<<PCIE1);
   PCMSK1 = (1<<PCINT9);
}

ISR (PCINT9_vect)
{
   if(PINJ & S0)
   {
      PORTC = 0x00;
   }
}

Das entsprechende Bit in PCICR, PCMSKI und SREG wird korrekt gesetzt - 
aber es tut sich nichts, d.h. es wird nicht mal in die ISR 
reingesprungen.

Vielleicht kann mir ja jemand helfen - wäre lieb.

Viele Grüße,
Anja

Autor: Dirk Broßwick (sharandac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

sollte eigentlich funktionieren bist auf die If-Abfrage ... bleibt nur 
noch die frage wozu die If-Abfrage da ist? Schon mal ohne versucht und 
einfach die LED schalten ohne Bedingung? Und wie hast du den Port 
beschalten, Widerstand gegen Masse und Taster gegen Plus ?

CA Dirk

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anja wrote:
> ISR (PCINT9_vect)
Den PCINT9_vect gibt es nicht! Der Pin PCINT9 ist dem Vektor PCINT1 
zugeordnet. Du musst zwischen den Vektorbezeichnungen und den Pins 
unterscheiden. Jedem Vektor sind 8 Pins zugeordnet, die bei 
entsprechender Maskierung alle den selben Interrupt auslösen.

Pinchange-Interrupt-Vektoren gibt es beim Mega256x nur drei, nämlich 
PCINT0, 1 und 2. Dein Code oben dürfte eigentlich gar nicht kompilieren, 
weil der Compiler eben PCINT9_vect nicht kennen kann.

Autor: Dirk Broßwick (sharandac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ... jetzt bin ich eben auch gerade drauf gekommen :-) Datenblatt 
komplett lesen

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja die IF Abfrage gehört natürlich raus :-)
Wie muß ich das denn dann machen? Ich checks irgendwie nicht anhand des 
Datenblattes wie das funktioniert mit den PCINT. Wo seh ich denn welchem 
Vector welche 8 Pins zugeordnet sind?
Kompilieren ging das mit dem AVR-GCC eigentlich ohne Probleme.
Also die LEDs sind Low aktiv geschalten.
Kannst dus mir vielleicht ein bisschen erklären wie das funktioniert?

Liebe Grüße,
Anja

Autor: Philipp H. (swissrookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Datenblatt unter 15:

"The Pin change interrupt PCI2 will trigger if any enabled PCINT23:16 
pin toggles, Pin change interrupt PCI1 if any enabled PCINT15:8 toggles 
and Pin change interrupts PCI0 will trigger if any enabled PCINT7:0 pin 
toggles. PCMSK2, PCMSK1 and PCMSK0 Registers control which pins 
contribute to the pin change interrupts. Pin change interrupts on 
PCINT23 :0 are detected asynchronously. This implies that these 
interrupts can be used for waking the part also from sleep modes other 
than Idle mode.kursiv"

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt drei Vektoren und jedem Vektor sind 8 Portpins zugeordnet, die 
den betreffenden Interrupt auslösen können. Welche Pins ihn tatsächlich 
auslösen, wird in den PCIMSK-Registern eingestellt, in denen jedes Bit 
einem Portpin entspricht. Wenn mehr als ein Pin maskiert ist, muss die 
Anwendungssoftware evtl. im Falle des Auftretens des Interrupts die Pins 
abfragen, um herauszufinden, welcher es war.

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also muß ich das dann praktisch so machen:
#include <avr/io.h>
#include <avr/interrupt.h

void ir_int_init(void)

int main(void)
{
   int k = 0;
   DDRB = 0x00;
   DDRC = 0xff;
   PORTC = 0xff;
   ir_int_init();
   sei();
   for(;;)
      k++;
}

void ir_int_init(void) //Initialize interrupt
{
   PCICR = (1<<PCIE0);
   PCMSK1 = 0xff;
}

ISR (PCI0_vect)
{
   PORTC = 0x00;
}

Und wie kann ich dann sagen lös nur ein Interrupt aus, wenn ein Signal 
an PB6 anliegt?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anja wrote:
>    PCICR = (1<<PCIE0);
>    PCMSK1 = 0xff;
Das PCIMSK1 hat nichts mit PCI0 zu tun! Wenn PCI0 ausgelöst werden soll, 
musst Du auch im richtigen PCIMSK-Register die Pins auswählen.

> Und wie kann ich dann sagen lös nur ein Interrupt aus, wenn ein Signal
> an PB6 anliegt?
Indem Du den entsprechenden Pin im richtigen PCIMSK-Register auswählst 
und den dazugehörigen Interrupt freigibst.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Und wie kann ich dann sagen lös nur ein Interrupt aus, wenn ein Signal
>an PB6 anliegt?

Garnicht. Der Interrupt wird bei einem Pegelwechsel ausgelöst. In der 
ISR musst du den Pegel prüfen und entsprechende Reaktionen einleiten.

MfG Spess

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 wrote:
> Garnicht. Der Interrupt wird bei einem Pegelwechsel ausgelöst.
Das ist natürlich nicht zu verleugnen...

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PCMSK0 = 0xff; //Damit müßte ich ja die komplette Gruppe auswählen
PCICR = (1<<PCIE0);

in der main halt dann sei() und die isr dann ISR(PCINT0_vect) {}

Oder lieg ich jetzt hier wieder falsch?

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry in der ISR (PCI0_vect) {}

Autor: Philipp H. (swissrookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein spezifisches Beispiel für PB6:

Beim Initialisieren den Interrupt aktivieren
PCICR |= (1<<PCIE0);
Anschliessend das Bit welches den Interrupt auslösen soll im 
dazugehörigen Register setzen
PCMSK0 |= (1<<PCINT6); 

ISR wird bei positiver und negativer Flanke an PB6 ausgelöst
ISR (PCINT0_vect)
{
  if(PINB & (1<<PB6))   //positive Triggerflanke PB6
  {
       //
  }

} 

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.