Hallo,
Habe da ein kleines Problem:
Im Anhang befindet sich ein Programm das wen es z.B.: "H11" über Rs232
erhält das Led am PORTB,1 einschalten sollte. Nun aber, habe ich den
Mega angeschlossen und ihm H11 übertragen, er hat auch das LED
eingeschalen aber wenn ich danach z.B. das zweite Led am Portb, 2
einschalten oder das erste led auschalten möchte macht er nichts mehr.
Erst wenn ich ihn resete dann kann ich das LED wieder einschalten. Ein
weiteres Problem ich kann auch nach einem Reset das zweite led nicht
ansteuern! Kann mir bitte jemand helfen, wäre sehr dankbar!
Danke, mfG Zsolt
Ach ja, ich habe auch versucht am schluss jeder funktion wo jetzt "reti"
steht "ret" oder "rjmp Main" hinzuschreiben hat aber leider auch nichts
gebracht!
Wie findet man Fehler in irgendwelchem Code ?
Einen freien Pin als Ausgang definieren und auf den Pin einen Puls
ausgeben. Dadurch kann man mit dem Scope mitverfolgen welche Code
ausgefuehrt wurde und welcher nicht.
Dann löscht du einen Pin und
fügst gleich danach eine endlosschleife ein.
nach der endlos setzt du ihn wieder.
Jetzt hängt das programm an der stelle und gibt dir per
signal 0 an daß es hier angekommen ist
alles klaro?
Gruß
Andi
wenn man hat.
also ich kenn den controller net,aber wenn man aus einer
Interruptroutine(int_rxc) heraus zu einer anderen springt (kein call),
dann MUSS diese angesprungene mit reti beendet werden !!
(es sei denn man springt wieder zuück in die int_rxc,aber sowas ist echt
Murx!!)
reti ist wie ein call nur für Interrupts.
Das heißt es wird eine Adresse auf dem Stack gespeichert,die
bei reti wieder zurückgeholt wird. Nur so kann das Programm
da weitermachen wo es unterbrochen wurde.
Hier sind einige male ret und reti verwechselt.
Dies produziert Stackfehler,da nützt auch kein scope!
gute Nacht
Gruß
ANdreas
Wobei man auch sagen muss, dass der ganze Programmaufbau, so
wie er jetzt ist, ziemlicher Murx ist.
Da wird hemmunglos in der Interrupt Routine eine Warteschleife
eingefügt, wenn nicht das richtige Zeichen daherkommt.
Da wird in der Interrupt Routine enie unnötige Auswertung gefahren,
die auch noch darin mündet, dass zeichen zurückgeschickt werden,
was wiederrum zu Wartezeiten im Interrupt führt etc.
Interrupt Funktionen sollen kurz sein!
Ein Aufbau der sich gut bewährt, ist zb Folgender:
Die Interrupt Funktion, die je automatisch nach dem Empfang
eines Zeichens aufgerufen wird, hat nur eine Aufgabe:
Sie nimmt das Zeichen entgegen, entscheidet ob durch dieses
Zeichen eine komplette Befehlssequenz empfangen wurde.
* Ist dieses Zeichen die Endekennung für die Sequenz, dann
setzt sie eine Flagge
* Ist dieses Zeichen nicht die Endekennung, dann speichert sie
das Zeichen im SRAM.
Die eigentliche Auswertung erfolgt dann im Hauptprogramm in
einer Schleife. In der Schleife wird ständig die Flagge
kontrolliert. Ist diese gesetzt, dann bedeutet dies, dass
im SRAM eine komplette Kommandosequenz vorliegt und in der
Hauptschleife wird diese dann ausgewertet.
Die Aufgabe der Interrupt Funktion ist es also, aus dem
empfangenen Zeichenstrom einzelne komplette Kommandosequenzrn
herauszufischen und im SRAM zu speichern.
Die Aufgabe der Hauptschliefe ist es eine komplette Kommandosequenz
zu bearbeiten.
> Dies produziert Stackfehler,da nützt auch kein scope!
Das stimmt nicht. Der einzige Unterschied zwischen ret und reti ist,
dass bei einem reti das I-Bit im Statusregister gesetzt wird, um die
Interrupts wieder freizugeben. Dem Stack ist das egal, welcher
Return-Befehl die abgelegte Rücksprungadresse wieder "abholt". Nur
werden nach der Beendigung eines Interrupt-Handlers mit ret anstatt mit
reti die Interrupts nicht wieder freigegeben und demzufolge ist der
erste Interrupt auch gleichzeitig der letzte...
...Ergänzung: Stackprobleme kriegt der OP allerdings trotzdem, da im
Code Sprung- und Verzweigungsbefehle (z.B. breq) mit einem ret
abgeschlossen werden. Da weder Sprung- noch Verzweigungsbefehle eine
Rücksprungadresse auf dem Stack ablegen, knallt es beim ret, wenn eine
Adresse vom Stack geholt wird, die dort gar nicht abgelegt wurde (bzw.
die von jemand anderem dort abgelegt wurde...). Ein Unterprogramm wird
mit (r)call aufgerufen, und NUR bei (r)call darf ein ret verwendet
werden, um an die aufrufende Stelle zurückzukehren! Bei (r)jmp und
br<xy> hat ein ret nichts verloren.
jonny,
das mit dem ret und reti stimmt natürlich!!
nur sollte man per hand des I-Flag rücksetzen und dann per ret
verlassen,
wo es doch reti gibt?
sorry,ich kenne nur 8051
wußte nicht was breq macht.
zur Ergänzung:
ISR:
...
...
...
bedingter sprung in eine außerhalb liegende routine
...
...
...
reti
außerhalb liegende routine
..
...
...
...
RETI (!!!)
ist genauso ok. beidesmal wird die ursprunsadresse zurückgeholt!
da ein sprung keine adressenspeichert.
Gruß
Andi
@Andreas:
Ist ein bisschen schwer nachvollziehbar, was der OP sich genau dabei
gedacht hat. Ich war davon ausgegangen, dass er mit dem ret wieder
zurück an die Stelle hinter dem breq springen wollte. Wenn das nicht der
Fall ist, dann trifft Dein Vorschlag zu, indem er einfach das ret durch
ein reti ersetzt.