Hallo zusammen ! ich hätte eine ganz einfache Frage, die mir seit ein paar Tagen den Kopf zerbricht. Mein Frage lautet ist es mit dem Atmel AT89C51ED2 möglich zwischen zwei Interrupts Prioritäten während einer Interrupt Service Routine zu wechseln ? unten habe ich ein Lauflicht programmiert der durch den externen Interrupt(lsbzumsb auf Port 2) 0 oder Interrupt1(msbzulsb auf Port 2) ausgelöst werden kann die höhere Priorität ist auf den externen Interrupt 1 gesetzt. wenn mann P3.2 drückt fängt das Lauflicht vom lsb zu msb sich zu bewegen da der P3.3 die höhere Priorität hat wird die ISR2 ausgelöst wenn man P3.3 drückt und das Lauflicht fängt dann an sich vom msb zu lsb zu bewegen jedoch kann ich jetzt nicht den Interrupt0 P3.2 (lsbzumsb) auslösen weil der Interrupt 1 die höhere Priorität hat. Was kann ich bzw. muss ich machen damit die sich höhere Prioritäten im ISR sich switchen : einmal die Priorität 3 für EX0 und einmal für EX1 ! mov IPL0,#00000100b Priorität 3 für EX1 mov IPH0,#00000100b Priorität 3 für EX1 include C51ED2.inc code at 0 sjmp init isr1: org 003h push acc push psw call lsbzumsb pop acc pop psw reti isr2: org 0013h push acc push psw call msbzulsb pop acc pop psw reti lsbzumsb: mov r3,#150 sprung3: mov p2,a call zeit RL a djnz r3,sprung3 ret msbzulsb: mov r4,#150 sprung4: mov p2,a call zeit RR a djnz r4,sprung4 reti init: mov IPL0,#00000100b mov IPH0,#00000100b mov a,#1 setb IT0 setb IT1 clr IE0 clr IE1 setb EX0 setb EX1 setb EA zeit: mov r1,#200 sprung2: mov r2,#200 sprung1: djnz r2,sprung1 djnz r1,sprung2 ret haupt : sjmp haupt end.
Ja man kann die Priorität jederzeit ändern. Der 8051 hat eine äußerst clevere und einfache Methode, die Prioritäten zu verwalten. Für die 4 Prioritäten sind nur 4 Bits nötig. Die Priorität wird beim Interrupteintritt ausgewertet und setzt das entsprechende Bit. Jedes RETI löscht dann wieder genau ein Bit, das höherwertige zuerst. Wenn man nun in einem Interrupt seine eigene Priorität erhöht, muß das unmittelbar vor dem RETI geschehen, sonst kann es passieren, daß man sich selbst unterbricht (2 Instanzen des Handlers). So und nun die schlechte Nachricht, das wird Dir bei Deinem Problem nicht das geringste helfen. Interrupts sind dazu da, daß man nur kurz darin verweilt und sein Ding macht. Du willst aber für immer drin bleiben und das geht nicht. Du mußt also Deinen Programmablauf nochmal neu überdenken. Interrupts sind auch generell keine gute Methode, Tasten abzufragen, da Tasten prellen. Peter
hallo erstmal vielen dank für die schnelle Antwort ! die Verwaltung von Prioritäten werden bei mir über mov IPL0,#00000100b mov IPH0,#00000100b gesetzt, die Entprellung kann ja über eine Zeitverzögerung kompensiert werden. Wenn Sie mir vielleicht ein Programmbeispiel zeigen könnten wäre ich Ihnen sehr verbunden. Mit freundlichen Grüßen Ertan
Hallo Ertan, setze in den Interrupts doch einfach nur bits sozusagen als Flags, z.B.: isr1: org 003h setb ($2F).0 clr ($2F).1 reti isr2: org 0013h clr ($2F).0 setb ($2F).1 reti Im Initialisierungsteil löschst du die beiden Flags: init: ... clr ($2F).0 clr ($2F).1 Den eigentlichen Aufruf von lsbzumsb und msbzulsb erfolgt dann im Hauptprogramm anhand der Flags: haupt : jnb ($2F).0,keinlsbzumsb call lsbzumsb keinlsbzumsb: jnb ($2F).1,keinmsbzulsb call msbzulsb keinmsbzulsb: sjmp haupt Wenn Du sofort umschalten können willst, mußt Du die Schleifen noch abbrechen können: lsbzumsb: clr ($2F).0 mov r3,#150 sprung3: mov p2,a call zeit RL a jb ($2F).1,Endelsbzumsb djnz r3,sprung3 Endelsbzumsb: ret msbzulsb: clr ($2F).1 mov r4,#150 sprung4: mov p2,a call zeit RR a jb ($2F).0,Endemsbzulsb djnz r4,sprung4 Endemsbzulsb: reti Wenn ($2F).0 gesetzt ist (durch isr1), dann wird lsbzumsb aufgerufen. Wenn ($2F).1 gesetzt ist (durch isr2), dann wird msbzulsb aufgerufen. Hab's nicht ausprobiert, aber ich hoffe, es funktioniert... Viel Glück, Bruno
Hallo erstmal vielen dank für eure schnelle Antwort . die Idee ist super jedoch kann ich mit den Flags nichts anfangen da der Compiler diese Syntax nicht erkennt setb ($2F).0 ! ? bitte um Hilfe ! MfG Ertan
Welcher Compiler? Das ist doch Assembler. Welchen benutzt Du denn? Im RAM ist der Bereich 20h bis 2Fh bitadressierbar. (Siehe Datenblatt bzw. 8051 Hardwarebook) Will man ein Bit davon nutzen, schreibt man das entspr. Bit hinter die Adresse der Speicherzelle z.B. 2F.0h 1.Bit (niederwertigstes) der Speicherzelle 2Fh im RAM 2F.1h 2. Bit " usw. Wie die Syntax genau bei deinem Assembler aussieht musst Du im Manual nachsehen. Probier mal: clr 2F.0h bzw. setb 2F.0h
Hallo :-)) ich benutze den RIDE51 RAISONANCE Kit ! setb 2F.0h bzw. 2F.0h akzeptiert der Compiler nicht aber setb 2Fh compiliert er ohne Probleme ? MfG Ertan
Hallo Ertan, leider kenne ich Deinen Compiler nicht, in meinem ist die Syntax wie ich oben beschrieben habe, z.B. ($2F).1 Wenn das bei Dir nicht funktioniert, dann nimm anstelle eines Bits ein ganzes Byte als Flag, z.B. nimmst Du 30h anstelle von ($2F).0 und 31h anstelle von ($2F).1 und weist denen entweder 0 oder 1 zu. Dann werden nur die Sprünge etwas umständlicher, aber Du könntest den jew. Wert in den Akku kopieren und dann jz bzw. jnz benutzen. Also anstelle von clr ($2F).0 bzw. setb ($2F).0 schreibst Du mov 30h,#0 bzw. mov 30h,#1 und anstelle von jb ($2F).0,Endelsbzumsb schreibst Du dann mov A,30h jnz Endelsbzumsb bzw. aus jnb ($2F).0,keinmsbzulsb wird dementsprechend mov A,30h jz keinmsbzulsb Dann mußt Du aber ggf. den Akku retten, wenn Du ihn irgendwo sonst in Deinem Programm ebenfalls benutzt (Push ACC und Pop ACC). Apropos push und pop, mit fällt da gerade noch etwas auf: In Deinen Interrupt Serviceroutinen rettest Du den Akku und das PSW, aber Du mußt darauf achten, sie in umgekehrter Reihenfolge vom Stack zurückzuholen, wie Du sie hinaufschiebst. Du hast push acc push psw call lsbzumsb pop acc pop psw geschrieben, es müßte aber push acc push psw call lsbzumsb pop psw pop acc sein. Das ist sehr wichtig, denn ansonsten findet sich der Inhalt des Akkus anschließend im PSW wieder und umgekehrt. Allerings brauchst Du Akku und Prozessorstatuswort nur dan zu retten, wenn Du es auch veränderst, ansonsten kannst Du die Befehle weglassen. Viel Spaß mit Deinem Projekt, Bruno
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.