| |
VB.NET - Ein- und UmsteigerRe: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Bibobernie | Datum: 29.06.12 11:50 |
| Aufgrund der 5KB Beschränkung hier der fehlende Teil des Codes in dem die ankommenden Befehle ausgewertet werden. Eventuell ist hier ja auch der Wurm drin:
Private Sub Wertübergabe()
If CGlobal.EmpfangenZ1 <> String.Empty Then
If Auswertung(CGlobal.EmpfangenZ1) Then
LstBoxAntw.Items.Add("1.Zelle, " & Date.Now.ToString( _
"HH:mm:ss") & ": " & CGlobal.EmpfangenZ1)
Else
MessageBox.Show("Übertragungsfehler")
End If
CGlobal.EmpfangenZ1 = String.Empty
End If
If CGlobal.EmpfangenZ2 <> String.Empty Then
If Auswertung(CGlobal.EmpfangenZ2) Then
LstBoxAntw.Items.Add("2.Zelle, " & Date.Now.ToString( _
"HH:mm:ss") & ": " & CGlobal.EmpfangenZ2)
Else
MessageBox.Show("Übertragungsfehler")
End If
CGlobal.EmpfangenZ2 = String.Empty
End If
End Sub
''' <summary>
''' Funktion Hilft die Empfangen Texte auszuwerten. Dabei werden die
' Leerzeichen zwischen den Werten entfernt und die Messwerte entsprechend
' zugeordnet.
''' </summary>
''' <param name="Empfang">Empfangener String vom Serialport</param>
''' <returns>Rückgabewert als Boolean (Empfang OK)</returns>
''' <remarks></remarks>
Private Function Auswertung(ByVal Empfang As String) As Boolean
Dim Text() As String, j As Boolean = True
Empfang = Empfang.Replace(" ", " ")
Empfang = Empfang.Replace(" ", " ")
Empfang = Empfang.Trim(Chr(10), " "c) 'Führende und abschließende
' Leerzeichen und LF-Zeichen entfernen
Text = Empfang.Split(" "c)
If Text.Length < 1 Then
Return False
Exit Function
End If
Select Case UCase(Text(0))
Case "U0"
Try
CGlobal.Messwerte.Zellsp.Add(CDbl(Text(1)))
Catch ex As Exception
CGlobal.Messwerte.Zellsp.Add(-9999)
End Try
Case "U1"
Try
CGlobal.Messwerte.Temp.Add(Val(CDbl(Text(1))))
Catch ex As Exception
CGlobal.Messwerte.Temp.Add(-9999)
End Try
Case "U4"
Try
CGlobal.Messwerte.O2.Add(Val(CDbl(Text(1))))
Catch ex As Exception
CGlobal.Messwerte.O2.Add(-9999)
End Try
Case "U5"
Try
CGlobal.Messwerte.ElektStrom.Add(Val(CDbl(Text(1))))
Catch ex As Exception
CGlobal.Messwerte.ElektStrom.Add(-9999)
End Try
Case "U6"
Try
CGlobal.Messwerte.Zellsp.Add(Val(CDbl(Text(1))))
Catch ex As Exception
CGlobal.Messwerte.Zellsp.Add(-9999)
End Try
Try
CGlobal.Messwerte.Temp.Add(Val(CDbl(Text(2))))
Catch ex As Exception
CGlobal.Messwerte.Temp.Add(-9999)
End Try
Try
CGlobal.Messwerte.ElektStrom.Add(Val(CDbl(Text(3))))
Catch ex As Exception
CGlobal.Messwerte.ElektStrom.Add(-9999)
End Try
Case Else
j = False
End Select
Return j
End Function Ahnungsloser ahnungsloser... | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Bibobernie | Datum: 29.06.12 15:16 |
| Hab jetzt weiter rumprobiert aber bekomm es einfach nicht hin. Hab mit den Timings gespiel (Timer und Timeout) sowie die laufzeit mit der Stopwatch aufgenommen. Egal ob mit oder ohne Timeout-Fehler, ein aufruf dauert immer rund 33ms.
Verwirrend ist auch die tatsache das, sobald ich den Timer auf 500ms stelle und nur einen Befehl fahre (zweiten auskommentiert) die Laufzeit auf über 600ms ansteigt und vereinzelt Timeouts auftauchen. Wenn ein aufruf im schnitt nicht länger als 33ms dauert, wieso kann ich dann mit dem Timer nicht auf 500ms oder drunter gehen?
Sorry für die vielen Fragen aber ich bin hier echt am rumrätseln und weiß einfach nicht weiter :/
Ahnungsloser ahnungsloser... | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Bibobernie | Datum: 30.06.12 17:01 |
| Kann mir denn keiner weiterhelfen?
Ich hab das ganze Problem mal mit einem neuen Form nachgebaut damit ein bissl Übersichtlichkeit reinkommt. Auf dem Form existieren nun nur noch zwei button und eine listbox. Klicke ich den einen Button wird Befehl u4 geschickt, klicke ich den zweiten button werden die befehle u6 und u4 geschickt. Die jeweiligen antworten sollen dann in die Listbox kommen.
Das senden und empfangen funktioniert bei beiden bottons. Allerdings empfange ich bei dem Button mit den zwei befehlen nur die Antwort auf den jeweils ersten Befehls. Wie kann ich das hin bekommen das ich beide Antworten erhalte?
Ich habe zwischendurch auch schon versucht zwischen den beiden Befehlen ein System.Threading.Thread.Sleep(500) einzufügen, dieses brachte allerdings auch keinen Erfolg...
Imports System.IO.Ports
Public Class Form1
Private Delegate Sub DelegateSub()
Private Empfang As New DelegateSub(AddressOf InListeEintragen)
Private s As String
Private Sub BtnEin_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles BtnEin.Click
SerialPort1.Write("U4" & vbCr)
End Sub
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As _
System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
SerialPort1.Close()
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As _
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
SerialPort1.Close()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
With SerialPort1 'Einstellungen Serieller
' Port
.BaudRate = 9600
.DataBits = 8
.Parity = IO.Ports.Parity.None
.Handshake = Handshake.None
.StopBits = IO.Ports.StopBits.One
.Open()
End With
End Sub
Private Sub BtnZwei_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles BtnZwei.Click
SerialPort1.Write("U6" & vbCr)
SerialPort1.Write("U4" & vbCr)
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As _
System.IO.Ports.SerialDataReceivedEventArgs) Handles _
SerialPort1.DataReceived
s = SerialPort1.ReadTo(Chr(13))
Invoke(Empfang)
End Sub
Private Sub InListeEintragen()
ListBox1.Items.Add(s)
s = String.Empty
End Sub
End Class Ahnungsloser ahnungsloser... | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 30.06.12 17:10 |
| Ohne jetzt die Geräet zu kennen. Hast du mal Breakpoints gesetzt und geschaut welche Abfolge bei den 2 Signalen abläuft? Mich interessiert da der zeitliche Ablauf: Sende Befehl 1, erhalte Antwort auf 1, Sende Befehl 2, bekomme keine Antwort ? Vielleicht solltest du erst auf das Event warten, welches die Antwort zu Befehl 1 darstellt und erst danach den zweiten Befehl abschicken. Dies könntest du testweise direkt im Event nach der erfolgreichen Antwort auf Befehl 1 machen. Wie verhält es sich da?
Beitrag wurde zuletzt am 30.06.12 um 17:11:21 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 30.06.12 18:10 |
| Ja sowas dachte ich mir schon. Ich hab auch schonmal mit nem selbsprogrammierten MicroController und ner Anwendung was gebastelt, ist aber schon ne Weile her. Ich schätze mal, wenn du den zweiten Befehl schickst, der MC immer noch dabei ist, den ersten abzuarbeiten, und du keine Antwort bekommst. Dahin zielte auch meine Frage ab.
Da ich in deinem Code nicht sehe, wann du was machst, hätte ich es mal so probiert:
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As _
System.IO.Ports.SerialDataReceivedEventArgs) Handles _
SerialPort1.DataReceived
s = SerialPort1.ReadTo(Chr(13))
Invoke(Empfang)
'Prüfen ob das gewünschte Empfangen wurde, wenn ja:
sendeBefehl2()
End Sub Wenn das nicht funktioniert, dann hast du immernoch die Möglichkeit eine kurze Pause einzulegen (Threading.Thread.sleep()).
Ich würde auch nochmal deine Empfangsmethode überprüfen. Vielleicht kommen die Befehle nicht zusammen an und du verpasst etwas. Daher -> alles Empfangene in einen Puffer bei dir laden, danach auswerten!
Hoffe ich konnte helfen . | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Preisser | Datum: 30.06.12 20:07 |
| Hallo,
mir sind auch einige Sachen bei deinem Code aufgefallen.
Du behandelst ja das "DataReceived"-Event des SerialPorts, welches in einem anderen Thread (z.B. aus einem Thread-Pool) aufgerufen werden kann. In dem Ereignishandler jedoch benutzt du dann die Methode ReadTo(String), die wie die anderen Read()-Methoden allerdings blockieren kann (solange, dis die angegebene Zeichenfolge gelesen wurde).
Aber was passiert, wenn zuerst z.B. nur ein einziges Byte ankommt, welches nicht die angegebe Trennungszeichenfolge enthält? In dem Fall würde ja die ReadTo()-Methode blockieren. Wenn danach allerdings weitere Daten ankommen, müsste das DataReceived-Event wieder ausgelöst werden, allerdings würde sich der andere Thread immer noch in dem Eventhandler befinden. Nun könnte es z.B. passieren, dass ein weiterer Thread aus dem Threadpool verwendet wird, um das DataReceived-Event auszulösen, wobei wiederrum die ReadTo()-Methode des SerialPorts aufgerufen wird, was zu Fehlern führen könnte.
Man müsste sich den Quellcode der SerialPort-Klasse genauer ansehen, um nachvollziehen zu können, was in solchen Situationen passieren könnte, weshalb es vermutlich einfacher wäre, es gar nicht erst dazu kommen zu lassen und z.B. einfach einen anderen Thread zu starten, der in einer Schleife die ReadTo-Methode aufruft (so wie es auch in den MSDN-Beispielen zum SerialPort dargestellt ist).
Ein anderer Punkt ist, dass du eine Variable in der Form dazu benutzt, den empfangenen String zu speichern und dann im GUI-Thread wieder auszulesen. Normalerweise aber sollte man die empfangenen Daten im Aufruf der Methode übergeben, denn nur dafür werden sie ja gebraucht. Ansonsten kann es beispielsweise zu Race Conditions kommen, wenn man nicht entsprechend synchronisiert. Hier wird zwar durch die Verwendung von "Invoke" (statt "BeginInvoke") sichergestellt, dass "s" nicht vom Lesethread überschrieben werden kann, solange der GUI-Thread noch mit der Ausführung der "InListeEintragen"-Methode beschäftigt ist; trotzdem sollte man soetwas vermeiden.
Hier ein Beispiel für einen separaten Lesethread:
Private serialPortReadThread As Thread
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) _
Handles MyBase.Load
SerialPort1.Open()
'Lesethread starten
serialPortReadThread = New Thread( _
Sub()
ReadSerialPort(SerialPort1)
End Sub)
serialPortReadThread.Start()
End Sub
Private Sub ReadSerialPort(sp As SerialPort)
Try
Do While True
Dim s As String = sp.ReadTo(ChrW(13))
Invoke( _
Sub()
InListeEintragen(s)
End Sub)
Loop
Catch ex As ThreadInterruptedException
' Thread wurde interrupted.
End Try
End Sub
Private Sub InListeEintragen(s As String)
ListBox1.Items.Add(s)
If Not ok Then
SendZwei(s)
End If
End Sub
Private Sub Form1_FormClosed(sender As System.Object, e As _
System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
' Lesethread unterbrechen, sodass er beendet wird
serialPortReadThread.Interrupt()
End Sub
Beitrag wurde zuletzt am 30.06.12 um 20:14:03 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 30.06.12 20:15 |
| Ja ich hatte mir damals auch ein extra Thread zum lesen des Ports angelegt, wie Preisser bereits beschrieben hatte ... wohl aus Unwissenheit über das Vorhandensein eines Events, welches ausgelöst wird, wenn Daten empfangen wurden . Dies funktionierte reibungslos.
Zudem habe ich dann meist nur Events rausgehauen, welcher der eigentliche Datenparser entgegennahm und bei erfolgreicher Überprüfung weitergab. So kannst du auch deine eigentliche Logik bissl besser von deiner Oberfläche trennnen. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 06.07.12 15:31 |
| Wenn man mal in der MSDN nachliest, steht dort auch, dass nicht für jedes empfangene Byte ein Event geraised wird. (http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx)
Vielleicht befolgst den dort vorgeschlagenen Weg und schaust mit der bytesToRead Methode nach, ob noch mehr im Puffer ist. Deine Empfangsanalyse war ja eher suboptimal! Zum Beispiel schaust du ja nur bis zu dem Zeichen (s = SerialPort1.ReadTo(Chr(13))). Wenn danach nochwas im Puffer liegt, verpasst du das einfach.
Sollte das nicht helfen, dann nutze bitte den hier im Thread schon gebrachten Vorschlag, eines extra Empfangs-Thread, welcher garantiert keine Bytes verpasst! Wenn du dabei Hilfe brauchst, einfach nochmal melden.
Wenn du es frickeln willst, dann füll deine gesendetet Zeichen mit Füllzeichen auf, damit das Event immer kommt. Ich würde aber eher zum Thread raten. Damit habe ich auch immer gute Ergebnisse erziehlt.
Beitrag wurde zuletzt am 06.07.12 um 15:33:07 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 06.07.12 16:54 |
| Hm also das loopen an der Stelle sorgt nicht dafür. Was macht eigentlich das DoEvents an der Stelle da? Das sollte man vermeiden.
Ich bin mir jetzt nicht sicher, da du ja immerwieder das SerialPort Objekt Byval übergibst, ob das nicht ständig neue Instanzen erzeugt und daher alles langsamer wird. Kann auch gut sein, das dieses Objekt da prinzipiell immer mit Byref übergeben wird, ich gestehe eine Wissenslücke . Jedenfalls würde es nicht schaden da Byref zu machen, da du ja eh immer mit dem Objekt weiterarbeitest.
Beachte mal den Speicherverbrauch bei deiner Anwendung, Steigt dieser dauerhaft an, haut irgendwas nicht hin.
Und wegen der Performanceprobleme, das ist bekannt. Hier mal eine Bibliothek die es wohl besser machen soll. Einfach mal testen.
http://www.codeproject.com/Articles/28572/SerialPort-NET-Top-10-Reasons-Why-You-Deserve-Bett
Beitrag wurde zuletzt am 06.07.12 um 16:58:23 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Preisser | Datum: 06.07.12 17:00 |
| Hallo,
den Teil des Codes verstehe ich nicht ganz:
Private Sub ReadSerialPort(ByVal sp As SerialPort)
Try
'...
Catch ex As System.TimeoutException
Application.DoEvents()
ReadSerialPort(sp) 'Darf ich hier loopen? Verursacht das
' eventuell die Probs?
'...
End Try
End Sub Warum catcht du eine TimeoutException, rufst dann aber wieder ReadSerialPort rekursiv auf (und noch dazu DoEvents, das in .Net eigntlich niemals verwendet werden sollte )?
Wenn du kein Timeout beim Lesen haben willst, warum stellst du dann überhaupt eins ein? (Die Standardeinstellung für ReadTimeout ist SerialPort.InfiniteTimeout, wodurch gar kein Timeout auftritt).
Beitrag wurde zuletzt am 06.07.12 um 17:00:31 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Preisser | Datum: 06.07.12 17:12 |
| Hallo,
xirton schrieb:
Zitat: | |
Ich bin mir jetzt nicht sicher, da du ja immerwieder das
SerialPort Objekt Byval übergibst, ob das nicht ständig neue
Instanzen erzeugt und daher alles langsamer wird. Kann auch
gut sein, das dieses Objekt da prinzipiell immer mit Byref
übergeben wird, ich gestehe eine Wissenslücke . Jedenfalls
würde es nicht schaden da Byref zu machen, da du ja eh immer
mit dem Objekt weiterarbeitest. | |
SerialPort ist eine Klasse, d.h. ein Referenztyp. Diese Instanzen (Objekte) werden immer im Heap angelegt (nicht im Stack bzw. im Speicherbereich der Variable) und man gibt nur Referenzen auf das Objekt weiter (so wie Pointer). (Eigentlich sind das aber Grundlagen... )
Wenn ein Argument einer Funktion als ByRef deklariert wird, wird dagegen eine Referenz auf die Referenz des Objektes übergeben (in VB.Net ist da die Schreibweise leider nicht so deutlich, aber in C# muss man Argumente, die als "ref" (ByRef) gekennzeichnet sind, ebenfalls mit "ref" übergeben, also z.B.
DoSomething(ref myObj, ref bla); statt DoSomething(myObj, bla); . Dies macht deutlich, dass die Funktion die Referenz ändern kann - deshalb sollte nur dann ByRef bei Referenztypen verwendet werden, wenn es tatsächlich notwendig ist, dass die aufgerufene Funktion die Referenz ändern kann - was es aber nur selten ist.
Beitrag wurde zuletzt am 06.07.12 um 17:13:57 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: xirton | Datum: 06.07.12 17:14 |
| Joar ich dachts mir schon, kurzer Blackout meinerseits . Danke! | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Bibobernie | Datum: 08.07.12 00:01 |
| So ich hab nun mal verschiedenes ausprobiert und hab mich jetzt erst einmal für die Variante ohne Threads entschieden weil diese ja ganz gut funktionierte.
Das Auswerteproblem welches ich mit den kurzen strings hatte lag an einer globalen Variablen in welche ich die empfangenen Stringteile einlagerte:
''' <summary>
''' Sub fügt empfangene Teilstrings aus Empfangs-Event zusammen.
''' </summary>
''' <param name="Buffer">Teilstrings aus Empfang</param>
''' <remarks></remarks>
Private Sub Fügen(ByVal Buffer As String)
Empfang = Empfang + Buffer 'Hier wird der empfangene Text
' zusammengefügt
If Buffer.Contains(Chr(13)) Then
Verarbeitung(Empfang, SerPort) 'Und hier an die Auswertung
' übergeben
Empfang = String.Empty 'Bei sehr kurzen
' Empfangsereignissen kommt es nicht zum löschen der globalen
' Variable. Die Sub beginnt einfach wieder von vorn.
End If
End Sub Dadurch wurde der neu empfangene Text einfach in die Variable geschrieben bevor diese gelöscht wurde. Somit hatte ich dann auch die Auswerteprobleme. Ich habe nun bereits in der sub "Verarbeitung" das löschen der globalen Variable veranlasst und alles funktioniert sehr gut. Nun erhalte ich auch sehr kurze Strings problemlos über die Schnittstelle.
Aber ich habe trotzdem noch ein kleines Problem bzw. ne frage:
Und zwar kommt es vor das ich mehrere Befehle über die Schnittstelle schicken muss. Das erledige ich bis jetzt ungefähr so:
Serport.write(Befehl1)
system.threading.thread.sleep(100) 'Kurze Wartezeiten damit die Schnittstelle/
' das Gerät sich nicht verschluckt;).
serport.write(Befehl2)
system.threading.thread.sleep(100)
serport.write(Befehl3) Das funktioniert an sich prima. Nun möchte ich jedoch eine Bedingung einbauen das z.B. Befehl2 nur gesendet wird wenn Befehl1 eine bestimmte Antwort gegeben hat. Habe versucht das wie folgt zu realisieren:
Serport.write(Befehl1)
system.threading.thread.sleep(100)
If Antwort = "OK" then
serport.write(Befehl2)
else
serport.write(Befehl3)
end if Hier habe ich aber scheinbar die Rechnung ohne VB gemacht. Das abarbeitet nämlich erst mal fluffig meinen Code mit den Befehlen ab und verarbeitet das Empfangsevent scheinbar nicht sofort. Nun hab ich die Vermutung das das ganze an dem Sleep liegt da das System in der Zeit ja nur Faul rumhängt und erst nach der Zeitspanne mit werkeln und Empfangen beginnt. Meine Frage dementsprechend ob jemand ne elegantere Lösung für solche Wartezeiten kennt bzw. ne Lösung für mein Problemchen mit dem Empfang parat hätte.
Ahnungsloser ahnungsloser... | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Preisser | Datum: 08.07.12 03:20 |
| Hallo,
Bibobernie schrieb:
Zitat: | |
Private Sub Fügen(ByVal Buffer As String)
Empfang = Empfang + Buffer 'Hier wird der empfangene Text
' zusammengefügt
If Buffer.Contains(Chr(13)) Then
Verarbeitung(Empfang, SerPort) 'Und hier an die Auswertung
' übergeben
Empfang = String.Empty 'Bei sehr kurzen
' Empfangsereignissen kommt es nicht zum löschen der globalen
' Variable. Die Sub beginnt einfach wieder von vorn.
End If
End Sub | |
Hmm, war das Zeichen mit dem Wert 13 nicht das Trennzeichen? Müsste dann nicht eigentlich der String jeweils an der Stelle dieses Zeichens gesplittet werden? Sonst könnte es ja passieren, dass mehrere Nachrichten gleichzeitig im Puffer liegen, oder dass eine Nachricht noch nicht vollständig übertragen wurde und der Rest erst beim nächsten Receive-Ereignis eintritt. (Das Splitten bzw. Lesen bis zum nächsten Vorkommen des Zeichens wird aber ja eigentlich bereits durch die blockierende SerialPort.ReadTo(String)-Methode erledigt, wenn man sie z.B. in einem separaten Thread aufruft... )
Übrigens sollte man eigentlich immer ChrW() statt Chr() verwenden; außer, es ist wirklich notwendig, ein Zeichen nicht durch den Unicode-Wert, sondern den ANSI-Wert des lokal verwendeten Zeichensatzes zu erzeugen.
Zitat: | | Hier habe ich aber scheinbar die Rechnung ohne VB gemacht. Das abarbeitet nämlich erst mal fluffig meinen Code mit den Befehlen ab und verarbeitet das Empfangsevent scheinbar nicht sofort. | |
Naja, wenn eine Kommunikation in zwei Richtungen geht, hat man einen Sende- und einen Empfangskanal, auf denen man meistens parallel senden und empfangen kann.
Wenn du z.B. im GUI-Thread etwas sendest, dann pausierst und wieder etwas sendest, bedeutet das nicht automatisch, zwischen den zwei Sendebefehlen eine Antwort empfangen wird; sondern es wird eben gesendet, und unabhängig davon wird irgendwann später, wenn das Gerät eine Antwort schickt, das Empfangsereignis ausgelöst (bzw. die blockierende Read()-Methode kehrt zurück).
Du könntest also z.B. erst einen Befehl schicken und dann warten, bis eine Antwort durch das Receive-Ereignis kommt. Wenn dies der Fall ist, kannst du die empfangene Antwort auswerten und entsprechend den nächsten Befehl schicken.
Oder, wenn du ein Request/Response-Prinzip verwenden willst, könntest du einen separaten Thread verwenden, der zuerst immer einen Befehl schickt und dann auf eine Antwort wartet, z.B. so in der Art:
Private Sub HandleConnection(sp As SerialPort)
Try
' 1. Befehl senden
sp.Write("ERSTER_BEFEHL" & ChrW(13))
' 1. Antwort auslesen
Dim firstAnswer As String = sp.ReadTo(ChrW(13))
If firstAnswer = "ABC" Then
' 2. Befehl senden
sp.Write("ZWEITER_BEFEHL" & ChrW(13))
' 2. Antwort auslesen
Dim secondAnswer As String = sp.ReadTo(ChrW(13))
End If
' usw.
Catch ex As ThreadInterruptedException '...
End Try
End Sub In dem Fall wird nur 1 Thread (statt 2) sowohl für das Senden als auch das Empfangen verwendet, wenn man erwarten kann, dass nach dem Senden eines Befehls immer eine Antwort erfolgt.
Beitrag wurde zuletzt am 08.07.12 um 03:40:33 editiert. | |
Re: Mehrere Befehle über RS232 senden/empfangen | | | Autor: Preisser | Datum: 08.07.12 14:06 |
| Hallo,
Bibobernie schrieb:
Zitat: | | Naja, ich empfange die Daten derzeit nicht über den Thread
sondern über ein Datarecive in dem ich alle existierenden
Zeichen einlese und an die Methode zum zusammenfügen
übergebe. Daher prüfe ich dort ob ein Empfangener String auch
Chr(13) enthält. Ich dachte zuerst auch das ich durch das
"If Buffer.Contains(Chr(13)) Then" unter Umständen
ein oder mehrere Zeichen übersehen könnt. Da das Datarecive
aber nach jedem Zeichen diese Methode aufzurufen scheint
hatte ich bis jetzt damit keine Probleme. | |
Ja, vermutlich funktioniert es meistens, weil das Gerät immer eine Nachricht absendet und eine Pause macht, bevor es eine weitere absendet - dann wird man das einzelne Paket meistens auch als solches empfangen. Trotzdem könnte es aber auch passieren, wenn das Gerät zwei Nachrichten schnell hintereinander abschickt, dass diese dann "in einem Rutsch", also in einem Paket, ankommen (oder, wenn eine Nachricht sehr groß ist, dass diese in mehreren Paketen ankommt).
Es handelt sich ja beim SerialPort um eine stream-basierte Kommunikation, nicht message-basiert, sodass man sich selbst darum kümmern muss, die einzelnen Nachrichten korrekt zu interpretieren.
Deshalb müsste man eigntlich immer beim Trennzeichen (13) den String splitten, und falls am Ende kein Trennzeichen stand, den hinteren Teil wieder an den Puffer anhängen, damit dieser für das nächste Datenpaket noch zur Verfügung steht. Wie gesagt, die SerialPort.ReadTo(...)-Methode erledigt das aber bereits .
Zitat: | | An sowas hatte ich auch gedacht allerdings habe ich ja zusätzlich das Datarecive-Event aktiviert. Wenn ich dann versuche im Thread mittels ReadTo die Antwort auszulesen kommt es da nicht zu eventuellen Redundanzen? Also das ich zuerst z.B. firstAnswer einlesen kann aber das Datarecive Event danach auch noch einmal den Empfangenen String bearbeitet. Oder gibt es eine Möglichkeit solche Events temporär, z.B. für die Dauer einer Methode, zu deaktivieren? | |
Naja, wenn du die Methode mit dem separaten Stream verwendest, darfst du eben einfach keinen Handler zum DataReceived-Event hinzufügen. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats Neu! sevPopUp 2.0
Dynamische Kontextmenüs!
Erstellen Sie mit nur wenigen Zeilen Code Kontextmenüs dynamisch zur Laufzeit. Vordefinierte Styles (XP, Office, OfficeXP, Vista oder Windows 8) erleichtern die Anpassung an die eigenen Anwendung... Weitere Infos
|