-
        

Ergebnis 1 bis 5 von 5

Thema: Verständnisfrage zu SUB deklarieren

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    25.03.2006
    Ort
    Hinsdorf
    Alter
    42
    Beiträge
    379

    Verständnisfrage zu SUB deklarieren

    Anzeige

    Hallo und einen schönen Abend!

    Auch nach durchlesen einiger Artikel hier habe ich noch immer nicht den Sinn gefunden eine Sub zu declarieren.
    Ich habe ein Prog geschrieben:
    Code:
    $regfile = "m8def.dat"                                                          ' specify the used micro
    $crystal = 12000000                                                             ' used crystal frequency                                                                   ' use baud rate
    $hwstack = 50                                                                   ' default use 32 for the hardware stack
    $swstack = 50                                                                   ' default use 10 for the SW stack
    $framesize = 40                                                                 ' default use 40 for the frame space
    '$sim
    'Declare Sub Fensterhoch_kue                                                     'PinB0 =>SV2/8  Fernbedienungsempfänger
    'Declare Sub Fensterrunter_kue                                                   'PinB2 =>SV2/6
    'Declare Sub Fensterhoch_bad                                                     'PinC3 =>SV2/4
    'Declare Sub Fensterrunter_bad
    'Declare Sub Temp_holen
    'Declare Sub Rel_wasser_an
    '------------------------------------------------------------------------------- Twi_lcd
    $lib "Lcd_i2c.lib"                                                              'My I2C driver for the LCD
    
    Config Lcd = 16 * 2
    Config Lcdbus = 4
    Initlcd
    Cursor Off
    Cls
    
    Const Pcf8574_lcd = &H40                                                        'Defines the address of the I/O expander for LCD
    
    Config Scl = Portc.5                                                            'Configure I2C SCL
    Config Sda = Portc.4                                                            'Configure I2C SDA
    Dim _lcd_e As Byte                                                              'Needed to control 4 line LCD
    _lcd_e = 128
    
    '------------------------------------------------------------------------------- Variablen
    Const Rolltime = 32
    
    
    Ddrd = &B11111111                                                               'Config Portd = Output
    Portb = &B00000101
    Portc = &B00001011                                                              'Pull up Portb.2 ein
    Rel_bad_auf Alias Portd.0                                                       'Alias für Relaise-Fensterheber Bad auf
    Rel_bad_zu Alias Portd.1
    Rel_kue_auf Alias Portd.2
    Rel_kue_zu Alias Portd.3
    Rel_wasser Alias Portd.6                                                        'Eingangssignal von der Brennerzeitsteuerung
    'Port_brenner Alias Portc.0                                  '{Portb.2}Eingang vom der Zeitsteuerung vom Ofen => Tag/Nachtprogramm: 0=Nachtabsenkung, 1=Tagprogramm
    
    Dim Flag_bad_auf_1 As Word , Flag_bad_auf_2 As Word , Fenster_bad_offen As Bit
    Dim Flag_bad_zu_1 As Word , Flag_bad_zu_2 As Word , Fenster_bad_zu As Bit
    Dim Flag_kue_auf_1 As Word , Flag_kue_auf_2 As Word , Fenster_kue_auf As Bit
    Dim Flag_kue_zu_1 As Word , Flag_kue_zu_2 As Word , Fenster_kue_zu As Bit
    'Dim Flag_wo_auf_1 As Word , Flag_wo_auf_2 As Word
    'Dim Flag_wo_zu_1 As Word , Flag_wo_zu_2 As Word
    
    Dim Twi_daten As Byte
    Dim Pump_st As Byte , Pump_st_z As Bit                                          'Zähler für die Pumpenstarts
    
    
    '------------------------------------------------------------------------------- Timer1 konfigurieren
    Config Timer1 = Timer , Prescale = 256
    On Timer1 Counter_irq
    Const Timer1vorgabe = 18661
    Enable Timer1
    Enable Interrupts
    Dim Timecount As Word
    
    
    '------------------------------------------------------------------------------- Configuration DS1820
    Config 1wire = Portb.1
    Dim Id1(8) As Byte
    Dim Id2(8) As Byte
    Dim Ar1(2) As Byte
    Dim Ar2(2) As Byte
    Dim T_vorl As Byte
    'Dim Tempraturbyte(6) As Byte At T_vorl Overlay
    Dim T_ruekl As Byte , T_ruekl_1 As Byte
    
    
    Id1(1) = 1wsearchfirst()
    Id2(1) = 1wsearchnext()
    
    '******************************************************************************* Hauptprogramm
    
    
    Do
    
    Debounce Pinb.0 , 0 , Fensterhoch_kue , Sub                                     'PinB0 =>SV2/8  Fernbedienungsempfänger
    Debounce Pinb.2 , 0 , Fensterrunter_kue , Sub                                   'PinB2 =>SV2/6
    Debounce Pinc.3 , 0 , Fensterhoch_bad , Sub                                     'PinC3 =>SV2/4
    Debounce Pinc.1 , 0 , Fensterrunter_bad , Sub                                   'PinC1 =>SV2/2
    
    If Timecount = 0 Then
       Lowerline                                                                    'select the lower line
       Waitms 1
       Locate 2 , 1
       Lcd "t=    "
    End If
    '
    Lowerline                                                                       'select the lower line
    Waitms 1
    Locate 2 , 1
    Lcd "t=" ; Timecount
    Waitms 1
    Locate 2 , 8
    Lcd "pu=" ; Rel_wasser
    Waitms 1
    Locate 2 , 13
    Lcd "br=" ; Pinc.0
    Waitms 1
    Upperline
    Locate 1 , 11
    Lcd "bs" ; Pump_st
    '                                                              'Port_brenner
     Upperline
      Locate 1 , 1
      Lcd "Tr" ; T_ruekl
      Waitms 1
     Upperline
      Locate 1 , 6
      Lcd "Tv" ; T_vorl
      Waitms 1
    '
    '******************************************************************************* Steuerung Umlaufpumpe Warmwasser
      1wreset                                                                       '1wirebus resetten
      1wwrite &HCC : 1wwrite &H44
                                     'Messung der temp beider Sensoren starten
    If Pinc.0 = 0 Then                                                              'Zeitprogramm vom Brenner
      If Timecount = 0 Or Timecount = 800 Or Timecount = 1600 Or Timecount = 2400 Or Timecount = 3200 Or Rel_wasser = 1 Then       'aller 20min {0,1200,2400} Rücklauftemperatur überprüfen dann Sprung in Unterprogramm
        Gosub Temp_holen
        Gosub Rel_wasser_an
      End If
    End If                                                                          'beide DS1820 Messung anstoßen
    'Gosub Temp_holen
    
    
    
    '*************************************************
     Select Case Twi_daten
    '******************************************************************************* Rolladen Bad rauf
             Case 1 : If Rel_bad_zu = 0 And Fenster_bad_offen = 0 Then              'Tastenverrieglung
                       Toggle Rel_bad_auf                                           'umschalten von Port zwischen 0&1
                       Fenster_bad_zu = 0                                           ' nach fenster vollständig runter, erst wieder möglich runter zu fahren nach dem es wieder rauffuhr
                       Else
                      Twi_daten = 0
                       Goto Ende
                       End If
                       'Locate 2 , 3
                       'Lcd Rel_bad_auf
    
                       If Rel_bad_auf = 1 And Flag_bad_auf_2 = 0 And Flag_bad_zu_2 = 0 Then       'if Abfrage jedesmal wenn case1 ist und somit der Port getoggle wird
                         Flag_bad_auf_1 = Rolltime + Timecount                      ' flag mit der Laufzeit für  Fenster kompl. auf plus Sekundenzähler
                          Elseif Rel_bad_auf = 1 And Flag_bad_zu_2 > 0 Then
                          Flag_bad_auf_2 = Rolltime - Flag_bad_zu_2                 'nach dem das Fenster runtergefahren wurde, wurde der Laufzeitwert im Flag_bad_zu_2 gespeichert, jetzt wird bei
                          Flag_bad_auf_1 = Timecount + Flag_bad_auf_2               ' erneutem auffahren die restliche Zeit, für komplett auf, neu in Flag_bad_auf_1 geschrieben
                          Flag_bad_zu_2 = 0                                         ' löschen der der Zeit die schon zugefahren ist
                       End If
    
                        If Rel_bad_auf = 0 And Flag_bad_auf_2 > 0 Then              'if Abfrage jedesmal wenn case1 ist und somit der Port getoggle wird
                          Elseif Rel_bad_auf = 1 And Flag_bad_auf_2 > 0 Then        '
                          Flag_bad_auf_1 = Timecount + Flag_bad_auf_2
                          Flag_bad_auf_2 = 0
                        End If
    
                        If Rel_bad_auf = 0 And Flag_bad_auf_1 > 0 Then
                          Flag_bad_auf_2 = Timecount
                          Flag_bad_auf_2 = Flag_bad_auf_1 - Flag_bad_auf_2
                        End If
    
                     Twi_daten = 0
    
    '******************************************************************************* Rolladen Bad runter
            Case 11 : If Rel_bad_auf = 0 And Fenster_bad_zu = 0 Then
                      Toggle Rel_bad_zu
                     Fenster_bad_offen = 0
                      Else
                     Twi_daten = 0
                      Goto Ende
                      End If
    
                       If Rel_bad_zu = 1 And Flag_bad_zu_2 = 0 And Flag_bad_auf_2 = 0 Then
                          Flag_bad_zu_1 = Rolltime + Timecount
                          Elseif Rel_bad_zu = 1 And Flag_bad_auf_2 > 0 Then
                          Flag_bad_zu_2 = Rolltime - Flag_bad_auf_2
                          Flag_bad_zu_1 = Timecount + Flag_bad_zu_2
                          Flag_bad_auf_2 = 0
                       End If
    
                       If Rel_bad_zu = 0 And Flag_bad_zu_2 > 0 Then
                          Elseif Rel_bad_zu = 1 And Flag_bad_zu_2 > 0 Then
                          Flag_bad_zu_1 = Timecount + Flag_bad_zu_2
                          Flag_bad_zu_2 = 0
                          End If
                       If Rel_bad_zu = 0 And Flag_bad_zu_1 > 0 Then
                          Flag_bad_zu_2 = Timecount
                          Flag_bad_zu_2 = Flag_bad_zu_1 - Flag_bad_zu_2
                       End If
                      Twi_daten = 0
    
    '******************************************************************************* Rolladen Küche rauf
             Case 2 : If Rel_kue_zu = 0 And Fenster_kue_auf = 0 Then
                       Toggle Rel_kue_auf
                      Fenster_kue_zu = 0
                       Else
                       Twi_daten = 0
                       Goto Ende
                       End If
                       Locate 2 , 5
                       Lcd Rel_kue_auf                                              '     If Flag_bad_auf_2 = 0  And
                       If Rel_kue_auf = 1 And Flag_kue_auf_2 = 0 And Flag_kue_zu_2 = 0 Then
                          Flag_kue_auf_1 = Rolltime + Timecount
                          Elseif Rel_kue_auf = 1 And Flag_kue_zu_2 > 0 Then
                          Flag_kue_auf_2 = Rolltime - Flag_kue_zu_2
                          Flag_kue_auf_1 = Timecount + Flag_kue_auf_2
                          Flag_kue_zu_2 = 0
                       End If
    
                        If Rel_kue_auf = 0 And Flag_kue_auf_2 > 0 Then
                          Elseif Rel_kue_auf = 1 And Flag_kue_auf_2 > 0 Then
                          Flag_kue_auf_1 = Timecount + Flag_kue_auf_2
                          Flag_kue_auf_2 = 0
                        End If
    
                        If Rel_kue_auf = 0 And Flag_kue_auf_1 > 0 Then
                          Flag_kue_auf_2 = Timecount
                          Flag_kue_auf_2 = Flag_kue_auf_1 - Flag_kue_auf_2
                        End If
                      Twi_daten = 0
    
    '******************************************************************************* Rolladen Küche runter
            Case 22 : If Rel_kue_auf = 0 And Fenster_kue_zu = 0 Then
                      Toggle Rel_kue_zu
                     Fenster_kue_auf = 0
                      Else
                      Twi_daten = 0
                      Goto Ende
                      End If
    
                       If Rel_kue_zu = 1 And Flag_kue_zu_2 = 0 And Flag_kue_auf_2 = 0 Then
                          Flag_kue_zu_1 = Rolltime + Timecount
                          Elseif Rel_kue_zu = 1 And Flag_kue_auf_2 > 0 Then
                          Flag_kue_zu_2 = Rolltime - Flag_kue_auf_2
                          Flag_kue_zu_1 = Timecount + Flag_kue_zu_2
                          Flag_kue_auf_2 = 0
                       End If
    
                       If Rel_kue_zu = 0 And Flag_kue_zu_2 > 0 Then
                          Elseif Rel_kue_zu = 1 And Flag_kue_zu_2 > 0 Then
                          Flag_kue_zu_1 = Timecount + Flag_kue_zu_2
                          Flag_kue_zu_2 = 0
                          End If
                       If Rel_kue_zu = 0 And Flag_kue_zu_1 > 0 Then
                          Flag_kue_zu_2 = Timecount
                          Flag_kue_zu_2 = Flag_kue_zu_1 - Flag_kue_zu_2
                       End If
                     Twi_daten = 0
                      Ende:
    
    
     End Select
    
    If Rel_bad_auf = 1 And Timecount => Flag_bad_auf_1 Then                         'rücksetzen des Ansteuerrelaise für Fensterheber nach abgelaufener Zeit
       Reset Rel_bad_auf
       Flag_bad_auf_1 = 0                                                           'rücksetzen vom Zeitzähler
       Fenster_bad_offen = 1                                                        'wenn Fensterladen kompl. offen dann verhindern das nochmalig angesteuert werden kann
       Fenster_bad_zu = 0                                                           'nach dem Fensterladen kompl. runtergefahren war wird beim auffahren die nochmalige "Runterfahrsperre" zurück gesetzt
       End If
     If Rel_bad_zu = 1 And Timecount => Flag_bad_zu_1 Then
       Reset Rel_bad_zu
       Flag_bad_zu_1 = 0
       Fenster_bad_offen = 0
       Fenster_bad_zu = 1
       End If
     If Rel_kue_auf = 1 And Timecount => Flag_kue_auf_1 Then
       Reset Rel_kue_auf
       Flag_kue_auf_1 = 0
       Fenster_kue_auf = 1
       Fenster_kue_zu = 0
       End If
     If Rel_kue_zu = 1 And Timecount => Flag_kue_zu_1 Then
       Reset Rel_kue_zu
       Flag_kue_zu_1 = 0
       Fenster_kue_zu = 1
       Fenster_kue_auf = 0
       End If
    
    
    Loop
    End
    
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Subroutinen
    Counter_irq:
    
    Timer1 = Timer1vorgabe
    Incr Timecount                                                                  ' increment every sec the counter with 1
    If Timecount => 3600 Then                                                       ' 5400 here is the 1,50 std
       Timecount = 0
    
                                                                                ' wenn nicht dann lade StartWert in Timer1
    End If
    Return
    
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sensor 1 auslesen
    Temp_holen:
      1wreset                                                                       'reset
      1wwrite &H55                                                                  'match rom command
      1wwrite Id1(1) , 8                                                            'id von sensor 1
      1wwrite &HBE
    
      Ar1(1) = 1wread(2)
      T_ruekl = Makeint(ar1(1) , Ar1(2))
          T_ruekl = T_ruekl / 2                                                     'Ar(1)
    
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sensor2 auslesen
    
      1wreset                                                                       'reset
      1wwrite &H55                                                                  'match rom command
      1wwrite Id2(1) , 8                                                            'id von sensor 2
      1wwrite &HBE                                                                  'scratchpad lesen
    
     Ar2(1) = 1wread(2)
      T_vorl = Makeint(ar2(1) , Ar2(2))
          T_vorl = T_vorl / 2
    
    Return
    
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Warmwasserpumpe ein/ausschalten und senden der Warmwassertemperatur
    Rel_wasser_an:
     If T_vorl < T_ruekl Then
     Goto Rel_wasser_1
     End If
      T_ruekl_1 = T_vorl - T_ruekl                                                  'Abweichung zwischen Warmwassertemperatur und zurück geführte Umwälzwasser
      If T_ruekl < 30 And T_vorl >= T_ruekl And T_vorl < 45 Then
    
    Rel_wasser_1:
      Rel_wasser = 1
      If Pump_st_z = 0 Then
         Pump_st_z = 1
         Incr Pump_st
      End If                                                                        'wenn Umwälzwasser kleiner als 26°C und die Warmwassertemperatur größer ist dann Umwälzpumpe an
                                                                  ' (1.Byte = Temperatur;2.-4. = 0Bytes; 5.Senderadresse; 6.Byte Komando)
    Elseif T_ruekl_1 =< 15 And T_ruekl_1 => 0 And Rel_wasser = 1 Then
      Rel_wasser = 0
      Pump_st_z = 0
    End If
    
    Return
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fernbedienungsempfänger
    
    Fensterhoch_kue:
      Twi_daten = 2
    Return
                                                                    'PinB0 =>SV2/8
    Fensterrunter_kue:
      Twi_daten = 22
    Return
                                                                 'PinB2 =>SV2/6
    Fensterhoch_bad:
      Twi_daten = 1
    Return
                                                                    'PinC3 =>SV2/4
    Fensterrunter_bad:                                                              'PinC1 =>SV2/2
      Twi_daten = 11
    Return
    
    '###############################################################################
    bei den ich einige Subroutinen mit Gosub anspringe. Ich nutze in dem Programm ein I2C LCD. Nun ohne die Deklaration läuft das Prog über eine gewisse Zeit hin stabil und macht was es soll. Aber nach einigen Stunden (5....6...?) fällt das Display aus und zeigt nur wirres Zeug an, auch geht dann ein bestimmter Programmteil nicht mehr.
    Jetzt habe ich alle Unterroutinen mal deklariert und jetzt läuft's.

    => weshalb dies? Alle Variablen waren dimensioniert.
    Wer hat für mich eine Erklärung für mich und die Zukunft?

    Danke und Gruß MAT

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.11.2008
    Ort
    Kapfenberg
    Beiträge
    628
    Hallo!

    Dieselbe Frage stelle ich mir auch. Was ist der Vorteil einer SUB gegenüber eines mit GOSUB angesprungen Programmteils.

    Eine weitere Frage fällt mir gerade ein, wo wir schon dabei sind:
    Wenn ich in einer GOSUB oder SUB bin, wird dann bei einem Interrupt dieser ausgeführt oder die Unterroutine erst fertig ausgeführt?

    Danek für die Hilfe
    Thomas

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    17.09.2005
    Beiträge
    276
    Sub haben auch den Sinn das die immer besser lesbar sind.
    Mit Copy & Paste lassen sich so ganze Abschnitte leichter in andere Projekte einbinden.
    Der größte Vorteil sind Locale Variablen.
    Weiterer Vorteil sind Parameterübergaben.

    Nachteile sind.
    Die Programme laufen einen Hauch langsamer.
    Es wird mehr Stack benötigt.

    lg
    Gento

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    11.12.2008
    Beiträge
    6
    also ich schließe mich Gento an ...

    eine SUB ist sowas wie eine Funktion ohne Rückgabewert,
    in Delphi oder Pascal nennt man das Ganze Procedure,
    in C Void() ...

    Einen Sinn gibt es klarerweise dann, falls Du

    - Strukturierten Code einem Spaghetticode vorziehst...
    Ist auch leichter zu debuggen dann

    - Subs mit lokalen Variablen und Übergabeparameter in anderen
    Programmen wiederverwenden willst, ohne die Routiine gleich neu
    schreiben willst... dann bestens gleich schöne Bezeichnervariable
    wählen ...

    - größere Projekte angehen möchtest, denn damit isset das Ganze
    übersichtlicher.. [Meine Sources im Real Life bewegen sich so um die
    160 MB in einem aktuellen Langzeitprojekt ... ]

    Eine Sub spart in diesem Falle natürlich auch den reservierten Platz des
    Ergebniswertes einer Funktion...

    Je nach Intelligenz des Compilers könnte man dann externe Toolsamlungen/Units einbinden und diese dann im Hauptteil einbinden...
    Der Compiler sollte dann natürlich nur die verwendeten Routinen compilieren, mal sehen, bin erst seit 2 Tagen damit unterwegs...

    Spart eine Menge Zeit....

    @ TomEdl


    Zum Interrupt-Timer:

    dieser führt beim nächsten Rechenschritt des Prozessors seinen eigenen Code aus, unabhängig von der momentan ausgeführten Routine.. nach der Ausführung des Timercodes setzt er die eigentliche Routine fort...

    Soll der Timer das gerade nicht machen, dann würde ich einen einfachen Lockingmechanismus verwenden, etwa mit einer globalen Variable, um das OnTimerEvent wieder zu verlassen...

    Das Sub / Die Funktion würde dann eine globale Variable, beispielsweise ein Byte, um eins erhöhen und vor dem Verlassen der Routine dieses wieder um eins erniedrigen. (Die Erhöhung kann man auch durch andere Routinen schleifen und erhöhen bzw erniedrigen, dann könnte man den Timer anweisen, mittels Case Abfrage nicht nur auf 0 zu reagieren...)

    Im Timer würde ich dann diese Variable beispielsweise auf den Wert 0 überprüfen.
    Falls dieser 0 ist, dann wird der Timerteil ausgeführt, andernfalls die
    Routine verlassen...


    um

    lg

    Peter

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.11.2008
    Ort
    Kapfenberg
    Beiträge
    628
    Zitat Zitat von bytecook
    Zum Interrupt-Timer:
    Soll der Timer das gerade nicht machen, dann würde ich einen einfachen Lockingmechanismus verwenden, etwa mit einer globalen Variable, um das OnTimerEvent wieder zu verlassen...
    Doch, dass soll er unbedingt machen. Danke für deine ausführliche Antwort, du hast mir sehr weitergeholfen.

    Gruß
    Thomas

Berechtigungen

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