PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Stack beim verlassen einer Schleife...



Klingon77
26.04.2009, 00:59
hi,

für mein kleines LED-Projekt:

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=46478&highlight=

muß ich "wild" im Programm umherspringen....

Geplant ist eine Menüführung mit Untermenü´s.
Die Steuerung soll über drei Tasten "UP"; "DOWN"; ENTER geschehen.

Der Pin "PordD.2" wird über Interrupt als Entertaste aus unterschiedlichen Programmteilen abgefragt.




...
Config Timer2 = Pwm , Compare B Pwm = Clear Down , Prescale = 64
...
Enable Timer2 'Timer2 starten
On Timer1 Enter:
Enable Interrupts
...




Enter: 'Entertaste abfragen
Debounce Pind.2 , 0 , Eingabe , Sub
If Enter = 1 And Wechsel = 1 Then
Enter = 0
Wechsel = 0
Goto Untermenu
End If
Return

...

Sub Eingabe
Up = 0 : Down = 0 : Enter = 1
End Sub


Untermenu:
...
...
...
...



Wird die Enter-Taste nicht betätigt verlässt das Programm die Subroutine normal mit Return.
bei jeder Betätigung der Entertaste bleibt mir eine Sprungadresse im Stack liegen.


Wie kann ich das vermeiden? Steh da ein wenig auf dem Schlauch... ](*,)


liebe Grüße,

Klingon77

PICture
26.04.2009, 01:45
Hallo Klingon77!

Ich programmiere zwar in ASM, glaube aber, dass das Ablegen der Rücksprungadressen unabhängig von einer Hochsprache ist. Die Adresse wird bei jedem "call" abgelegt und bei "goto" nicht. Deswegen würde ich "Enter" mit "goto Enter" einspringen und anstatt mit "return", mit "goto ..." verlassen, wobei "..." die Marke direkt nach dem "call Enter" ist. Du musst es ausprobieren, weil ich mir nur erinnern kann, dass ich mal QBASIC noch unter DOS benutzt habe ... :)

MfG

Klingon77
26.04.2009, 02:08
hi,

mal Dank für den Tipp.

leider springt BASCOM nicht in "ENTER" wenn ich schreibe:

On Timer1 GOTO Enter:

Habe es eben getestet. Syntax wird genommen aber es wird nicht verzweigt. Wäre auch zu schön gewesen.


liebe Grüße,

Klingon77

PICture
26.04.2009, 02:23
Ja aber das "GOTO" ist mit einer Bedingung von Timer1 verbunden, die anscheinend nicht erfüllt ist. Ich habe ganz einfaches "goto" gemeint. Ich würde eben eine leere endlose Schleife ausprobieren ob der stack überfüllt wird. Vielleicht musst du in deinem konkretem Programm mehr ändern ... :)

Klingon77
26.04.2009, 02:31
hi,

GOTO kann auch nicht gehen.

Der Timer zählt immer runter oder hoch.
Bei jedem überlauf springt er zu "ENTER".
Danach muß er ja wissen wohin er zurückspringen muß falls ENTER nicht gedrückt wurde.


Eine andere Möglichkeit wäre eine "SUB":

On TIMER1 ENTER , SUB


Die Sub könnte ich mit:

If ENTER = 1 THEN End Sub 'Entertaste gedrückt

verlassen.
Dann die IF THEN zu den einzelenen Menu´s.

Geht aber auch nicht; habe ich schon getestet.


liebe Grüße,

Klingon77

PICture
26.04.2009, 02:38
Vielleicht kanns du ihm das mit "GOTO" anstatt "RETURN" sagen, wenn er immer auf die gleiche Adresse zurückspringen soll. Wenn er von verschiedenen Aufrufer mit "CALL" bzw. "SUB" aufgerufen wird, geht es leider nicht... :(

In ASM könnte ich es noch mit Flags erkennen wovon er aufgerufen wurde, aber BASCOM kenne ich überhaupt nicht.

In BASIC hätte ich ein Byte dafür verwendet indem jedes Bit einen anderen Aufrufer bedeuten würde...

MfG

Klingon77
26.04.2009, 04:45
hi,

mal Dank für Deine Hilfe \:D/

nun ist mir noch eine andere Lösung eingefallen.

Das Problem war folgendes:

* Die Farben (RGB) steuere ich mit PWM in einer Schleife z.B: von 0 - 255 (dunkel bis max. hell).
* um nun auch einen sehr langsamen Farbverlauf zu realisieren habe ich ein "WAITms" (Pause Millisekunden) in die Schleife eingefügt.
* Die ENTER-Taste wird zwar per Interrupt sofort ausgewertet, wenn sie gedrückt wird aber...
* ...durch den WAIT-Befehl dauerte es mitunter mehrere Sekunden, bis die Verzweigung in das Untermenu erfolgte.

* Nun habe ich eine zusätzliche Schleife (FOR-NEXT) in die Farbregelschleife eingefügt.
* Sie zählt entsprechend dem eingegebenen Pausenwert hoch. Der eigentliche "WAITms" - Befehl entfällt.
* In dieser zweiten Schleife wird die Auswertung der ENTER-Taste (sofern gedrückt) ausgeführt.
* Das Programm verlässt die Schleife mit "EXIT FOR" und springt sofort sofort in das Unteremu.

So kann ich von jedem Punkt aus zu jeder Zeit mit GOTO beliebig verzweigen.


\:D/ \:D/ \:D/


Funktioniert Prima O:)

Auch wenn mich nun alle Informatiker "hauen", weil ich mit GOTO arbeite...
...es ist mir noch nichts besseres eingefallen.


liebe Grüße und nochmals Dank für die späte Hilfestellung,

Klingon77

PICture
26.04.2009, 05:22
Es ist schön zu hören, dass meine kleine Hilfe dich aus dem Schlauch bewegt hat. Ich konnte dir zwar nicht konkret helfen, war aber sicher, dass du es selber schaffst... :)

Übrigens ich bin, wie du, kein Informatiker und nur deswegen sind für mich einfache Lösungen, an die die Profis nicht kommen, weil sie manchmal nicht schön sind, am liebsten ... :)

Viel Erfolg weiterhin!

MfG

Klingon77
26.04.2009, 11:10
hi,

die Frage der Lösung ist meistens nicht ob man sie findet, sondern wann man sie findet.

AVR´s sind vollkommen neu für mich; mein erstes Programm.

Meine BASIC-Kenntnisse sind bestenfalls rudimenatär.



Anbei mal der betreffende CODE-Schnipsel.






Do

For Lauf1 = 1 To Pause01 'Pause01 = Pausenwert für die Geschwindigkeit
If Enter = 1 Then
Exit For
End If
Waitms 1 ' damit es nicht soooo schnell rennt...
Next Lauf1

If Enter = 1 Then
Enter = 0
Goto Untermenu
End If

...
...
...
Loop





liebe Grüße,

Klingon77

Besserwessi
26.04.2009, 11:10
Ich bin zwar auch kein Experte für Bascom, aber soweit ich mich noch erinnere wird in BSCOM mit
ON Timer1 funktion

kein normaler code erzeugt, sondern es wird der Interrupt-vector definiert. Das Problem ist als mehr die Programmierung mt Interrupts.

Da hat man nämlich wirklich ein Problem und man sollte nicht irgendwie aus der Interruptroutine in den normalen Programmfluß springen. Da hat man einmal das Problem mit dem Stack und zum anderen kann man da Hauptprogramm mtten in einer Zuweisung unterbrochen haben. Damit könnte z.B. ein Variable nur halb überschreiben sein. Das einzige was mir da als sinnvoller Fall einfällt wäre ein totaler neustart des Programm, ggf. mit parameterns die nur in einer ISR geändert werden.

Klingon77
26.04.2009, 11:17
hi Besserwessi,

meine Interrupt Routine sieht so aus:

--------------------------------------------------------------------------
Enter: 'Entertaste abfragen
Debounce Pind.2 , 0 , Eingabe , Sub
Return
--------------------------------------------------------------------------


Die SUB "Eingabe" hat folgenden Code:

--------------------------------------------------------------------------

Sub Eingabe
Up = 0 : Down = 0 : Enter = 1
End Sub

--------------------------------------------------------------------------

Es wird lediglich eine Taste abgefragt und ein Wert zugewiesen (ENTER = 1).

Dann geht es zurück in´s Hauptprogramm und erst dort erfolgt die Auswertung (Post direkt über Deinem).

So sollte es funktionieren; der Stack bleibt immer "UP to DATE" und es dürften keine Fehler erzeugt werden.


liebe Grüße,

Klingon77