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:
Code:
'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:
Code:
'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:
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ß )
Lesezeichen