Archiv verlassen und diese Seite im Standarddesign anzeigen : UART, zeitlicher Ablauf Subprogramme
mollyman
13.06.2013, 21:18
Hallo 
ich habe ein kleines Verständnisproblem, wobei mir Mr Google und Tante SuFu auch nicht helfen konnten.
Es geht um die Reihenfolge in der das Main und die Sub ablaufen.
Folgende Konstellation:
Über die UART kommen Nachrichten rein die mit CR enden. In der Main loop wird das erste Zeichen der Nachricht per if-Schleife ausgewertet und danach in die jeweiligen Sub gesprungen.
Frage 1.
Wenn ich das bisher richtig verstanden habe wird die Main-Loop immer wieder ausgeführt , sie macht also so lange keine neues Telgramm kommt immer wider die Verarbeitung der alten Nachricht. 
Sinnvoll ist das bestimmt nicht, wäre es denn schädlich ?
Kann man das sinnvoll verhindern
Frage 2
Wie und in welcher zeitlichen Reihefolge werden die Subs bearbeitet und wie wirkt sich das aus:
Folgendes Beispiel: 
Es kommen 2 Nachrichten direkt hintereinander rein, die den gleichen Nachrichtenkenner haben also in die gleiche subroutine laufen
Beispiel
Nachricht 1 kommt herein. durch das CR wird die Sub für die uart angsprochen. die ändert den Inhalt der Variabelen für den nachrichten inhalt, die Mainloop verzweigt in die subroutine mit byval wird das telegramm für die Routine für das sub mit übergeben. Die Subroutine fängt an zu arbeiten.
Während die subroutine noch arbeitet wird die direkt folgende nachricht mit cr abgeschlossen.
Sie ändert damit die variabele für die nachricht 
Sub Serial0charmatch()
Input Telegramm Noecho
End Sub Serial0charmatch()
und dann ?????
A: Geht es dann in der unterbrochenen Subroutine weiter, bis diese abgearbeitet ist und springt dann in die Main-Loop zurück und stößt das gleiche Sub mit der neuen Variabelen an
oder 
B: springt das Sub(mit dem input) in die Mainloop und würde dann damit eine nur halb verarbeitete 1. Nachricht hinterlassen.
Wenn normalerweise Fall B eintritt, gibt es eine Möglichkeit es so zu machen, das es doch zu Fall a wird ?
Das Thema ist bei mir halt besonders wichtig, da nicht nur alle Sekunde eine Nachricht kommt, sondern auch dazwischen und oft auch 2 Nachrichten direkt in Folge.
(Ein bestimmter Event beim Sender führt zu 2 unterschiedlichen Nachrichten des gleichen Typs)
Danke im voraus
peterfido
13.06.2013, 22:14
Hast Du mehr Code? 
Es lässt sich nicht pauschal sagen, dass die Mainloop ständig / immer wieder durchlaufen wird. Das passiert nur, wenn die subs auch wieder sauber zurückspringen.
Serialcharmatch und Co nutze ich nicht. Ich arbeite immer mit ischarwaiting(). Für ein passendes Beispiel bräuchte ich mindestens deine Auswerteroutine.
mollyman
14.06.2013, 06:05
ja klar:
Hier ein Ausschnitt
$regfile = "M32def.dat"
$crystal = 4000000
$hwstack = 32
$swstack = 10
$framesize = 40
$baud = 9600
 
Config Serialin = Buffered , Size = 60 , Bytematch = 013    ' Serielles Input
'Ausgänge:
Zeit_segmente Alias Portc.7                                 ' Ausgang für die Uhr
Rennz Alias Portc.6                                         ' Ausgang für die verbleibende Restzeit
Licht_5 Alias Portc.5                                       ' Ausgang für Lampe 5
Licht_4 Alias Portc.4                                       ' Ausgang für Lampe 4
Licht_3 Alias Portc.3                                       ' Ausgang für Lampe 3
Licht_2 Alias Portc.2                                       ' Ausgang für Lampe 2
Licht_1 Alias Portc.1                                       ' Ausgang für Lampe 1
Do
Ttyp = Mid(telegramm , 2 , 1)
If Ttyp = Lebensz Then
Call Zeit(telegramm)
End If
If Ttyp = Platzt Then
Call Platz(telegramm)
End If
 
Loop
End
 
Sub Serial0charmatch()
Input Telegramm Noecho
End Sub Serial0charmatch()
 
Zeit:
Uz_std10 = Mid(telegramm , 5 , 1)
Uz_std1 = Mid(telegramm , 6 , 1)
Uz_min10 = Mid(telegramm , 7 , 1)
Uz_min1 = Mid(telegramm , 8 , 1)
Uz_sek10 = Mid(telegramm , 9 , 1)
Uz_sek1 = Mid(telegramm , 7 , 1)
 
If Uz_std10 = "0" Then
   Uz1 = Seg_array(10)
   Else
   Uz1 = Seg_array(uz_std10)
End If
If Uz_std1 = "0" Then
    Uz2 = Seg_array(10)
    Else
    Uz2 = Seg_array(uz_std1)
    End If
If Uz_min10 = "0" Then
    Uz3 = Seg_array(10)
    Else
    Uz3 = Seg_array(uz_min10)
End If
If Uz_min1 = "0" Then
   Uz4 = Seg_array(10)
   Else
   Uz4 = Seg_array(uz_min1)
End If
If Uz_sek10 = "0" Then
   Uz5 = Seg_array(10)
   Else
   Uz5 = Seg_array(uz_sek10)
End If
If Uz_sek1 = "0" Then
   Uz6 = Seg_array(10)
   Else
   Uz6 = Seg_array(uz_sek1)
End If
LA1 = Mid(telegramm , 5 , 1)
LA2 = Mid(telegramm , 6 , 1)
LA3 = Mid(telegramm , 7 , 1)
LA4 = Mid(telegramm , 8 , 1)
LA5 = Mid(telegramm , 9 , 1)
If LA1 = "1" Then
   Licht_1 = 1
   Else
   Licht_1 = 0
End If
If LA2 = "1" Then
   Licht_2 = 1
   Else
   Licht_2 = 0
End If
If LA3 = "1" Then
   Licht_3 = 1
   Else
   Licht_3 = 0
End If
If LA4 = "1" Then
   Licht_4 = 1
   Else
   Licht_4 = 0
End If
If LA5 = "1" Then
   Licht_5 = 1
   Else
   Licht_5 = 0
End If
Shiftout Data_channel , Clock_channel , Uz1
   Shiftout Data_channel , Clock_channel , Uz2
   Shiftout Data_channel , Clock_channel , Uz3
   Shiftout Data_channel , Clock_channel , Uz4
   Shiftout Data_channel , Clock_channel , Uz5
   Shiftout Data_channel , Clock_channel , Uz6
   Pulseout zeit_strobe_port , zeit_strobe_pin , 10000
Return
mollyman
14.06.2013, 11:08
erstmal danke peterfido (https://www.roboternetz.de/community/members/28466-peterfido)
hatte ich ganz vergessen.
Habe mir mal das ISCHARWAITING angesehen.
grundsätzlich wäre es glaube ich interessant weil ich die Nachricht im UART Puffer bleibt und ich diese nur dann abrufe, wenn ich auch die neue Nachricht verarbeiten kann.
Allerdings ist immer die Rede von einem Zeichen. Bei mir sind es aber bis zu 60 Zeichen pro Nachricht.
peterfido
14.06.2013, 12:41
Irgendwie fehlt mir da was. Beispielcode sollte compilierfähig sein.
Dein Code würde ich etwa so umsetzen (Fehlende Typen einfach angenommen, natürlich ungestestet)):
$regfile = "M32def.dat"
$crystal = 4000000
$hwstack = 32
$swstack = 10
$framesize = 40
$baud = 9600
Dim Position As Byte
Dim B As Byte
Dim Uz(6) As Byte
Dim Telegramm(60) As Byte
Dim Ttype As Byte At Telegramm + 1 Overlay
Dim Uz_std10 As Byte At Telegramm + 4 Overlay               ' = Mid(telegramm , 5 , 1)
Dim Uz_std1 As Byte At Telegramm + 5 Overlay                ' = Mid(telegramm , 6 , 1)
Dim Uz_min10 As Byte At Telegramm + 6 Overlay               ' = Mid(telegramm , 7 , 1)
Dim Uz_min1 As Byte At Telegramm + 7 Overlay                ' = Mid(telegramm , 8 , 1)
Dim Uz_sek10 As Byte At Telegramm + 8 Overlay               ' = Mid(telegramm , 9 , 1)
Dim Uz_sek1 As Byte At Telegramm + 9 Overlay                ' = Mid(telegramm , 7 , 1)
La1 alias Uz_std10
La2 Alias Uz_std1
La3 Alias Uz_min10
La4 Alias Uz_min1
La5 Alias Uz_sek10
Const Lebensz = 5                                           '???
Const Platzt = 6                                            '???
Dim Seg_array(10) As Byte                                   '???
Config Serialin = Buffered , Size = 60                      ', Bytematch = 013    ' Serielles Input
'Ausgänge:
Zeit_segmente Alias Portc.7                                 ' Ausgang für die Uhr
Rennz Alias Portc.6                                         ' Ausgang für die verbleibende Restzeit
Licht_5 Alias Portc.5                                       ' Ausgang für Lampe 5
Licht_4 Alias Portc.4                                       ' Ausgang für Lampe 4
Licht_3 Alias Portc.3                                       ' Ausgang für Lampe 3
Licht_2 Alias Portc.2                                       ' Ausgang für Lampe 2
Licht_1 Alias Portc.1                                       ' Ausgang für Lampe 1
Zeit_strobe_port Alias Portb                                '???
Zeit_strobe_pin Alias 0                                     '???
Data_channel Alias Portb.1
Clock_channel Alias Portb.2                                 '???
Do                                                          '???
   If Ischarwaiting() = 1 Then
      Gosub Empfangen
   End If
Loop
End
Empfangen:
   B = Inkey()
   If B = 13 Then
      Gosub Auswerten
      Position = 0
   Else
      Incr Position
      Telegramm(position) = B
   End If
Return
Auswerten:
   If Ttype = Lebensz Then
     If Uz_std10 = 48 Then
        Uz(1) = Seg_array(10)
     Else
        Uz(1) = Seg_array(uz_std10)
     End If
     If Uz_std1 = 48 Then
         Uz(2) = Seg_array(10)
         Else
         Uz(2) = Seg_array(uz_std1)
         End If
     If Uz_min10 = 48 Then
         Uz(3) = Seg_array(10)
         Else
         Uz(3) = Seg_array(uz_min10)
     End If
     If Uz_min1 = 48 Then
        Uz(4) = Seg_array(10)
        Else
        Uz(4) = Seg_array(uz_min1)
     End If
     If Uz_sek10 = 48 Then
        Uz(5) = Seg_array(10)
        Else
        Uz(5) = Seg_array(uz_sek10)
     End If
     If Uz_sek1 = 48 Then
        Uz(6) = Seg_array(10)
        Else
        Uz(6) = Seg_array(uz_sek1)
     End If
'     LA1 = Mid(telegramm , 5 , 1)
'     LA2 = Mid(telegramm , 6 , 1)
'     LA3 = Mid(telegramm , 7 , 1)
'     LA4 = Mid(telegramm , 8 , 1)
'     LA5 = Mid(telegramm , 9 , 1)
     If LA1 = 49 Then
        Licht_1 = 1
     Else
        Licht_1 = 0
     End If
     If La2 = 49 Then
        Licht_2 = 1
     Else
        Licht_2 = 0
     End If
     If La3 = 49 Then
        Licht_3 = 1
     Else
        Licht_3 = 0
     End If
     If La4 = 49 Then
        Licht_4 = 1
     Else
        Licht_4 = 0
     End If
     If La5 = 49 Then
        Licht_5 = 1
     Else
        Licht_5 = 0
     End If
     Shiftout Data_channel , Clock_channel , Uz(1)
     Shiftout Data_channel , Clock_channel , Uz(2)
     Shiftout Data_channel , Clock_channel , Uz(3)
     Shiftout Data_channel , Clock_channel , Uz(4)
     Shiftout Data_channel , Clock_channel , Uz(5)
     Shiftout Data_channel , Clock_channel , Uz(6)
     Pulseout Zeit_strobe_port , Zeit_strobe_pin , 10000
   Elseif Ttype = Platzt Then
      nop
   End If
Return
mollyman
14.06.2013, 17:37
Ersteinmal Danke für die Antwort
Soorry wegen der nicht compilierfähigkeit.
Da der Code bereits über 4k groß ist, wollte ich ihn nicht komplett einstellen.
Kurz vorab.
Es gibt 4 Verschiedene Nachrichten unterschieden werden sie am 2. Zeichen der Nachricht. Für jeden Nachrichtentyp hatte ich eine eigene Subroutine vorgesehen:
die Typen sind Lebenszeichen ( L ) Platzierung ( P) Initialisierung (I) und Bestround (B). Dafür die Variabelen Platzt und Lebensz
Const Lebensz = 5                                           '???
Const Platzt = 6                                            '???
Müsste es dann nicht so heißen:
Const Lebensz = 76    ' Ascii Nummer für L                                     
Const Platzt = 80        'Ascii Nummer für P
In jedem der Telegramme sind eine Reihe an Informationen  enthalten. 
Hier am Beispiel L:
Telegrammtyp, Aktuelle Uhrzeit; Restzeit, Lampe 1 an oder aus, Lampe 2 an oder aus,Lampe 3 an oder aus,Lampe 4 an oder aus,Lampe 5 an oder aus.
Die variabelen Fangen deshalb bei mir auch so an:
LA = Lampe
UZ = Uhrzeit
RZ = restzeit
wen ich das richtig verstehe, hast du die String-Werte aus dem String durch deren ASCII Code nummer ersetzt.
Das ist nicht ganz richtig, der Fehler liegt aber bei mir
La2 Alias Uz_std1
La3 Alias Uz_min10
La4 Alias Uz_min1
La5 Alias Uz_sek10
Die Lampen haben keine Gemeinsamkeit mit den Uhrzeiten
Aber da ich noch nicht ganz fertig bin und Teile des Protokolls noch in der Abstimmung sind, waren noch nicht alle Platzangaben in den Telegrammen richtig gesetzt.
Zeit_strobe_port Alias Portb                                '???
Zeit_strobe_pin Alias 0                                     '???
Data_channel Alias Portb.1
Clock_channel Alias Portb.2 
Insgesamt habe ich 13 Blöcke mit sieben Segement Anzeigen
Alle 13 Blöcken hängen am gleichen Data out port und am gleichen Clock Port, der Strobe Port wird je Block gesetzt ( Uhrzeit und Restzeit sind ein block -> Zeit_Strobe)
Dim Seg_array(10) As Byte                                   '???
Das ist das Array in dem steht welche 8 Binärzeichen  für die Siebensegmentanzeige an die Schiebregister gesendet werden sollen.
Quasi die Übersetzungsliste Dezimal-Zahl zu Siebensegmentanzeige. Da keine Nachgeschaltete Logik dahinter ist muss ich das hier im Programm machen.
Glaube ich zumindest.
Gruß Martin
Ich habe hier gerade nicht den kompletten Code zur hand. Ich baue das ein und schreibe das nochmal hier.
peterfido
14.06.2013, 18:10
Klingt so, als ob Du  meine Vorgehensweise erkannt hast. ;)
Wenn möglich, arbeite ich mit Overlays, was hier gut geht. Spart umkopiererei. "Strings" der Länge 1 werte ich normal als byte aus. Spart in dem Beispiel hier die ganzen MIDs. Zumal das Vergleichen von Strings mehr Zeit benötigt.
 
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.