Forum: Mikrocontroller und Digitale Elektronik Funktionen vs Interrupts


von robert (Gast)


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

von Karl H. (kbuchegg)


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.

von robert (Gast)


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 ?

von Karl H. (kbuchegg)


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.

von Peter D. (peda)


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

von robert (Gast)


Angehängte Dateien:

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

von Kanzler Gorkon (Gast)


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).

von Karl H. (kbuchegg)


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
1
#pragma vector=ADC_vect
2
__interrupt void CurrentMeasurementComplete()
3
{
4
  shuntVoltageADC = ADCH;
5
  currentUpdated = TRUE;
6
  CLEAR_ALL_TIMER0_INT_FLAGS;
7
}

und da steht klar dabei
1
#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.

von Johannes M. (johnny-m)


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...

von robert (Gast)


Lesenswert?

Jetzt ist mir das klar. Vielen Dank für die Hilfe !!!

Grüße

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.