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.