Interrupts deaktiviert, ISR wird trotzdem benötigt?

OP #5416848
Lesenswert?
• ▲
▼
Hallo,

Ich habe eine kleine Funktion die auf einen Interrupt von INT1 wartet um 
die Pulszeit am INT1 zu messen.
1
uint16_t Capture(void)
2
{
3
  uint8_t sreg = SREG;
4
  cli(); // disable IRQs
5

6
  // enable external interrupt INT1, rising edge
7
  EICRA = (1 << ISC11) | (1 << ISC10);
8
  EIMSK = (1 << INT1);
9
  EIFR = (1 << INTF1);
10

11
  // wait for rising edge
12
  while(! (EIFR & (_BV(INTF1))));
13
  
14
  TCNT1 = 0;
15
  // switch to falling edge
16
  EICRA = (1 << ISC11);
17
  EIFR = (1 << INTF1);  
18
  
19
  // wait for falling edge
20
  while(! (EIFR & (_BV(INTF1))));  
21
  
22
  ret = TCNT1;
23
  
24
  SREG = sreg; // enable IRQs
25
  
26
  return ret;
27
}

Nun resetet sich der AVR aber immer. Sobald ich die ISR einfüge läuft 
es:
1
ISR (INT1_vect) {}

Dann wird sie aber trotzdem aufgerufen, oder?
Ich habe mir gedacht, dass nach dem cli() die ISR nicht gebraucht 
werden, oder? Wie kann ich die ISR "wegoptimieren"?

Ich habe AVR Studio 5.1 mit AVR/GCC.
Gast #5416964
Lesenswert?
• ▲
▼
@ Hugo

Also, mich würde ja auch mal interessieren, ob es einen vernünftigen 
Grund gibt, das so zu machen.

Das Verfahren hat aus meiner Sicht nur Nachteile.

1. Zusätzlicher Aufwand um EICRA, EIMSK und EIFR zu bedienen.
2. Ein Busy-Waiting auf die jeweilige Flanke.

Den Zweck könnte man auch ohne 1. erreichen, selbst wenn man 
Busy-Waiting verwendet.

Und Busy-Waiting wendet man, meiner Meinung nach, auch nur in den ersten 
Programmen an, um das Prinzip der Erkennung von Flanken mal zu lernen. 
Oder, falls definitiv klar ist, dass die nachfolgende Änderung in einem 
Zeitabstand kommt, der nicht gemessen werden muss und kürzer ist, als es 
bräuchte, um einen Timer zu konfigurieren. (Also etwa Status-Abfragen in 
der UART).

Ausserdem kann das, wenn man schon soweit ist, der Timer von alleine - 
ohne Busy-Waiting, so dass die CPU nebenbei noch anderes tun kann.

Magst Du das mal erklären?


Mal Code ohne EICRA und Konsorten (mit irgendeinem Pin der auf Eingang 
konfiguriert ist).
1
uint16_t Capture(void)
2
{
3
  // wait for low
4
  while (! (PORT & (1 << PIN)));
5
  // wait for high
6
  while (PORT & (1 << PIN));
7

8
  ; rising edge occurred
9

10
  TCNT1 = 0;
11
  
12
  // wait for falling edge
13
  while (! (PORT & (1 << PIN)));
14

15
  return (TCNT1);
16
}
#5417075
Lesenswert?
• ▲
▼
> Ich habe eine kleine Funktion die auf einen Interrupt von INT1 wartet um
die Pulszeit am INT1 zu messen.

Ist ganz schlechter Stil. Man sollte nie in einer Funktion warten. Das 
nennt sich blockierend. Und ist sehr schwer zu debuggen. Mach alle 
Funktionen nicht blockierend und warte ausschliesslich im Main.

Mach eine Zustandsvariable im Main und benutze diese zum Reagieren und 
auch zum Debuggen
#5417089
Lesenswert?
• ▲
▼
Gorch F. schrieb:
>> Ich habe eine kleine Funktion die auf einen Interrupt von INT1 wartet um
> die Pulszeit am INT1 zu messen.
>
> Ist ganz schlechter Stil.

Naja, Stil ist für manche ja das Ende des Besens ...

> Man sollte nie in einer Funktion warten. Das
> nennt sich blockierend. Und ist sehr schwer zu debuggen.

Ich sehe überhaupt keinen Grund, warum das schwer zu debuggen sein 
sollte.

> Mach alle
> Funktionen nicht blockierend und warte ausschliesslich im Main.

Oh, nun ist main() blockierend ... ups

Oftmals kann bei simplen Anwendungen die Variante ohne Interrupts 
sinnvoller sein: der Compiler kann besser optimieren und so manche 
push/pop-Orgien sind auch unnötig.

Also: ob polling in simplen µC Anwendungen ohne OS schlecht oder gut 
ist, hängt von einigen Faktoren ;-)

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.