www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Funktionen vs Interrupts


Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche gerade die Atmel Applicationnote 444 zu verstehen.

Hier werden viele Funktionen in der Form

void Funktion(void)
{
...
}

eingeführt. Das ist mir auch verständlich.

Neu ist mir allerdings, wie hier Interruptroutinen deklariert werden.
Diese sehen z.B. so aus:

__interrupt void CurrentMeasurement()
{
...
}

Meine Frage ist, was nun der Unterschied zwischen beiden ist und warum 
man manchmal Funktionen und manchmal Interrupts hernimmt.
Außerdem habe die diese Form mit "__interrupt void..." noch nicht 
gesehen.
Würde ich diesen dann wie eine Funktion aufrufen, also einfach mit

CurrentMeasurement();

Bin über jegliche Hilfe sehr dankbar.

Grüße

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
robert wrote:

> Neu ist mir allerdings, wie hier Interruptroutinen deklariert werden.
> Diese sehen z.B. so aus:
>
> __interrupt void CurrentMeasurement()
> {
> ...
> }
>
> Meine Frage ist, was nun der Unterschied zwischen beiden ist und warum
> man manchmal Funktionen und manchmal Interrupts hernimmt.

Ein Interrupt ist ein völlig anderes Konzept als eine normale
Funktion.
Eine normale Funktion wird aufgerufen, wenn in deinem Programm
ein Aufruf dazu vorkommt.
Ein Interrupt hingegen wird mit einem Ereignis gekoppelt. Wenn
dieses Ereignis eintritt, dann wird die Interrupt Funktion aufgerufen.
Die Interrupt Funktion kann also zu jedem beliebigen Zeitpunkt
ausgelöst werden, wobei das Auslösen vom Auftreten irgendwelcher
Dinge abhängt. In einem AVR sind ISR (Interrupt Service Routine)
immer an irgendwelche Dinge der Hardware gekoppelt. Ein Timer
macht zb gerade einen Überlauf und kann als Folge davon einen
Overflow-Request absetzen. Hat man eine ISR Funktion für
diesen Fall vorgesehen und diese auch entsprechend registriert,
dann wird die Funktion aufgerufen sobald der Timer einen Overflow
meldet, unabhängig davon wo sich das restliche Programm gerade
rumtreibt.

> Außerdem habe die diese Form mit "__interrupt void..." noch nicht
> gesehen.

Das ist compilerspezifisch. Interrupts sind ausserhalb der
C-Norm, daher gibt es dafür kein standardisiertes Sprachkonstrukt.

> Würde ich diesen dann wie eine Funktion aufrufen, also einfach mit

Du rufst sie gar nicht auf. Du installierst sie nur und gibst
den zugehörigen Interrupt frei. Tritt das Ereignis ein, wird
die Funktion aufgerufen.

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, vielen Dank soweit.

Ich würde also hier

__interrupt void CurrentMeasurement()
{
...
}

nur reinschreiben, was nach dem Interruptaufruf abgearbeitet werden 
soll.

Was ich allerdings nicht finde, wo und das Ereignis festgelegt wird, 
welches den Interrupt aufruft.

Die Harwareroutinen sind mir klar. Z.B. Ein Timer Overflow Interrupt 
wird ausgelöst, wenn ein entsprechendes Interrupt Flag gesetzt wird. In 
den Atmel Datenblätter sind ja alle solchen Interrupts aufgeführt. Über 
Softwareinterrupts habe ich nun die Möglichkeit, mir selber welche zu 
erzeugen.
Wenn ich z.B. will, dass immer, wenn ein ADC einen Wert von 500 
überschreitet, eine Interruptroutine ausgeführt wird, dann müsste ich 
diese Bedingung irgendwo einführen. Wie würde dan dann aussehen ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
robert wrote:

> __interrupt void CurrentMeasurement()
> {
> ...
> }
>
> nur reinschreiben, was nach dem Interruptaufruf abgearbeitet werden
> soll.
>
> Was ich allerdings nicht finde, wo und das Ereignis festgelegt wird,
> welches den Interrupt aufruft.

Normalerweise ist das Ereignis bei einem AVR in irgendeiner Form
durch den 'Funktionsnamen' oder einen Zusatz dazu festgelegt.

> den Atmel Datenblätter sind ja alle solchen Interrupts aufgeführt. Über
> Softwareinterrupts habe ich nun die Möglichkeit, mir selber welche zu
> erzeugen.

Von welchem Atmel Chip reden wir?

> Wenn ich z.B. will, dass immer, wenn ein ADC einen Wert von 500
> überschreitet, eine Interruptroutine ausgeführt wird, dann müsste ich
> diese Bedingung irgendwo einführen. Wie würde dan dann aussehen ?

Bei einem 8-Bit AVr, wie er hier im Forum gang und gäbe ist?
Gar nicht.
Welche Interrupts es gibt, ist von der Hardware (vom Prozessor)
vorgegeben.
Bei den Wald und Wiesen AVR, kann ein ADC m.W. lediglich einen
Interrupt auslösen, wenn er eine Messung fertig hat. Es steht dir
natürlich frei innerhalb der ISR den gemessenen Wert mit 500 zu
vergleichen und dann weiter darauf zu reagieren. Aber einen Interrupt
speziell für den Fall, dass der ADC Wert eine Grenze übersteigt, ist
nicht vorgesehen (*)

(*) Was nicht unbedingt heist, dass es nicht einen Prozessor auf
diesem Planeten gibt, der auch das kann. Die üblichen ATMegaXX
und ATTinyXX, mit denen wir es hier im Forum zu tun haben, können
es nicht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
robert wrote:

> Wenn ich z.B. will, dass immer, wenn ein ADC einen Wert von 500
> überschreitet, eine Interruptroutine ausgeführt wird, dann müsste ich
> diese Bedingung irgendwo einführen. Wie würde dan dann aussehen ?

Das geht nicht.

Du kriegst jedesmal nen Interrupt, wenn der ADC mit Messen fertig ist.
Und in dem Interrupt mußt Du dann den ADC-Wert mit 500 vergleichen und 
dann die gewünschte Task ausführen.


Es gibt allerdings MCs, die sowas können, z.B. die Silabs 8051.


Peter

Autor: robert (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich benutze den Atmel Mega 168

Dann habe ich es wohl falsch verstanden, dass ich mir beliebige 
Interruproutinen "zusammenbasteln" kann ?
Aber wann wird dann eine solche Interruptroutine überhaupt aufgerufen ?

__interrupt void CurrentMeasurement()
{
...
}

Diesen Auszug habe ich im Anhang zusammengestellt. Man findet ihn in 
main.c, Seite 9

Autor: Kanzler Gorkon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diese Funktion musst Du Dir selber aufrufen, dann weisst Du auch wann 
das passiert.
Interrupts, die an eine Hardware gekoppelt sind haben spezielle Namen 
(siehe Datenblatt).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
robert wrote:
> Aber wann wird dann eine solche Interruptroutine überhaupt aufgerufen ?
>
> __interrupt void CurrentMeasurement()
> {
> ...
> }

In deinem ganzen Auszug gibt es keine Funktion dieses Namens,
es gibt aber eine CurrentMeasurementComplete
#pragma vector=ADC_vect
__interrupt void CurrentMeasurementComplete()
{
  shuntVoltageADC = ADCH;
  currentUpdated = TRUE;
  CLEAR_ALL_TIMER0_INT_FLAGS;
}

und da steht klar dabei
#pragma vector=ADC_vect

dass diese Funktion ein Interrupt Handler für den ADC Interrupt
ist, als aufgerufen wird, wenn der ADC mit einer Messung fertig
ist.

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

Bewertung
0 lesenswert
nicht lesenswert
robert wrote:
> __interrupt void CurrentMeasurement()
> {
> ...
> }
Das ist auch nur die halbe Wahrheit. Da gehört noch die Zeile mit dem 
#pragma dazu, die definiert, für welchen Interrupt-Vektor der Handler 
sein soll. Die Software der Appnote ist für den IAR-Compiler geschrieben 
und jeder Compiler benutzt, wie Karl Heinz schon gesagt hat, eine 
compilerspezifische Syntax für solche nicht-ANSI-Erweiterungen. Wenn Du 
nicht mit dem IAR-Compiler arbeitest, musst Du die Definitionen der 
Interrupt Handler entsprechend ändern (und auch noch einige andere Dinge 
wie verwendete Bibliotheken usw.).

Generell kann ein Interrupt Handler nicht aus dem laufenden Programm 
heraus aufgerufen werden, sondern ausschließlich von dem damit 
zusammenhängenden Hardware-Ereignis. Und wie das generell geht, ist im 
AVR-Tutorial bzw. im AVR-GCC-Tutorial ganz gut beschrieben.

EDIT:
Jetzt dachte ich ja, ich wär mal schneller als Karl Heinz, aber wieder 
nix...

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt ist mir das klar. Vielen Dank für die Hilfe !!!

Grüße

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.