Forum: Mikrocontroller und Digitale Elektronik Frage zu Interrupt


von Zoltan (Gast)


Lesenswert?

Ich hätte eine Frage zu AVR Studio(C), und zwar:
In einer Funktion wird ein Interrupt ausgelöst. Nachdem das Programmteil 
dort abgearbeitet wurde, wird das Programm an der Stelle wieder 
fortgesetzt, an welcher der Interrupt auftrat.?
Wie kann ich nun das Programm, nach Abarbeitung des Interruppts.., aber 
irgendwo anders, zB. in einer anderen Funktion weiterlaufen lassen?

Danke
Zoltan

von mikki merten (Gast)


Lesenswert?

Geht nach folgendem Schema:

POP   R16    ;alte Return Adresse vom Stack entfernen
POP   R16
LDI   R16,low(RETURN_ADRESSE)
push  R16
LDI   R16,high(RETURN_ADRESSE)
push  R16
reti

Alternativ geht auch:

POP   R16    ;alte Return Adresse vom Stack entfernen
POP   R16
JMP   RETURN_ADRESSE

Hier müssen allerdings mit CLI die Interrupts wieder freigegeben werden.

von Zoltan (Gast)


Lesenswert?

Hallo miki.
Danke für die Antwort.
Ich programmiere das ganze aber in C, und Assembler ist nicht gerade 
meine Stärke.

von Zoltan (Gast)


Lesenswert?

Sorry heisst natürlich mikki..

von crazy horse (Gast)


Lesenswert?

solche Sachen  sind in C nicht machbar. Du kannst aber Assemblerroutinen 
innerhalb des C-Programmes einfügen.
#asm
 Assemblerbefehle
#endasm
Und wie du die Adresse des Sprungziels in den Assemblercode bekommst, 
weiß ich auch nicht, geht aber wahrscheinlich.
Wofür soll das ganze eigentlich gut sein?
Gibt sicher ne andere Möglichkeit, daß sauber zu lösen.
Problematisch ist so eine Sache auf jeden Fall, vor allem in Bezug auf 
die Wartbarkeit solcher Programme.Mußt auch aufpassen, welche Register 
du in einem Assemblerteilprogramm verwendest, beim nächsten 
Compiler-update kann die Registerverteilung anders sein, ebneso beim 
Verwenden verschiedener Compileroptimierungen.

von Zoltan (Gast)


Lesenswert?

>Wofür soll das ganze eigentlich gut sein?

Ich möchte, nachdem irgendwo ein Interrupt auftrat, die Aufgaben im 
Intrerrupt abarbeiten und von da ins Main springen. Ich habe jetzt 
einfach am Ende der Interrupt Funktion noch folgendes eingefügt: main() 
, womit er ins Main springt, aber ich glaube Main darf man nicht 
aufrufen, oder?

von crazy horse (Gast)


Lesenswert?

ich sage einfach mal, daß geht schief. Du hast ja in einem C-Programm 
nicht nur den SP für die Adressen/push/pop, sondern auch noch den 
Datenstack. Stackfehler sind da vorprogrammiert. Funktionerende 
Holzhammermethode wäre ein Sprung nach Adr 0, kostet aber relativ viel 
Zeit und du verlierst alle Variablen, ist also auch nicht das Wahre.
Warum du das alles machen willst/mußt, hat sich mir aber immer noch 
nicht offenbart.

von Zoltan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo crazy horse

Das Programm ist eine Steuerung für einen Modell-Uboot. Es wird zuerst 
die Pulsplänge vom Sender gemessen, dann die Signale von einem 
Drucksensor und einem Neigungssensor(ADXL202).Der Neigungssensor wird 
noch Temperaturkompensiert, daher die lange Tabelle am Anfang. UART und 
Handschaltung...

Das Problem ist, (es läft bis jetzt alles bestens), das ich noch einen 
Senderausfall programmieren wollte. Dabei wartet der MC 100ms. Wenn 
innerhalb dieser Zeit nichts vom Empfänger kommt, dann erzeugt er eine 
vorgeben Pulslänge für den Tiefenruderservo, so das das Boot 
"automatisch" auftaucht. Dabei tritt eben dieser Fall auf, welches ich 
oben beschrieben habe. Das Programm gerät durcheinander. Ich habs jetzt 
aber gelöst, indem ich im Interrupt nicht zurück, sonder nach main 
springe, da wollte ich auch hin. Aber das ist so,glaube ich, nicht 
schön??

von Peter D. (peda)


Lesenswert?

Du hast recht, das ist nicht schön und obendrein noch fehlerhaft.

Wenn Du im Interrupt das main() aufrufst, dann beendest Du ihn ja nicht. 
Somit z.B. beim 10. Senderausfall läuft vielleicht Dein Stack über und 
das Programm stürzt ab.


Die übliche Herangehensweise:

Man setzt im Interrupt ein Bit und in der Main-Loop testet man dann 
dieses Bit ab und startet dort die entsprechende Behandlungsroutine.


Peter

von Reiner Patommel (Gast)


Lesenswert?

Wenn Du unbedingt zu main() zurück willst, warum benutzt Du dann nicht 
den watchdog ?  Empfänger re-triggert WD.  Bei Ausfall des Triggers 
reboot.

von Zoltan (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für Eure Antworten.
Ich habe das Problem jetzt ohne den Aufruf von Main lösen können. Der 
Aufruf war garnicht nötig, denn das Programm läuft sowiso in die Main 
Funktion. Ich habs mir halt wieder schwer gemacht...
Vollständigkeitshalber nochmal die geänderte Code im Anhang.

von MarkusS (Gast)


Lesenswert?

Hallo,

generell kann man solche Probleme mit,
setjmp() und
longjump()
lössen.

Gruss,

MarkusS

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.