Archiv verlassen und diese Seite im Standarddesign anzeigen : Programmsprung
hallo,
folgendes problem:
1) mein µC führt ein Programm aus
2) ein Interrupt wird ausgelöst
3) der interrupt soll ein bestimmtes programm abarbeiten
4) nachdem die interruptrutine abgearbeitet wurde, soll der normale programmzyklus wieder aufgenommen werden, aber an einer bestimmten anderen stelle (nicht an der das programm durch den interrupt unterbrochen wurde)
wie löse ich 4) möglichst schön? ich könnte vor dem reti die rücksprungadresse auf dem stack manuell maipulierenu aber irgendwie gefällt mir das nicht (ich müßte ja eine feste adresse auf den stack legen, und bei programmänderungen jedesmal die rücksprungadresse anpassen)
linux_80
03.12.2005, 15:33
Hallo,
ich glaube nicht, das das eine so gute Idee ist,
was ist, wenn zB. während dem Versenden über UART(oder an LCD) ein IRQ auftritt, und danach woanders weitergemacht werden soll, was wäre dann mit den restlichen Zeichen ?
Üblicher wäre es, in der IRQ-Routine ein Flag zu setzen, das dann vom Hauptprogramm ausgewertet wird, und bei nächster Gelegenheit verzweigt wird, ist auch viel einfacher, besonders wenn man mal nach einem Fehler forschen muss.
Na ja, du wirst doch von der Zieladresse eine Label, also irgendwas symbolisches haben, das sich beim Compilieren nach Änderungen eh' automatisch anpaßt.
Wie möchtest du aber letztlich wieder zur tatsächlichen Position beim Interrrupt zurückkommen ?
(Ich hab noch nicht ganz mitgekriegt, was du im Endeffekt erreichen möchtest).
Kann es sein, daß du eigentlich nur einen Teil der "interrupt" Verarbeitung im normalen Modus machen willst, irgendwann aber dann doch wieder ganz zurück möchtest ?
(Wahrscheinlich schlecht ausgedrückt)
EDIT: Oder überlegst du dir eine Art Task-switching, also so wie Multi-threads ?
also, ich hab einen roboter der unterprogramme ausführen kann. befindet er sich nun in einem unterprgramm, und es wird der hauptschalter betätigt, dann so er das unterprogramm beenden, und der roboter anhalten. drückte ich nochmal den hauptschalter, dann soll er wieder losfahren.
eine warte schleife inerhalb des interrupts ist nicht möglich, da er auch via UART befehle empfangen kann. allerding ist es zeimlich egal, wenn mal ein paar bits fehlen, ich habe ein äußerst fehlerresitentes datenübermittlungsprtokol entwickelt.
Naja, ich kann mir kaum vorstellen daß es auf ein paar µs Verzögerung zwischen dem Betätigen des Schalters und dem Anhalten des Roboters ankommt
also falls du mit einer minimalen Verzögerung leben kannst mach es so wie von linux_80 vorgeschlagen.
Du musst doch nur irgendein Bit in irgendeiner globalen Variable in deiner Interruptroutine setzen.
In der Hauptschleife überprüfst du dann dieses Bit, und falls es gesetzt ist hälst du den Roboter an
(denn dann weisst du ja, daß seit dem letzten Durchlaufen der Schleife ein Interrupt aufgetreten ist)
ich hab aber mehrere unterprogramme und ich will nicht in jedem unterprogramm eine abfragen reinmachen...könnte man nicht einfach die rücksprungadresse auf dem stack manipulieren
man kann schon...
aber normalerweise sollte man solche Eingriffe vermeiden,
da man sich da ein paar sehr unschöne Effekte einhandeln kann.
Wenn deine Unterprogramme den Stack auch in irgendeiner Form nutzen, wird er dir mit Sicherheit irgendwann überlaufen.
(denn wenn du ein Unterprogramm derart tötest wird der Stack ja nicht korrekt abgebaut)
Normalerweise macht man solche Sachen nur, wenn man ein preemptive Multitasking implementieren will
Bei "Exceptionhandlern" ist das Verfahren so, daß zuvor ein Punkt am Stack definiert wird, der bei "STACKUNWIND" (wird dann bei der Exception selbst aufgerufen, z.B. division durch null) einen korrekten Aufsetzpunkt darstellt. d.h. die "nicht korrekt abgebauten" Bereiche liegen drunter.
Für den normalen Betrieb (reaktion auf Taste drücken) ist das aber eigentlich "pfui gack".
ich hab mal ein sehr schlechtes prog geschrieben, dass so funktioniert wie ich es möchte, aber es ist doch sehr schlecht programmiert. vllt. kann mir jemand helfen es zu verbessern:
INCLUDE 89s8252.mc
JMP Anfang
org 0003h
call spring
RETI
org 00C8h
Anfang:
SETB EA
SETB it0
SETB ex0
eins:
NOP
JMP eins
zwei:
NOP
JMP zwei
spring:
DEC sp
DEC sp
DEC sp
DEC sp
MOV DPTR,#zwei
MOV A,82h
PUSH A
MOV A,83h
PUSH A
INC sp
INC sp
RET
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.