[vb.net] Serial Port korrekt Daten empfangen

OP #1814523
Lesenswert?

Hallo liebe Forengemeinde,

ich hätte eine kleine Problemstellung und bitte um Denkanstöße:

Ich besitze einen "Funkempfänger" auch "Scanner" genannt. Diese besitzt 
eine serielle Schnittstelle. Der Datenverkehr ist recht gut erforscht: 
http://www.freqofnature.com/index.php?m=Software&p=Uniden%20Protocols

Ich möchte den Scanner mit Hilfe meiner Software bedienen können. Dies 
klappt auch soweit (Write-Kommandos funktionieren tadellos) nur leider 
der Empfang der vom Scanner gesendeten Informationen bereitet Probleme.

Schreiben:

SerialPort1.Write("LCD1" & vbCrLf)

funktioniert bestens.

Darauf sollte der Scanner antworten, das tut er auch

Lesen tue ich (sicherlich falsch) so:

For i = 0 To 40 Step 1
            Label2.Text = Label2.Text & Chr(SerialPort1.ReadByte)
        Next

leider hängt das Programm nach einiger Zeit und ich bekomme eine 
Fehlermeldung. Dies passiert primär dann, wenn ich "zu schnell" 
hintereinander Kommandos sende.

Ich wollte nun fragen was ich tun muss, damit das alles korrekt abläuft.
Hier ein paar Stichworte die mir einfallen:

- Time out (beim Serial Port) was ist das, welchen Sinn ergibt es und 
wie sollte ich es konfigurieren.

- Sende / Empfangspuffer leeren ?

- Gibt es sowas wie einen Interrupt zum Empfangen oder ein Flag die man 
regelmäßig auslesen könnte ?

- Wie stelle ich sicher, dass keine weiteren Kommandos gesendet werden 
bevor alles ausgelesen ist ?

Vielen Dank

Gruß
Gast #1825126
Lesenswert?

Hallo Zusammen,

Ich habe mich erst kürzlich mit dem selben Thema beschäftigt.

Anbei ein Beispiel zum lesen der Daten.

Achtung: Wenn der 'input' in ein Control auf Deiner Form geschrieben 
werden soll, muss mit einem Delegaten gearbeitet werden!

------------------------------------------------------------------------
Imports System.IO.Ports
Public Class Form1

Private WithEvents MySP As New SerialPort

Private Sub Form1_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
MySP = New SerialPort("COM1")
'Hier könnten noch weitere Einstellungen wie StopBits usw. eingestellt 
werden.
MySP.BaudRate = 19200
MySP.Open()
MySP.DtrEnable = True
MySP.RtsEnable = True
End Sub

Private Sub MySP_DataReceived(ByVal sender As Object, ByVal e As
System.IO.Ports.SerialDataReceivedEventArgs) Handles MySP.DataReceived
Dim input As String
input = MySP.ReadLine
MsgBox(input)
End Sub
End Class
-----------------------------------------------------------------------

Gruss
lorefach
OP #1835161
Lesenswert?

Soo also ich hab's mir jetzt selbst zusammengesucht. Für meine Probleme 
fand ich folgende Lösung:
1
Dim Empfang As String
2
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
3
        SerialPort1.PortName = "COM9"
4
        SerialPort1.BaudRate = 19200
5
        SerialPort1.DataBits = 8
6
        SerialPort1.ReadTimeout = -1
7
        SerialPort1.StopBits = IO.Ports.StopBits.One
8
        SerialPort1.Parity = IO.Ports.Parity.None
9
        SerialPort1.ReceivedBytesThreshold = 1
10
        SerialPort1.Open()
11
    End Sub

dann
1
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
2
        Try
3
            Do Until Empfang = vbCrLf
4
                'Empfang &= SerialPort1.ReadChar
5
                Empfang &= Convert.ToChar(Convert.ToInt16(SerialPort1.ReadChar.ToString))
6
            Loop
7
            SerialPort1.DiscardInBuffer()
8

9
        Catch ex As Exception
10

11
        End Try
12
    End Sub

Ist natürlich alles doppelt und dreifach gemoppelt (der Type-Cast) und 
warscheinlich so das schlimmste was ich machen konnte. Auch das Try ist 
eher behelfsmäßig. Funktioniert aber für meine Anforderungen besten !

Vielen Dank an alle die versucht haben zu Helfen


Gruß =)
#1837326
Lesenswert?

Lehrmann Michael schrieb:

>             Do Until Empfang = vbCrLf
>                 'Empfang &= SerialPort1.ReadChar
>                 Empfang &=
> Convert.ToChar(Convert.ToInt16(SerialPort1.ReadChar.ToString))
>             Loop
>             SerialPort1.DiscardInBuffer()

Bei sowas leuten bei mir sofort alle Warnglocken. Man Discarded keinen 
Buffer, wenn man nicht weiß was drinnen steht und wie vollständig das 
ist. Eigentlich sollte sich jede Empfnagsroutine jedes einzelne Byte 
ansehen und entscheiden was es damit machen will. Die Gefahr ist 
riesengroß, dass dein Gegenüber schon den nächsten Datensatz auf den Weg 
gebracht hat, von dem ein Teil auch schon angekommen ist, den du dann 
mit dem Discard entsorgst. Der nächste Empfang steigt dann mitten in die 
laufende Übertragung ein und schon ist das Chaos perfekt.
Gast #1838911
Lesenswert?

Hallo Michael,

Ich sehe nicht ein, wieso du nicht "SerialPort1.readline" anwendest...
Aus meiner Sicht sollte das selbe Resultat entstehen - einfach 
Einfacher! ;-)

Anyhow - Viel Spass damit!

Gruss
lorefach

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren