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