PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : HILFE: Ledlauflicht Stacküberlauf verhindern



Matthiasbaue
26.10.2006, 16:13
Hallo,
ich habe folgendes Problem, ich habe eine Programm für zwei Led Lauflichter geschrieben aber leider bekomme ich nach kurzer Zeit einen Stacküberlauf.
Ich finde keine Lösung um das zu verhindern, kann mir gemand helfen??

Hier ist das Programm, ich habe es für einen AT89S8252 geschrieben und verwende es auf einen AT89S8253.


$large
Dim A As Byte
Dim C As Byte
Dim D As Byte
Dim L1 As Byte
Dim R1 As Byte
Dim R2 As Byte
Dim L2 As Byte
Dim Merker1 As Byte
Dim Merker2 As Byte


P0 = &HFF
P1 = &HFF
P2 = &HFF
P3 = &HFF ' Enstellung Links Laufband 2 =1
A = 1
D = 1
Merker1 = 0
Merker2 = 0



Main:
Do
Zulauflicht1:
If P0.0 = 0 And Merker1 = 0 Then
Set L1
Print L1
Gosub Zu_lauflicht1
Else
If L1 = 1 Then
Gosub Zu_lauflicht1
Else
Auflauflicht1:
If P0.0 = 0 And Merker1 = 1 Then
Set R1
Print R1
Gosub Auf_lauflicht1
Else
If R1 = 1 Then
Gosub Auf_lauflicht1
Else
If L2 = 1 Then
Gosub Zu_lauflicht2
End If
End If
End If
End If
End If

Zulauflicht2:

If P0.3 = 0 And Merker2 = 0 Then
Set L2
Print L2
Gosub Zu_lauflicht2
Else
If L2 = 1 Then
Gosub Zu_lauflicht2
Else
Auflauflicht2:
If P0.3 = 0 And Merker2 = 1 Then
Set R2
Print R2
Gosub Auf_lauflicht2
Else
If R2 = 1 Then
Gosub Auf_lauflicht2
Else
If L1 = 1 Then
Gosub Zu_lauflicht1
End If
End If
End If
End If
End If
Loop

Zu_lauflicht1:
If L1 = 0 Then
Goto Main
Else
If A = 1 Then
P0.6 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 2 Then
P0.7 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 3 Then
P1.0 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 4 Then
P1.1 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 5 Then
P1.2 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 6 Then
P1.3 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 7 Then
P1.4 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 8 Then
P1.5 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 9 Then
P1.6 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 10 Then
P1.7 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 11 Then
P2.0 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 12 Then
P2.1. = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else
If A = 13 Then
P2.2 = 0
Waitms 0.2
A = A + 1
Goto Zulauflicht2
Else

L1 = 0
Merker1 = 1

Goto Main
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
Return
End


Zu_lauflicht2:
If L2 = 0 Then
Goto Main
Else
If D = 1 Then
P2.3 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 2 Then
P2.4 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 3 Then
P2.5 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 4 Then
P2.6 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 5 Then
P2.7 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 6 Then
P3.0 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 7 Then
P3.1 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 8 Then
P3.2 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 9 Then
P3.3 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 10 Then
P3.4 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 11 Then
P3.5 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 12 Then
P3.6 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else
If D = 13 Then
P3.7 = 0
Waitms 0.2
D = D + 1
Goto Zulauflicht1
Else

L2 = 0
Merker2 = 1

Goto Main
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
Return
End

Auf_lauflicht1:
If R1 = 0 Then
Goto Main
Else
If A = 14 Then
P2.2 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 13 Then
P2.1 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 12 Then
P2.0 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 11 Then
P1.7 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 10 Then
P1.6 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 9 Then
P1.5 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 8 Then
P1.4 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 7 Then
P1.3 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 6 Then
P1.2 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 5 Then
P1.1 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 4 Then
P1.0 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 3 Then
P0.7 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
If A = 2 Then
P0.6 = 1
Waitms 0.2
A = A - 1
Goto Zulauflicht2
Else
R1 = 0

Merker1 = 0
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
Return
End

Auf_lauflicht2:
If R2 = 0 Then
Goto Main
Else
If D = 14 Then
P3.7 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 13 Then
P3.6 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 12 Then
P3.5 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 11 Then
P3.4 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 10 Then
P3.3 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 9 Then
P3.2 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 8 Then
P3.1 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 7 Then
P3.0 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 6 Then
P2.7 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 5 Then
P2.6 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 4 Then
P2.5 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 3 Then
P2.4 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
If D = 2 Then
P2.3 = 1
Waitms 0.2
D = D - 1
Goto Zulauflicht1
Else
R2 = 0

Merker2 = 0
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
Return
End


EDIT: das heisst "CODE" und nicht "QUOTE" :-) Picnick

MFG Matthias

robocat
26.10.2006, 16:29
ganz schön krank dein code.

Zu_lauflicht1:
If L1 = 0 Then
Goto Main
mir ist bascom fremd, aber wenn du mit gosub reingehst, musst du natürlich mit return wieder raus. sonst liegt die rücksprungadresse noch aufm stack und es gibt logischerweise recht schnell einen overflow.

Matthiasbaue
26.10.2006, 17:35
Vielen Dank für die nette Antwort!!!

Ich bin doch jedesmal mit return rausgegangen, oder ? Es ist mein erstes Programm.

MFG
Matthias

robocat
27.10.2006, 10:16
schon gut, war ja nicht bös gemeint ;)
ich muss gestehen, dass ich da nicht durchblicke, was du genau machst.
aber die von mir zitierte stelle wird mit gosub aufgerufen, und springt (if(...)) mit goto zurück nach main. entweder das geschieht niemals, dann ist die stelle überflüssig, oder es geschieht eben doch, und der stack wird zunehmend voller.
kurz gesagt, ich bin fast sicher, dass dein stacküberlauf an "vergessenen" rücksprungadressen liegt, die sich dort ansammeln.

gruesse

Matthiasbaue
29.10.2006, 10:24
Hallo robocat,

kannst du mir Bitte ein kleines Beispiel,an meinem Code geben, wie ich die Rücksprunge nach "Main" umschreiben muß, damit der Stack nicht überläuft?.

MFG
Matthias

Gento
29.10.2006, 10:46
unabgesehen von goto,gosub & Co ich habe den Code nur überflogen.

Vermeige in sich verschaltete if
end if
end if
end if
& noch 20x

Das bringt den zum Überlauf / & Stack erhöhen.

Sieht grausam aus Dein Rattenschwanzcode :-$

Gento

Matthiasbaue
29.10.2006, 21:14
Hallo,
wie ich so lese ist mein Code wohl nicht so gut gelungen, ich kann mein Problem mit dem Stacküberlauf leider nicht lösen.
Ich würde das Prgramm neu schreiben, aber ich weiß leider nicht, wie ich anders (als ich es bis jetzt programmiert habe) 2 etwa simultan laufende LED Lauflichter ansteuern kann.

Zum Programm:
Ich brauche 2 Taster (P0.0 und P0.3)
Je Taster:
1. mal tasten LEDs schalten sich nacheinander an und bleiben an.
2. mal tasten LEDs schalten sich nacheinander aus und bleiben aus.

Es muß sein das die LED Lauflichter gleichzeitig an/aus getastet werden oder zeitversetzt. Mein altes Programm hat diese Anforderungen erfühlt aber leider bekomme ich einen Stack überlauf.

Kann mir jemand Helfen?

MFG
Matthias

BiGF00T
29.10.2006, 21:36
Ich habe auch keine Ahnung von Basic aber an Robocats Aussage is was dran. Geh deinen Code mal Stück für Stück durch und schau dir an, wie oft du an ein Return kommst und wie oft du stattdessen wieder mit goto nach Main springst.
Wenn ich was wie ein Lauflicht wollte, dann würde ich wahrscheinlich eine 1 an den Port schreiben und die dann durchschieben, bis ich die 1 rausgeschoben hab und dann von vorn mit ner 1 anfangen. Wie das mit Basic geht, weiß ich nicht. Auf alle Fälle verstehe ich deinen Code nicht :/ Sorry... Kannst du die Funktion deines Programms nochmal in Worte fassen?
Ein Lauflicht ist für mich einfach, dass eine LED immer an ist und diese dann weiterwandert, um am Ende wieder umzuspringen auf den Anfang...
Deine Beschreibung mit den 2 Tastern kann ich mir nicht vorstellen... Kannst du das nochmal präzisieren?


Ich brauche 2 Taster (P0.0 und P0.3)
Je Taster:
1. mal tasten LEDs schalten sich nacheinander an und bleiben an.
2. mal tasten LEDs schalten sich nacheinander aus und bleiben aus.

Also sobald man Taster 1 drückt, gehen alle LEDs an und bleiben das auch und bei Taster 2 gehen sie der Reihe nach wieder aus? Ist das richtig so?

Gento
29.10.2006, 21:37
Vermeide goto's

Zähle die nur Tastendrücke und Werte aus mit Case.

Gento

BiGF00T
29.10.2006, 21:43
Soll pro Tastendruck eine weitere LED angehen und diese auch wieder durch Drücken des 2. Tasters abgezogen werden können?

Wenn Taster 1 (LED hoch) gedrückt wird, dann kannst du ja einfach machen Portwert * 2 + 1
Multiplikation mit 2 müsste die "1" genau um eine Stelle nach links verschieben und die 1 füllt die neu entstandene Lücke auf.
wenn Taster 2 gedrückt wird, dann einfach Portwert / 2 und schon hat man ne Stelle weniger.
Keine Garantie...
[1=LED leuchtet, 0=LED aus]
00000001 = 1
00000011 = 3
00000111 = 7
00001111 = 15
00011111 = 31
00111111 = 63
01111111 = 127
11111111 = 255
Also wenn du grad 5 LEDs anhast, dann hat dein Port den Wert 31. Dann drückt einer den Taster 2, also durch 2 teilen = 15.5 (da es kein Kommawert gibt, wird die 5 hinterm Komma weggeworfen und das Ergebnis ist 15, was genau den 4 angeschalteten LEDs entspricht.)
Also musst du nur deinen Wert irgendwo in ner Variablen haben und bei Tasterdruck multiplizieren bzw. teilen und ihn dann an deinen Port zuweisen.

EDIT: Das ist zwar nicht die Antwort auf deine Frage, wieso der Stack voll wird und wie man deinen Code verbessern könnte, damit das in Zukunft nicht mehr passiert aber ich versteh den Code absolut nicht (mach dir nix draus... Meine ersten Programme waren auch nie der Hammer und sind sie heute manchmal auch nicht...).

Matthiasbaue
30.10.2006, 15:44
Hallo,
vielen dank für Eure antworten!!!
Ich glaube ich habe das Programm nicht so gut erklärt, ich werde es jetzt nachholen.
Taster 1 und Taster 2 stehen nicht miteinander in Beziehung. Taster 1 ist nur für LED Lauflicht 1. ,Taster 2 ist nur für LED Lauflicht 2.

Taster 1 wird einmal getastet
-die 13 Leds schalten sich mit einer Zeitverzögerung von 0.2s nacheinander an und bleiben auch an.

Taster 1 wird zum zweiten mal getastet
-alle LEDs schalten sich nacheinander mit einer Zeitverzögerung von 0.2s aus und bleiben auch aus.

das selbe Prinzip macht der 2. Taster für das LED Lauflicht 2 auch.

Das große Problem ist, wenn der Taster 1 betätigt wurde, startet das Lauflicht 1 (Beschreibung Taster 1), wenn der Taster 2 betätigt wird und das Lauflicht 1 noch nicht alle 13 LED an oder aus geschaltet hat, soll trotzdem das Lauflicht 2 loslaufen.

MFG
Matthias

BiGF00T
30.10.2006, 16:02
Also hat deine Schaltung 26 LEDs?
OOOOOOOOOOOOO Lauflicht 1
OOOOOOOOOOOOO Lauflicht 2
Ist jede LED einfach an einen Ausgang des µCs angeschlossen?
Soll man den Hoch- / Runterzählvorgang auch durch ein zweites Tasten umkehren können, solange es noch nicht fertig ist?
Soll in den 200 ms, die zwischen den Schritten liegt, auch das andere Lauflicht anfangen können?

Matthiasbaue
30.10.2006, 16:17
Hallo Bigfood,

-jede LED ist einfach an einen Ausgang des µCs angeschlossen.
-der Hoch-/ Runterzählvorgang soll erst umgekehrt werden wenn der Vorgang abgeschlossen ist (alle LEDs an oder aus), und nicht zwischendurch.
-Soll in den 200 ms , die zwischen den Schritten liegt, auch das andere Lauflicht anfangen können. Antwort Ja

MFG
Matthias

BiGF00T
30.10.2006, 16:51
Wenn ich jetzt nur Basic könnte...
Hab mal was wildes hässliches zusammengehackt... :/
LEIDER IN C
und auch nicht unbedingt funktionstüchtig...
Aber ich denke, solange du nur immer die Taster überprüfst und dir die Richtung merkst, in die es gerade zählen soll (hier hab ich das add1 und add2 genannt und später einfach zum Lauflichtwert dazugezählt), sollte es gleichzeitig funktionieren... einfach keine 200ms warten, sondern einen zähler runter- bzw hochzählen lassen und dann die nächste led hinzuschalten.
Wahrscheinlich blamiere ich mich mit dem Stück Code total, weil wer rausfindet, dass ich nen Denkfehler drinhab... War auch nur schnell zusammengeschrieben... Hoffe, dass es die Idee vermittelt (und dass die Idee nicht falsch ist)


unsigned char wait1 = 0;
unsigned char wait2 = 0;
char add1 = 0;
char add2 = 0;
unsigned char ll1 = 0;
unsigned char ll2 = 0;
unsigned char in1 = 0;
//----------
while (1)
{
in1 = PINA; // eingänge einlesen
//----------
if (in1 == 1) // taster 1 gedrückt
{
if (ll1 == 0) // lauflicht leer?
add1 = 1; // vorwärtslauf
else if (ll1 == 13) // lauflicht voll?
add1 = -1; //rückwärtslauf
// ansonsten passiert einfach nix
}
if (in1 == 2) // taster 2 gedrückt
{
if (ll2 == 0) // lauflicht leer?
add2 = 1;
else if (ll2 == 13) // lauflicht voll?
add2 = -1;
// ansonsten passiert einfach nix
}
//----------
if (add1 != 0) // wenn das lauflicht grad mal läuft
{
if (wait1 == 0) // 200 ms sind rum oder is die erste LED...
{
ll1 = ll1 + add1; // lauflicht 1 erhöhen/verringern
wait1 = 200; // wieder von vorn zählen
}
wait1--; // zähler verringern, eine millisek. ist rum...
}
if (add2 != 0) // wenn das lauflicht grad mal läuft
{
if (wait2 == 0)
{
ll2 = ll2 + add2; // lauflicht 2 erhöhen/verringern
wait2 = 200; // wieder von vorn zählen
}
wait2--;
}
//----------
wait (1 ms);
if ((ll1 == 0) || (ll1 == 13)) // wenn endstellung erreicht, dann nix mehr machen...
{
wait1 = 0;
add1 = 0;
}
if ((ll2 == 0) || (ll2 == 13)) // wenn endstellung erreicht, dann nix mehr machen...
{
wait2 = 0;
add2 = 0;
}
//----------
// jetzt hier einfach mal die LEDs setzen. Status is in ll1 und ll2 drin.
// also einfach so viele Ausgänge auf 1 setzen, wie der Wert drin is...
}

Matthiasbaue
30.10.2006, 19:34
Hallo Bigfoot,
vielen dank für deine Mühe aber leider habe ich von C keine Ahnung.
Ich habe das Problem selber gelöst, indem ich alle goto durch Return ersetzt habe.

MFg
Matthias

robocat
30.10.2006, 23:09
freut mich, dass es nun klappt!
c code ist gar nicht so-viel-anders. ob nun "if x bla bla endif" oder if(x) {bla;bla;} is doch egal.
keine angst vor c!

BiGF00T
30.10.2006, 23:55
Gratulation. Wenn es funktioniert, dann kannst du es ja so lassen.
Natürlich ist der Code nicht optimal aber wenn er seinen Zweck erfüllt, dann kannst du ihn wegspeichern und bei Bedarf optimieren und rumprobieren...
Ja, C-Code ist nicht wirklich sehr viel anders.
Es kann auf alle Fälle nicht schaden, wenn man ihn halbwegs lesen kann, dann kann man viele Beispiele mehr verwenden. Selber schreiben muss man ihn dazu nicht können.
Vielleicht könnte man sogar einen Wiki-Beitrag machen, der die wichtigsten Sprachen (Basic, C und Asm) gegenüberstellt und die jeweiligen Equivalente von Schleifen, Kommentaren und Bedingungen in einer Tabelle gegenüberstellt, sodass Anfänger Codebeispiele in anderen Sprachen einfacher durchschauen und ggf. auch einfacher umsteigen können.

Guy
06.11.2006, 14:13
@Matthias

Auch wenn dein Programm jetzt funktioniert, habe ich die trotzdem mal ein Programm geschrieben wo du sehen kannst wie man so was macht.

Ich muß ehrlich sagen als ich dein Programm gesehen habe standen mir die Haare zu Berg.


$regfile = "8515def.dat"
Dim I As Integer
Dim Schalter1an As Bit
Dim Schalter2an As Bit
Dim Bytetemp As Byte

Config Pina.0 = Input
Config Portb = Output
Config Portc = Output

Portb = 0
Portc = 0

Do
' lampen 1
If Pina.0 = 1 Then
If Schalter1an = 1 Then
If Portb = 255 Then
Schalter1an = 0
End If
Else
If Portb = 0 Then
Schalter1an = 1
End If
End If
While Pina.0 = 1 ' WARTEN BIS TASTE WIDER LOSGELASSEN
Wend
End If
' end lampen 1


' lampen 2
If Pina.1 = 1 Then
If Schalter2an = 1 Then
If Portc = 255 Then
Schalter2an = 0
End If
Else
If Portc = 0 Then
Schalter2an = 1
End If
End If
While Pina.1 = 1 ' WARTEN BIS TASTE WIDER LOSGELASSEN
Wend
End If
' end lampen 2

' lampen 1
If Schalter1an = 1 And Portb <> 255 Then
Bytetemp = Portb
Bytetemp = Bytetemp + 1
Portb = Portb Or Bytetemp
End If
If Schalter1an = 0 And Portb <> 0 Then
Shift Portb , Right
' Shift Portb , Left ' anders rum
End If
' end lampen 1


' lampen 2
If Schalter2an = 1 And Portc <> 255 Then
Bytetemp = Portc
Bytetemp = Bytetemp + 1
Portc = Portc Or Bytetemp
End If
If Schalter2an = 0 And Portc <> 0 Then
Shift Portc , Right
' Shift Portc , Left ' anders rum
End If
' end lampen 2

For I = 1 To 5
'Die for Schleife ist nur beim Simulator notwendig, weil der wait befehl mit der LCD Anzeige im Simulator nicht funktioniert.
'Also wenn fertig Schleife durch Wait ersetzen.
' Waitms 0.1
Next I
Loop


mfg Guy

Edit

Hier noch ein Beispiel wie du zum Beispiel die Lampen auch ausschalten kannst.


If Schalter1an = 0 And Portb <> 0 Then
' Shift Portb , Right
' Shift Portb , Left ' anders rum
Portb = Portb / 2
End If

Mußt dich mal mit binär rechen abgeben. Als Beispiel, bei einer Binärzahl verschiebst du durch Division alles nach Rechts, und durch Multiplikation alles nach links.