Hallo ich hab da mal ein ganz interessantes Problem und zwar nach dem ich ein program geschrieben habe das nicht funktioniert hat habe ich ein test Programm geschrieben das folgendes venomehn hat. Hier erst mal der Code: .include "4433.inc" .def temp1 = r16 .def temp2 = r17 .org 0x000 rjmp main .org INT0addr rjmp inttest main: ldi temp1, RAMEND out SPL, temp1 ldi temp1, $F0 out DDRD, temp1 ldi temp1, $0F out DDRB, temp1 ldi temp1, 0b00000010 out MCUCR, temp1 ldi temp1, 0b01000000 out GIMSK, temp1 sei ldi temp1,$00 ldi temp2,$00 out PORTB,temp2 out PORTD,temp1 loop: in temp1, PIND andi temp1, $01 cpi temp1, $00 breq weiter rjmp loop weiter: ldi temp1,$a0 ldi temp2,$0a out PORTB,temp2 out PORTD,temp1 rjmp loop inttest: ldi temp1,$F0 ldi temp2,$01 out PORTB,temp2 out PORTD,temp1 reti Die Pins 2 u. 4 sind als Eingänge wie im I/O Tutorial aufgebaut (also bei Betätigung auf masse). Wenn jetzt der Taster S1 der an pin2 angeschlossen ist betätigt wird dann wird in portB $0A und in portD $A0 geladen so weit so gut aber wenn ich S2 der mit pin4 verbunden ist und somit den interupt auslöst betätige dann wird aus mir unerklerlichen gründen in portB $0A und in portD $A0 oder eben in portB wird $01 und in portD $F0 geladen. Eigentlich sollte ja nur in portB $01 und in porD $F0 geladen werden. Woran kann das liegen das der falsche wert geladen wird hat irgend jemand eine Ahnung ? PS: noch ne kleine frage wenn ich in der loop schleife statt rjmp nur jmp verwende was laut datenblat ein Sprung zur absoluten Adresse ist was für mich bedeutet das ich nicht mehr zurück springen kann und das ist in diesem fall ja auch nicht nötig nur dann funktioniert das Programm auch nicht nur mit rjmp aber rjmp speichert eine Adresse auf dem stack und dann müsste doch eigentlich bei einer endlos schleife der stack über laufen oder nicht bitte klärt mich mal darüber auf DANKE im voraus Klaus PPS: Ich drücke nie beide Taster gleichzeitig
Hi! Du benutzt in der INT0-Routine die gleichen Register wie im Main-Prog. (Temp1 (r16) und Temp2 (r17)). Dadurch verändert die INT0-Routine den Registerinhalt von r16 und r17 des Main-Progs. Desweiteren soltest Du im INT0 das Statusregister sichern und vor RETI wieder rücksichern damit die Operationen im Main-Prog nicht verfälscht werden. Am einfachsten machst Du das mit .def StReg=r0 in StReg,SREG ;Statusregister sichern .... Code .... out SREG,StReg ;Statusregister zurückschreiben reti Natürlich ist darauf zu achten, das StReg (r0) für nichts anderes benutzt wird. In der INT0-Routine solltest Du entweder Register verwenden, die überall woanders nicht verwendet werden oder Du setzt vorher den Inhalt von Temp1 und Temp2 auf den Stapel mit .def StReg=r0 in StReg,SREG push Temp1 ;Temp1 (r16) auf den Stapel setzen push Temp2 ;Temp2 (r17) auf den Stapel setzen .... Code .... pop Temp2 ;Temp2 (r17) vom Stapel holen pop Temp1 ;Temp1 (r16) vom Stapel holen out SREG,StReg reti Noch ein Vorschlag zwecks logik! Wenn Du in Deiner loop nicht auf = (breq) sondern <> (brne) prüfst, kannst Dir den rjmp sparen und das Ergebnis ist das gleiche das bei Übereinstimmung die Schleife verlassen wird: loop: in temp1, PIND andi temp1, $01 cpi temp1, $00 brne loop Eine kürzere Variante gibs noch mit SBIC (Skip if Bit in I/O is clear): loop: sbic pind,0 ;Ist Pin0 an PortD gelöscht (GND)? rjmp loop ;Wenn nicht, dann zurück zu loop weiter: ;Ansonsten gehts hier weiter (Marke nicht erforderlich) Gruß Andi
Hi und danke Andi Wie schon gesagt ist das nur ein Test Programm und daher war ich mit der Sicherung der Register etwas schlampig nur glaub ich das du mich falsch verstanden hast ich bekomme nicht im Hauptprogramm die falschen Werte sondern in der INT0 Routine also wenn der INT0 ausgelöst wird schreibt er die Daten des Haubtprogramms in die Register. Hast du auch eine Antwort auf die rjmo u. jmp Frage? Aber die Programmabkürzungs Tips sind gute Tips Danke Klaus
Ich habe keine Ahnung, was das für ein µC ist, den Du da programmierst. Aber von dem was ich so programmiere würde ich sagen, daß sowohl JMP als auch RJMP nichts auf dem Stack ablegen. Der Unterschied ist, wie Du schon sagtest: JMP springt eine direkte Adresse an, bei RJMP wird die Sprungadresse relativ zum aktuellen Programmzähler codiert gespeichert. Dadurch verbraucht ein RJMP Befehl weniger Speicher, kann dafür keine so großen Sprünge machen. (Im wahrsten Sinne des Wortes). Als Programmierer merkt man da eigentlich wenig von. Ich würde mir angewöhnen RJMP zu benutzen. Wenn die Adresse außerhalb des zu erreichenden Bereiches liegt, sollte der Assembler einen Fehler anzeigen. K.A. wie bei Deinem µC dann der Befehl aussieht, der eine Rücksprungadresse auf den Stack legt. Beim 8051 wäre das CALL, bei 6502 JSR. Hoffe das trifft in etwa auf Deinen µC zu, Markus_8051
@Klaus: Dann sei mal nicht so schlampig und mach das mal mit dem sichern des Statusregisters und der Register Temp1 und Temp2 bzw. benutze erst mal andere (reservierte) Register in der INT0-Routine z. B. r18 und r19. Denn nur wenn man in der Software für korekte Programierung sorgt steigen die Chancen der korekten Funktion erheblich. Vielleicht klapps ja dann mit der Funktion die es machen soll. Wie mein Vorredner schon sagte, RJMP ist ein Sprungbefehl und kein Call-Befehl (Unterprogrammaufruf). Mit RJMP spart man sich gegenüber JMP 1 Word da die relative Sprungadresse im RJMP-Befehl mit 12 Bit enthalten ist. Man kann relativ vom aktuellen PC von -2047 bis +2047 springen. Gruß Andi
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.