Forum: Mikrocontroller und Digitale Elektronik AVR ATiny84: Interrupt Flags und Reihenfolge


von Christian J. (Gast)


Lesenswert?

Hallo,

bei der Vergewaltigung der Arduino IDE durch Umgehung der 
"Nutzfunktionen" bin ich derzeit an einer Interruptgeschichte über den 
INT0 dran. Leider weiss ich nicht ganz genau wann welches Bit gesetzt 
wird.

Int Ereignis -> INTF0
ISR Routine -> CLI -> INTF0 = 0?

Habe erstmal diese Makros definiert:

#define INT0_DISABLE     GIMSK &= ~_BV(INT0)
#define INT0_ENABLE    GIMSK |= _BV(INT0)
#define INT0_CLEAR_PENDING  GIFR  |= _BV(INTF0)

Wann genau wird das INTF0 gelöscht durch die Hardware? Beim Eintritt in 
die Routine oder beim Raustritt? Ich brauche das nämlich damit mir keine 
Pending Ints direkt nach der ISR wieder reinhauen, wenn SEI die Global 
Ints wieder zulässt.

Ne blöde Frage: Wie kann man bei einem Level Interrupt verhindern, dass 
der ständig aufgerufen wird, wenn der Puls etwas länger ist als die 
Reaktionszeit der CPU? Wenn der ADXL345 Sensor nämlich seinen FIFO 
Overflow INT Pin auf HIGH lässt während meine CPU im Tiefschlaf schläft, 
dann kommt sie nie wieder da raus, wenn ich RISING einstelle. Idle Mode 
wäre eine Läsung aber mehr Strom eben.


Gruss,
Christian

von Thomas E. (thomase)


Lesenswert?

Christian J. schrieb:
> Wann genau wird das INTF0 gelöscht durch die Hardware? Beim Eintritt in
> die Routine oder beim Raustritt? Ich brauche das nämlich damit mir keine
> Pending Ints direkt nach der ISR wieder reinhauen, wenn SEI die Global
> Ints wieder zulässt.

Das Flag wird am Anfang gelöscht, wenn der Controller auf den 
Interrupt-Vektor springt. Von einer ISR weiss er gar nichts.

> Ne blöde Frage: Wie kann man bei einem Level Interrupt verhindern, dass
> der ständig aufgerufen wird, wenn der Puls etwas länger ist als die
> Reaktionszeit der CPU? Wenn der ADXL345 Sensor nämlich seinen FIFO
> Overflow INT Pin auf HIGH lässt während meine CPU im Tiefschlaf schläft,
> dann kommt sie nie wieder da raus, wenn ich RISING einstelle. Idle Mode
> wäre eine Läsung aber mehr Strom eben.

Das verstehe ich jetzt überhaupt nicht.

mfg.

von Christian J. (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Das verstehe ich jetzt überhaupt nicht.

Bei einem Level IRQ wird solange immer eine neue Anforderung erzeugt, 
wie das Signal anliegt. D.h. es passiert oft bei mir, dass er sofort 
nach Verlassen der ISR direkt wieder reinspringt, weil das Pending Bit 
gesetzt wurde. Vermutlich muss man das einfach nur löschen mit "1", ich 
hatte angenommen  dass "0" es löschen würde.

von Thomas E. (thomase)


Lesenswert?

Christian J. schrieb:
> Thomas Eckmann schrieb:
>> Das verstehe ich jetzt überhaupt nicht.
>
> Bei einem Level IRQ wird solange immer eine neue Anforderung erzeugt,
> wie das Signal anliegt. D.h. es passiert oft bei mir, dass er sofort
> nach Verlassen der ISR direkt wieder reinspringt, weil das Pending Bit
> gesetzt wurde. Vermutlich muss man das einfach nur löschen mit "1", ich
> hatte angenommen  dass "0" es löschen würde.

Ein Interrupt-Flag wird mit 1 gelöscht. Und zwar mit:
1
GIFR = (1 << INTF0);

Aber nicht so:
1
GIFR |= (1 << INTF0);

Das würde alle anderen Flags auch loeschen.

mfg.

von Peter D. (peda)


Lesenswert?

Christian J. schrieb:
> während meine CPU im Tiefschlaf schläft,
> dann kommt sie nie wieder da raus, wenn ich RISING einstelle.

Zum Aufwachen besser den Pin-Change-Interrupt nehmen.

Der Level-Interrupt ist nur sinnvoll für Peripherie mit mehreren 
Interruptquellen. Man springt dann solange wieder in den Interrupt, bis 
alle Quellen abgearbeitet sind.

von Christian J. (Gast)


Lesenswert?

Peter Dannegger schrieb:

> Christian J. schrieb:
>> während meine CPU im Tiefschlaf schläft,
>> dann kommt sie nie wieder da raus, wenn ich RISING einstelle.
>
> Zum Aufwachen besser den Pin-Change-Interrupt nehmen.
>
> Der Level-Interrupt ist nur sinnvoll für Peripherie mit mehreren
> Interruptquellen. Man springt dann solange wieder in den Interrupt, bis
> alle Quellen abgearbeitet sind.

Dankie für den Tip mit dem I-Flag, hätte das jetzt glatt falsche 
gemacht. Aber mal ein paar allgemeine Fragen. Auch wenn ich bisher alles 
ans Rennen gekriegt habe.

Ich habe den Attiny84 an einen ADXL345 geflanscht. Der Chip ist buggy, 
die Z-Achse ist bei allen 5 Stück kaputt, das wurde auch vom Händler 
bestätigt. Ihr Offset liegt weit außerhalb des Kalibrierbereichs. Aber 
das soll nicht das Thema sein.

Peter, Du würdest also den Rising Int, der so sein muss vor dem Sleep 
auf Pin Change umschalten, damit auch der PWR-DOWN Mode genutzt werden 
kann? der ADXL345 löst alle 4s einen INT aus, wenn sein FIFO voll ist. 
Und wenn die CPU wach ist wieder auf Rising umstellen?

von Thomas E. (thomase)


Lesenswert?

Christian J. schrieb:
> Peter, Du würdest also den Rising Int, der so sein muss vor dem Sleep
> auf Pin Change umschalten, damit auch der PWR-DOWN Mode genutzt werden
> kann? der ADXL345 löst alle 4s einen INT aus, wenn sein FIFO voll ist.
> Und wenn die CPU wach ist wieder auf Rising umstellen?

Ich weiss ja nicht, was Peter empfiehlt, aber ich würde nur den 
Pinchange nehmen und den Pin-Status am Anfang der ISR abfragen.

Das setzt aber voraus, dass der auch mindestens so lange anliegt.

mfg.

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
Noch kein Account? Hier anmelden.