Hallo zusammen
Ich möchte, einen Interrupt mittels Polling erkennen.
Dazu möchte ich das EIRF Register auslesen.
Doch ich weiss nicht genau, wie ich die Register konfigurieren muss,
damit der uC nicht an die Vector Addresse springt. Denn dann wird das
Flag gelöscht.
Hier mein Code:
1
EICRA|=(1<<ISC11)|(1<<ISC01);//INT0 und INT1 auf fallende Flanke (DB Seite: 67)
2
EIMSK|=(1<<INT0)|(1<<INT1);//INT0 und INT1 aktivieren
3
4
sei();
Das ich das EICRA beschreiben muss ist definitiv klar, aber muss ich
auch die Bits im EIMSK setzen? oder bestimme ich damit das gesprungen
wird?
Ich möchte nur, dass das Flag gesetzt wird.
Danke schonmal
Wozu willst du das? Wenn du einen externen Interrupt mittels Polling
überwachen wollst, dann überwache doch einfach den Pin und mach ne
einfache Flankenerkennung:
Marius Wensing schrieb:> Wozu willst du das? Wenn du einen externen Interrupt mittels Polling> überwachen wollst, dann überwache doch einfach den Pin und mach ne> einfache Flankenerkennung:aktuell = einlesen();> if(aktuell != gespeichert)> {> foo();> }> gespeichert = aktuell;>> Gruß> Marius
Danke für die Antwort.
Das wäre eine Möglichkeit, jedoch kann ich das Polling nicht permanent
durchführen.
Die Flanke ist nur kurzzeitig vorhanden, deshalb möchte ich einfach
sobald ich im Programm Zeit fürs Polling habe, schauen, ob der INT
bereits gekommen ist.
Claudio Hediger schrieb:> Die Flanke ist nur kurzzeitig vorhanden, deshalb möchte ich einfach> sobald ich im Programm Zeit fürs Polling habe, schauen, ob der INT> bereits gekommen ist.
Dazu im Interrupt Vektor ein Flag (globale Variable) setzen, und in der
Mainloop abfragen, sobald Zeit dafür ist. So wird das üblicherweise
gemacht
Claudio Hediger schrieb:> Die Flanke ist nur kurzzeitig vorhanden, deshalb möchte ich einfach> sobald ich im Programm Zeit fürs Polling habe, schauen, ob der INT> bereits gekommen ist.
dann setze doch ein Flag im der ISR - wie es andere auf machen.
Im Interrupt ein flag setzten (globale variable) und wieder zurück zum
normalen programm kommen.
Sobald du Zeit hast -> Flag abfragen -> drauf reagieren
Peter II schrieb:> Claudio Hediger schrieb:>> Die Flanke ist nur kurzzeitig vorhanden, deshalb möchte ich einfach>> sobald ich im Programm Zeit fürs Polling habe, schauen, ob der INT>> bereits gekommen ist.>> dann setze doch ein Flag im der ISR - wie es andere auf machen.
Wäre eine Möglichkeit, aber wozu zusätzliche Flags benützen wenn es doch
bereits ein vorhandenes gibt.
Hier ein Auszug aus dem DB:
1
• Bit 1 – INTF1: External interrupt flag 1
2
When an edge or logic change on the INT1 pin triggers an interrupt request, INTF1 becomes set
3
(one). If the I-bit in SREG and the INT1 bit in EIMSK are set (one), the MCU will jump to the corresponding
4
interrupt vector. The flag is cleared when the interrupt routine is executed.
5
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared
6
when INT1 is configured as a level interrupt.
Diesem Text nach, müsste es möglich sein ohne einen Aufruf
durchzukommen.
Aber ich dachte wenn ich im EIMSK die INTs nicht setze, geht garnichts
1
Alternatively, the flag can be cleared by writing a logical one to it.
Macht diese stelle überhaupt Sinn?
Meiner Meinung nach müsste man eine logische 0 schreiben.
Denn es wird ja eine eins gesetzt wenn ein Interrupt eintritt
@ Claudio Hediger (hedie)
>Ich möchte, einen Interrupt mittels Polling erkennen.
Kann man machen.
>Dazu möchte ich das EIRF Register auslesen.
Dann tu das.
>Doch ich weiss nicht genau, wie ich die Register konfigurieren muss,>damit der uC nicht an die Vector Addresse springt. Denn dann wird das>Flag gelöscht.>Hier mein Code:>EICRA |= (1<<ISC11) | (1<<ISC01); //INT0 und INT1 auf fallende Flanke
OK.
>(DB Seite: 67)> EIMSK |= (1<<INT0) | (1<<INT1); //INT0 und INT1 aktivieren
Nö. FREIGEBEN darfst du die Interrupts nicht. Die Funktion zum setzen
der Flags ist aber dennoch aktiv und kann per Polling gelesen und auch
gelöscht werden. Siehe Datenblatt.
>auch die Bits im EIMSK setzen? oder bestimme ich damit das gesprungen>wird?
Ja.
>Ich möchte nur, dass das Flag gesetzt wird.
Also MSK auf 0.
Falk Brunner schrieb:>>Ich möchte, einen Interrupt mittels Polling erkennen.>> Kann man machen.
Danke falk für deine Antwort
Was sagst du dazu:
1
Alternatively, the flag can be cleared by writing a logical one to it.
Macht diese stelle überhaupt Sinn?
Meiner Meinung nach müsste man eine logische 0 schreiben.
Denn es wird ja eine eins gesetzt wenn ein Interrupt eintritt
@ Claudio Hediger (hedie)
>Aber ich dachte wenn ich im EIMSK die INTs nicht setze, geht garnichts
Doch. Die INterruptfunktionen sind praktisch immer aktiv, nur die
Wirkung, nämlich das Ausführen der ISR, wird durch das entsprechende
MSK-Bit gesteuert.
>Alternatively, the flag can be cleared by writing a logical one to it.>Macht diese stelle überhaupt Sinn?
Ja, ist halt eine Ausnahme.
Falk Brunner schrieb:> @ Claudio Hediger (hedie)>>>Aber ich dachte wenn ich im EIMSK die INTs nicht setze, geht garnichts>> Doch. Die INterruptfunktionen sind praktisch immer aktiv, nur die> Wirkung, nämlich das Ausführen der ISR, wird durch das entsprechende> MSK-Bit gesteuert.>>>Alternatively, the flag can be cleared by writing a logical one to it.>>>Macht diese stelle überhaupt Sinn?>> Ja, ist halt eine Ausnahme.
Danke,
Aber den
Alternatively, the flag can be cleared by writing a logical one to
2
> it.
>> Macht diese stelle überhaupt Sinn?
Natürlich macht das Sinn.
Was du brauchst, ist eine Möglichkeit, wie du gezielt eines oder mehrere
Bits im Register atomar löschen kannst.
> Meiner Meinung nach müsste man eine logische 0 schreiben.
Sieh es so an:
Wenn du auf das Register schreibst, beschreibst du nicht das Bit,
sondern du teilst den µC mit, welche Interrupt Request Flags zu löschen
sind.
Claudio Hediger schrieb:> Meiner Meinung nach müsste man eine logische 0 schreiben.
Ja, da hatten die AVR-ler wohl den Schalk im Nacken.
Es stimmt aber, man muß setzen, um zu löschen.
Wenn man z.B. vom 8051 kommt, wo es logisch richtig implementiert ist,
tappt man unweigerlich in diese Fallgrube.
Es gibt dadurch auch unschöne Seiteneffekte. Wenn das Register noch
andere Bits enthält, können Interrupts "versehentlich" gelöscht werden
(OR-/AND-Instruktionen), z.B. Beim TWI oder ADC.
Peter
Peter Dannegger schrieb:> Ja, da hatten die AVR-ler wohl den Schalk im Nacken.
Könnte man meinen wenn man noch nie davon gehört hat.
Aber es ist die beste Lösung.
Claudio Hediger schrieb:
> Meiner Meinung nach müsste man eine logische 0 schreiben.
Das schreiben einer 0 auf das Interrupt bit das du löschen
willst wäre nur dann eine Möglichkeit, wenn du gleichzeitig alle
Bits die du nicht löschen willst mit einer 1 beschreibst.
Da diese Logik aber noch seltsamer wäre als einfach nur alle
Bits die gelöscht werden sollen mit einer 1 zu beschreiben
wurde das nicht so implementiert.
Was garnicht funktionieren würde ist Auslesen, Ausmaskieren und
Zurückschreiben (RMW).
Während so eines RMW Zyklus könnte nämlich ein weiterer Interrupt
kommen der ein bit setzt, und dann geht dieses verloren.
Beispielablauf:
Interrupt 1 passiert:
INT ist 0x01 // interrupt bit 0 ist gesetzt
Auslesen:
A = INT
Interrupt 2 passiert:
INT ist 0x03 // interrupt bit 0 und 1 ist gesetzt
Ausmaskieren
A &= ~0x01
=> A ist 0x00
Zurückschreiben:
INT = A
=> INT ist 0x00, oops wir haben aus versehen interrupt bit 1 gelöscht.
Löscht man dagegen Interrupts durch schreiben einer 1 ist alles ganz
einfach:
Beispielablauf:
Interrupt 1 passiert:
INT ist 0x01 // interrupt bit 0 ist gesetzt
Interrupt 2 passiert (ob jetzt oder später ist egal):
INT ist 0x03 // interrupt bit 0 und 1 ist gesetzt
Schreiben einer 1 auf das bit das gelöscht werden soll (atomar)
INT = 0x01
=> INT ist 0x02 // interrupt bit 1 ist noch gesetzt, die Hardware hat
genau das gewünschte bit gelöscht
Peter Dannegger schrieb:> Es gibt dadurch auch unschöne Seiteneffekte. Wenn das Register noch> andere Bits enthält, können Interrupts "versehentlich" gelöscht werden> (OR-/AND-Instruktionen), z.B. Beim TWI oder ADC.
Genau deswegen macht Atmel es so. Das hat nichts mit Schalk oder
"logisch richtig" zu tun, sondern damit, dass man die Bits, die man
nicht verändern möchte, auf 0 belässt, was beim Zusammensetzen von
Registerwerten über OR automatisch geschieht.
Klar, wer mit den Bit-Set/Bit-Clear-Assemblerbefehlen einzelne Bits
anspricht, für den wirkt das unintuitiv, aber wenn man das gesamte
Register beschreiben möchte, für den ist das ungemein bequem, diese Bits
einfach ignorieren zu dürfen, die einen nicht interessieren.