PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART, zeitlicher Ablauf Subprogramme



mollyman
13.06.2013, 20: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, 21: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, 05: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, 10: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, 11: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, 16: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, 17: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.