-         

Ergebnis 1 bis 10 von 10

Thema: Subroutinen starten selbstständig, sollten sie aber nicht

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7

    Subroutinen starten selbstständig, sollten sie aber nicht

    Anzeige

    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:
    Code:
    '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:
    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 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

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.07.2007
    Alter
    53
    Beiträge
    1.080
    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"!
    Mein Hexapod im Detail auf www.vreal.de

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7
    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

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.07.2007
    Alter
    53
    Beiträge
    1.080
    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".
    Mein Hexapod im Detail auf www.vreal.de

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7
    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?

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.07.2007
    Alter
    53
    Beiträge
    1.080
    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?
    Mein Hexapod im Detail auf www.vreal.de

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7
    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.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7
    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?

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7
    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 (ATmega 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?

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    21.05.2008
    Ort
    Bonn
    Alter
    30
    Beiträge
    7

    Subroutinen starten selbstständig, sollten sie ... [gelöst]

    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ß )

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •