PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Subroutinen starten selbstständig, sollten sie aber nicht



Fabs
21.05.2008, 09:06
Hallo, ich versuche zurzeit als erstes eigenes Programm eine Ampel zu programmieren. Wenn man auf Taster1 drückt sollte die Ampel rot werden und bei Taster2 sollte die Gelbe LED blinken.
Leider passiert das auch schon wenn die Taster nicht gedrückt werden.
Ich hab es jetzt mit Interrupt-Flags und dem Debounce-Befehl probiert, aber es funktioniert beides nicht. Die Subroutinen werden scheinbar zufällig aufgerufen.

Hier habe ich es mit den Interrupt-Flags probiert:

'Ampel mit Fussgängerinterrupt #03.BAS: Immer grün, wenn T1 gedrückt -> 2s gelb, 6s rot/5sec Speaker, 2s gelb, wieder grün
' wenn T2 gedrückt -> gelbe LED blinkt, T2 erneut drücken -> Ampel wird wieder grün
'Hardware: Grüne LED an PD5, gelbe LED an PD6, rote LED an PD7,
' Taster1 an PD2/INT0, Taster2 an PD3/INT1, Speaker an PB0
'---------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 3686400

Declare Sub Fussgaenger
Declare Sub Ampelaus
Dim Var As Byte

Ddrd = &B11100000 'PD5..PD7=Ausgang
Portd = &B00001100 'PullUps von PD2+3 aktivieren
Ddrb = &B00000001 'PB0=Ausgang
Mcucr = &B00001010 'INT0 und INT1 auslösebedingung bei H/L Flanke
'---------------------------------------------------------------------------
Main:
Portd = &B00100000 'Grüne LED
Do
If Gifr.6 = 1 Then 'Ist das INTF0-Flag gesetzt?
Gifr.6 = 1 'INTF0-Flag wieder löschen
Call Fussgaenger
End If
If Gifr.7 = 1 Then 'Ist das INTF1-Flag gesetzt?
Gifr.7 = 1 'INTF1-Flag wieder löschen
Call Ampelaus
End If
Loop
'----------------------------------------------------------------------------
Sub Fussgaenger:
Var = 0
Portd = &B01000000 'Gelbe LED
Wait 2
Portd = &B10000000 'Rote LED
Wait 1

Fussgruen:
Toggle Portb.0 'Speaker invertieren
Waitms 1000 '1sec warten
Var = Var + 1
If Var < 5 Then 'Insgesamt 5sec warten
Goto Fussgruen

End If
Portd = &B11000000 'Rote und gelbe LED
Wait 2
Portd = &B00100000 'Grüne LED
End Sub
'----------------------------------------------------------------------------
Sub Ampelaus:
Portd = &B01000000 'Gelbe LED
Wait 2
Portd = &B10000000 'Rote LED
Wait 1
Portd = &B00000000 'Erst alle LEDs auschalten
Do
Toggle Portd.6 'Gelbe LED im Abstand von 0,5sec an- und ausschalten
Waitms 500
If Gifr.7 = 1 Then 'Ist das INTF1-Flag gesetzt?
Gifr.7 = 1 'INTF1-Flag wieder löschen
Goto Ampelan
End If
' If Gifr.6 = 1 Then 'Ist das INTF0-Flag gesetzt?
' Gifr.6 = 1 'INTF0 wieder löschen
' Call Fussgaenger
' End If
Loop

Ampelan:
Portd = &B01000000 'Gelbe LED
Wait 1
Portd = &B00100000 'Grüne LED
End Sub
'----------------------------------------------------------------------------
End

Und hier mit dem Debounce-Befehl:

'Ampel mit Fußgängerinterrupt - Debounce.BAS: Immer grün, wenn T1 gedrückt -> 2s gelb,
' 6s rot/5sec Speaker, 2s gelb, wieder grün
' wenn T2 gedrückt -> gelbe LED blinkt,
' T2 erneut drücken -> Ampel wird wieder grün
'Hardware: Grüne LED an PD5, gelbe LED an PD6, rote LED an PD7,
' Taster1 an PB4, Taster2 an PB2, Speaker an PB0
'----------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 3686400

Dim Var As Byte

Ddrd = &B11100000 'PD5..PD7=Ausgang
Ddrb = &B00000001 'PB0=Ausgang
Portb = &B00010100 'PullUps von PB2+4 aktivieren
'----------------------------------------------------------------------------
Main:
Portd = &B00100000 'Grüne LED
Do
Debounce Pinb.2 , 0 , Ampelaus
Debounce Pinb.4 , 0 , Fussgaenger
Loop
'----------------------------------------------------------------------------
Fussgaenger:
Var = 0
Portd = &B01000000 'Gelbe LED
Wait 2
Portd = &B10000000 'Rote LED
Wait 1

Fussgruen:
Toggle Portb.0 'Speaker invertieren
Waitms 1000 '1sec warten
Var = Var + 1
If Var <= 5 Then 'Insgesamt 6sec warten
Goto Fussgruen
End If

Portd = &B11000000 'Rote und gelbe LED
Wait 2
Portd = &B00100000 'Grüne LED
Return
'----------------------------------------------------------------------------
Ampelaus:
Portd = &B01000000 'Gelbe LED
Wait 2

Gelbblinken:
Var = 0
Toggle Portd.6

Langsamblinken:
If Var < 10 Then
Waitms 50
Debounce Pinb.2 , 0 , Ampelan
Debounce Pinb.4 , 0 , Fussgaenger
Var = Var + 1
Goto Langsamblinken
End If

If Var >= 10 Then
Goto Gelbblinken
End If

Ampelan:
Portd = &B01000000 'Gelbe LED
Wait 1
Portd = &B00100000 'Grüne LED
Return
'----------------------------------------------------------------------------
End


Danke schonmal und viele Grüße
Fabs

[Edit 23.05.08 12:20]: Code aktualisiert
[Edit 26.05.08 08:15]: Code aktualisiert

MeckPommER
21.05.2008, 09:56
hallöchen :-)

nur kurz zwei anmerkungen:

-wie hast du die taster beschaltet? schliesst der taster den pin auf ground mit einem pullup? Es gibt nämlich immer probleme, wenn man die pins "in der luft" zu hängen hat, sie also weder nach + noch nach gnd beschaltet.

du kannst die taster entweder nach + schliessen mit einem externen widerstand von ca. 10kohm nach gnd (pull-down), oder nach gnd schliessen lassen mit dem internen pull-up.

- du springst gen ende deiner subs per "goto" wieder ins hauptprogramm. das ist absolut verboten (nee ... ist erlaubt aber sollte verboten werden ^^)

das "end sub" sorgt schon dafür, das der rechner an der stelle nach dem aufruf des subs weitermacht. das "goto" allerdings zerkrümelt dir die controllerinternen strukturen (stack).

also einfach weg mit dem "goto main"!

Fabs
21.05.2008, 10:22
Hallo,

die Taster habe ich mit "Portd = &B00001100" durch den internen PullUp auf gnd geschlossen.

Das Goto benutze ich, da in "Main" als erstes die Grüne LED wieder eingeschaltet wird. Das reicht ja wenn man das einmal macht und muss in der Hauptschleife nicht die ganze Zeit wiederholt werden. Wenn ich "Goto Main" weglassen würde, würde er ja mit "End Sub" direkt in die Hauptschleife springen.

[Edit:]
Mir fällt gerade ein, dass ich die Grüne LED ja auch einfach jeweils am Ende der Sub einschalten kann, also kann ich "Goto" wirklich weglassen :)

MeckPommER
21.05.2008, 11:03
Du kannst nicht nur, sondern du MUSST das goto weglassen. Grund ist folgender:
Bei einem Sprung zu einer Unterroutine mit call oder gosub, merkt sich der controller die adresse, von der er kam, um danach an dieser stelle weiterarbeiten zu können.
Er packt diese Adresse (2 Bytes) auf einen stapel und merkt sich, das dieser stapel wieder 2 bytes "höher" geworden ist.

ist das unterprogramm beendet, so nimmt der controller einfach die beiden obersten bytes vom stapel und weiß nun, wo er weiterzumachen hat und das der stapel nun wieder 2 bytes weniger hoch ist.

springst du nun aber mit "goto" aus dem sub wieder ins hauptprogramm, so legt jeder aufruf des unterprogramms 2 bytes auf den stapel, die niemals wieder heruntergenommen werden. das ergibt dann irgendwann einen stapelüberlauf.


Ach ja ... und subs werden nicht mit gosub aufgerufen, sondern wenn, dann mit "call".

Fabs
21.05.2008, 11:55
Das "Goto Main" hab ich jetzt weg.

Wenn ich das der BASCOM Hilfe richtig entnommen habe ist der Unterschied zwischen "Gosub" und "Call" doch, dass man bei "Call" Variablen mit in die Subroutine nehmen kann. Dann müsste es doch, wenn man keine Variablen mitnehmen will, besser sein, wenn man "Gosub" nimmt oder hat das ganze noch andere Gründe?

Und hast du vielleicht noch eine Idee, wie man das Problem mit den selbststartenden Subroutinen lösen kann?

MeckPommER
21.05.2008, 13:05
Der Unterschied zwischen "gosub" und "call" ist, das "gosub" einfach zu einem Unterprogramm spring und "call" eine Funktion oder Prozedur aufruft. Eine Prozedur ohne Parameterübergabe ist zwar nichts anderes als ein einfaches Unterprogramm, trotzdem sollte man es (Bascom-)sprachlich nicht durcheinanderwurschteln.

Ein Unterprogramm wird einfach mit der Sprungadresse aufgerufen.

...
gosub mach_was
...

mach_was:
... dies und das
return

während eine Prozedur oder Funktion zu Anfang des Programms deklariert wird und Parameter übergeben werden können.

Die Deklarierung als Prozedur und das Ausführen mit gosub ist also eine Mischung, die man vermeiden sollte. Es funktioniert halt nur "zufällig", da keine Parameter übergeben werden. Ob es tatsächlich auch im erzeugten Code zu 100% sauber ist, kann ich auch nicht sagen.

Jedenfalls ist es besser, gleich zu Anfang Unsauberkeiten zu vermeiden, um sich keinen schlechten Programmierstil anzugewöhnen :-)

Definierte Prozeduren kommen sogar ohne "Call" und "Gosub" aus, sehen dann als wirklich wie reguläre Basic-Befehle aus.

Was deinen Code angeht so hab ich mir nochmal dein erstes Listing angeschaut. Wo soll da was per Interrupt passieren? Du fragst in der Hauptschleife doch ständig die Taster ab?

Fabs
21.05.2008, 13:32
In der Hauptschleife brauche ich auch eigentlich nichts zu unterbrechen. Ich wollte es nur mit den Interrupt-Flags probieren, weil ich die die sehr praktisch finde (man kann die Taste drücken, aber es wird erst gesprungen, wenn das Programm an der Stelle ankommt, wo das Interrupt-Flag abgefragt wird).
Im zweiten Listing habe ich es dann ja mit "Debounce" anstelle des Interrupts probiert, aber da habe ich das gleiche Problem. (also die Subroutinen starten ohne dass ich sie ausgelöst habe).
Ich dachte auch schon, dass das vielleicht durch irgendwelche Funkwellen, Felder etc. ausgelöst werden könnte, aber ich habe ein einfaches Beispielprogramm in den AVR gebrannt und das hat auch einwandfrei funktioniert.

Fabs
21.05.2008, 14:15
Mir ist garade die "gloreiche" Idee gekommen, man könnte die Taster ja mal an andere Pins anschließen. Mit dem "Debounce"-Befehl funktioniert es jetzt aber für die Interrupts müssen die Taster beim ATmega8 doch an PD2/INT0 bzw. PD3/INT1 angeschlossen sein.
Kann man das auch irgendwie anders lösen?
Oder wie könnte man eventuelle Störquellen eliminieren?

Fabs
26.05.2008, 07:41
Den Code habe ich im ersten Beitrag jetzt nochmal aktualisiert.
Der Teil mit dem Debounce-Befehl klappt jetzt soweit an den anderen Pins. Das einzige Problem ist noch, dass der Lautsprecher aus der "Fussgaenger"-Routine beim zurückkehren ins Hauptprogramm nocheinmal invertiert wird, allerdings nur wenn Var<x oder Var <=y ist (wobei x=ungerade Zahl 1,3,5,... und y=gerade Zahl 2,4,6,...) ansonsten klappt es. Aber das ist eigentlich nur nebensächlich.

Das große Problem ist immer noch der Teil mit den Interrupts. Wenn man die Benutzen möchte muss man die Taster soweit ich weiß ja an PD2/INT0 bzw. PD3/INT1 (ATmega8) anschließen.
Das Problem ist immer noch, dass die Subroutinen einfach selbstständig anfangen zu laufen und das noch nicht einmal nach einem bestimten Schema (mal die eine, dann die andere, mal bleibt er länger in der Hauptschleife und mal so kurz, dass man noch nicht einmal sieht, dass die LED angeht).
Was ich später gerne machen würde ist das Programm bei "Ampelaus" in den Power-down Mode zu bringen und dafür brauche ich ja die Interrupts.
Und dann nochmal etwas nebensächliches: Wenn die Ampel aus ist möchte ich auch gerne direkt von dort aus in die "Fussgaenger"-Routine springen können (im Programm ist das der auskommentierte Teil). Ich bin mir aber nicht sicher ob man das so machen kann, weil man dann ja zweimal ein Subfunktion aufgerufen hätte, aber am Ende nur ein "End Sub" (als erstes "Call Ampelaus", dann "Call Fussgaenger" und dann einmal "End Sub")
Ich hoffe ich habe mich irgendwie verständlich ausgedrückt :)

Hat dazu noch irgendjemand eine Idee?

Fabs
30.05.2008, 07:43
Ich hab den Fehler nach endlosem Suchen endlich gefunden:
durch das einschalten der LED's mit PORTD=&Bxxx00000 habe ich gleichzeitig die PullUp-Widerstände, die ich mit PORTD=&B00001100 aktiviert habe wieder ausgeschaltet ...

Hier der funktionierende Code mit Interruptflags:

'Ampel mit Fussgängerinterrupt #03 Interruptflag.BAS:
'Immer grün, wenn T1 gedrückt -> 2s gelb, 6s rot/5sec Speaker, 2s gelb, wieder grün
'wenn T2 gedrückt -> gelbe LED blinkt, T2 erneut drücken -> Ampel wird wieder grün
'Hardware: Grüne LED an PD5, gelbe LED an PD6, rote LED an PD7,
' Taster1 an PD2/INT0, Taster2 an PD3/INT1, Speaker an PB0
'---------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 3686400

Declare Sub Fussgaenger
Declare Sub Ampelaus
Dim Var As Byte
Dim A As Byte

Ddrd = &B11100000 'PD5..PD7=Ausgang
Portd = &B00001100 'PullUps von PD2+3 aktivieren
Ddrb = &B00000001 'PB0=Ausgang
Mcucr = &B00001010 'INT0 und INT1 auslösebedingung bei H/L Flanke
'---------------------------------------------------------------------------
Main:
Portd = &B00100000 Or &B00001100 'Grüne LED
'Ohne das "OR" würde der PullUp-Widerstand wieder ausgeschaltet und die Programme laufen zufällig und von alleine ab!
'Man könnte allerdings auch einfach PORTD=&Bxxxx11xx schreiben oder die LED's zu Fuss mit PORTD.x=1/0 an- bzw. ausmachen
Do
Waitms 50 '50 ms warten, (quasi ein manueller debounce)
If Gifr.6 = 1 Then 'Ist das INTF0-Flag gesetzt?
Gifr.6 = 1 'INTF0-Flag wieder löschen
Call Fussgaenger
End If
If Gifr.7 = 1 Then 'Ist das INTF1-Flag gesetzt?
Gifr.7 = 1 'INTF1-Flag wieder löschen
Call Ampelaus
End If
Loop
'----------------------------------------------------------------------------
Sub Fussgaenger:
Var = 0
Portd = &B01000000 Or &B00001100 'Gelbe LED
Wait 2
Portd = &B10000000 Or &B00001100 'Rote LED
Wait 1

Fussgruen:
Toggle Portb.0 'Speaker invertieren
Waitms 1000 '1sec warten
Var = Var + 1
If Var < 5 Then 'Insgesamt 5sec warten
Goto Fussgruen
End If

Portd = &B11000000 Or &B00001100 'Rote und gelbe LED
Wait 2
Portd = &B00100000 Or &B00001100 'Grüne LED

If A = 1 Then 'Wenn die Ampel aus war,...
Wait 2
Goto Ampelwiederaus '...dann mach sie auch wieder aus
End If
End Sub
'----------------------------------------------------------------------------
Sub Ampelaus:
Ampelwiederaus:
A = 1
Portd = &B01000000 Or &B00001100 'Gelbe LED
Wait 2
Portd = &B00000000 Or &B00001100 'Erst alle LEDs auschalten
Do
Toggle Portd.6 'Gelbe LED im Abstand von 0,5sec an- und ausschalten
Waitms 500
If Gifr.7 = 1 Then 'Ist das INTF1-Flag gesetzt?
Gifr.7 = 1 'INTF1-Flag wieder löschen
Goto Ampelan
End If
If Gifr.6 = 1 Then 'Ist das INTF0-Flag gesetzt?
Gifr.6 = 1 'INTF0-Flag wieder löschen
Goto Fussgaenger '???Stack Überlauf, da ein "End Sub" ausgelassen wird???
End If 'Nein, den durch das Goto wird keine Sub aufgerufen
Loop

Ampelan:
A = 0
Portd = &B01000000 Or &B00001100 'Gelbe LED
Wait 1
Portd = &B00100000 Or &B00001100 'Grüne LED
End Sub
'----------------------------------------------------------------------------
End

Und hier der funktionierende Code mit dem Debounce:

'Ampel mit Fußgängerinterrupt - Debounce.BAS: Immer grün, wenn T1 gedrückt -> 2s gelb,
' 6s rot/5sec Speaker, 2s gelb, wieder grün
' wenn T2 gedrückt -> gelbe LED blinkt,
' T2 erneut drücken -> Ampel wird wieder grün
'Hardware: Grüne LED an PD5, gelbe LED an PD6, rote LED an PD7,
' Taster1 an PD2, Taster2 an PD3, Speaker an PB0
'----------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 3686400

Dim A As Byte
Dim Var As Byte

Ddrd = &B11100000 'PD5..PD7=Ausgang
Ddrb = &B00000001 'PB0=Ausgang
Portd = &B00001100 'PullUps von PD2+3 aktivieren
'----------------------------------------------------------------------------
Main:
'Wenn man direkt den ganzen PORTD=&Bxxxxxxxx setzen will müsste man PORTD=&Bxxxx11xx oder
'PORTD=&Bxxxxxxxx OR &B00001100 benutzen um die PullUp-Widerstände nicht auszuschalten.
Portd.7 = 0 'Rot aus
Portd.6 = 0 'Gelb aus
Portd.5 = 1 'Grün an
Do
Debounce Pind.3 , 0 , Ampelaus
Debounce Pind.2 , 0 , Fussgaenger
Loop
'----------------------------------------------------------------------------
Fussgaenger:
Var = 0
Portd.5 = 0 'Grün aus
Portd.6 = 1 'Gelb an
Wait 2
Portd.6 = 0 'Gelb aus
Portd.7 = 1 'Rot an
Wait 1

Fussgruen:
Toggle Portb.0 'Speaker invertieren
Waitms 1000 '1sec warten
Var = Var + 1
If Var <= 5 Then 'Insgesamt 6sec warten
Goto Fussgruen
End If

Portd.6 = 1 'Gelb an (->Rot-Gelb)
Wait 2
Portd.7 = 0 'Rot aus
Portd.6 = 0 'Gelb aus
Portd.5 = 1 'Grün an
If A = 1 Then 'Wenn Ampel vorher aus war,...
Wait 2
Goto Ampelaus '...dann schalte sie auch wieder aus
'???Stacküberlauf wegen überspringen von Return???
End If 'Nein, denn Debounce beutzt den Goto Befehl und es wird keine...
Return '...Sub aufgerufen.wenn kein SUB am Ende spezifiziert wird.
'----------------------------------------------------------------------------
Ampelaus:
A = 1
Portd.5 = 0 'Grün aus
Portd.6 = 1 'Gelb an
Wait 2

Do
Var = 0
Toggle Portd.6 'Gelbe LED invertieren

Langsamblinken:
If Var < 10 Then '10 mal Taster abfragen (0,5sekunden) ...
Waitms 50
Debounce Pind.3 , 0 , Ampelan
Debounce Pind.2 , 0 , Fussgaenger
Var = Var + 1
Goto Langsamblinken '...dann die Gelbe LED invertieren
End If
Loop

Ampelan:
A = 0
Portd.6 = 1 'Gelb an
Wait 1
Portd.6 = 0 'Gelb aus
Portd.5 = 1 'Grün an
Return
'----------------------------------------------------------------------------
End

Und falls es jemanden interessiert: ich habe "zwischendurch" noch eine über die UART gesteuerte Ampel programmiert. Es gehört jetzt zwar nicht ganz hier hin, aber falls jemand nach "Ampel" sucht wird er (oder sie) wohl auch auf diesen Beitrag stoßen. Also hier der Code:

'Ampel mit Fußgängerinterrupt #05 UART.BAS: Ampelphasen sollen über die UART gesteuert werden.
'Hardware: Grüne LED an PD5, gelbe LED an PD6, rote LED an PD7, Speaker an PB0;
' MAX232 an PD0/PD1, Nullmodemkabel zum PC
'-------------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 3686400

Config Com1 = Baud = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

Dim C As Byte
Dim I As Byte
Dim J As Byte
Dim K As Byte
Dim L As Byte
Dim M As Byte
Dim Var As Byte

Ddrd = &B11100000 'PD7,6,5 als Ausgang
Ddrb = &B00000001 'PB0 als Ausgang
'-------------------------------------------------------------------------------
Main:
Portd = &B00100000 'Grüne LED
C = 1
Do
If Ucsra.rxc = 1 Then 'Ein Byte vollständig empfangen
I = Udr 'Byte aus der UART auslesen
Select Case I
Case "1"
Fussgaenger:
Print "Fussgaengerampel initiiert!"
If Portd = &B00000000 Or Portd = &B01000000 Then 'Wenn Ampel aus war setze J=1, damit
J = 1 'die Ampel später automatisch wieder ausgeschaltet wird
End If
Var = 0
Portd = &B01000000 'Gelbe LED
Print "Gelb"
Wait 2
Portd = &B10000000 'Rote LED
Print "Rot"
Wait 1
Print "Fussgaengerampel eingeschaltet!"
Fussgruen:
Toggle Portb.0 'Speaker invertieren
Waitms 1000 '1sec warten
Var = Var + 1
If Var <= 5 Then 'Insgesamt 6sec warten
Goto Fussgruen
End If
Print "Fussgaengerampel ausgeschaltet!"
Wait 1
Portd = &B11000000 'Rote und gelbe LED
Print "Rot-Gelb"
Wait 2
Portd = &B00100000 'Grüne LED
Print "Gruen"
Wait 1
If J = 1 Then 'Wenn die Ampel vorher aus war ...
Goto Ampelsicheraus '...schalte sie auch wieder aus
End If
Case "2"
C = 0
Ampelaus:
Print "Sind Sie sicher, dass Sie die Ampel auschalten moechten? (J/N)"
Do
If Ucsra.rxc = 1 Then 'Ein Byte vollständig empfangen
L = Udr 'Byte aus der UART auslesen
M = L And &B11011111 'Aus kleinen Buchstaben große machen
Select Case M 'Jetzt solange warten, bis "J" oder "N" eingegeben wurde
Case "J"
Print "J"
Goto Ampelsicheraus
Case "N"
Print "N"
Goto Main
Case Else
Print "Bitte geben Sie >J< fuer Ja oder >N< fuer Nein ein"
End Select
End If
Loop
Ampelsicheraus:
Print "Ampel wird ausgeschaltet"
Portd = &B01000000 'Gelbe LED
If J = 1 Then 'Wenn die Ampel automatisch ausgeschaltet wird, weil J=1,...
J = 0 '...setze J=0 damit das nicht passiert, wenn die Ampel...
Waitms 500 '...vor dem Fussgaengerinterrupt an war
Goto Ampelblinkt
Else
Wait 2
End If
Ampelblinkt:
Print "Ampel ist ausgeschaltet"
Do
Toggle Portd.6 'Gelbe LED Blinkt
Waitms 500 'Im Abstand von 0,5sekunden
If Ucsra.rxc = 1 Then 'Ein Byte vollständig empfangen
K = Udr 'Byte aus der UART auslesen
Select Case K
Case "1"
Goto Fussgaenger
Case "2" 'Die Ampel soll ja weiter blinken und nicht aus dem ...
Print "Ampel ist bereits ausgeschaltet" '...Rhytmus kommen
Case "3"
Goto Ampelein
Case "5"
Print "1=Fussgaengerampel anschalten"_
"2=Ampel ausschalten"_
"3=Ampel einschalten"
Case Else
Print "Befehl ungueltig. Senden Sie >5< um eine Liste der moeglichen Befehle zu erhalten"
End Select
End If
Loop
Case "3"
If C = 1 Then 'Die Ampel soll ja nicht zwischendurch einfach Gelb werden
Print "Ampel ist bereits eingeschaltet"
Goto Ampelistan
End If
Ampelein:
Print "Ampel wird eingeschaltet"
Portd = &B01000000 'Gelbe LED
Wait 2
Portd = &B00100000 'Grüne LED
Print "Ampel ist eingeschaltet"
C = 1
Ampelistan:
Case "5"
Print "1=Fussgaengerampel anschalten"_
"2=Ampel ausschalten"_
"3=Ampel einschalten"
Case Else
Print "Befehl ungueltig. Senden Sie >5< um eine Liste der moeglichen Befehle zu erhalten"
End Select
End If
Loop
'-------------------------------------------------------------------------------
End

Falls jemand noch Fragen hat, so kann er sie gerne stellen. Ich werde dann versuchen sie zu beantworten (oder vllt. macht das auch jemand anderes, der die Antwort weiß :) )