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
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
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.
ah ... jetzt bin ich eben auch gerade drauf gekommen :-) Datenblatt komplett lesen
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
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"
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.
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?
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.
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
spess53 wrote:
> Garnicht. Der Interrupt wird bei einem Pegelwechsel ausgelöst.
Das ist natürlich nicht zu verleugnen...
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?
Hier mal ein spezifisches Beispiel für PB6: Beim Initialisieren den Interrupt aktivieren
1 | PCICR |= (1<<PCIE0); |
Anschliessend das Bit welches den Interrupt auslösen soll im dazugehörigen Register setzen
1 | PCMSK0 |= (1<<PCINT6); |
ISR wird bei positiver und negativer Flanke an PB6 ausgelöst
1 | ISR (PCINT0_vect) |
2 | {
|
3 | if(PINB & (1<<PB6)) //positive Triggerflanke PB6 |
4 | {
|
5 | //
|
6 | }
|
7 | |
8 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.