Forum: PC-Programmierung [vb.net] Serial Port korrekt Daten empfangen


von Lehrmann M. (ubimbo)


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ß

von Sam .. (sam1994)


Lesenswert?

Also in c# gibts da ein Event das RecieveByte (oder so) heißt. 
Vielleicht gibts das in VB auch (in c# könnte ich dir konkret sagen wie 
das geht. Basic hab ich so meine Probleme.

von lorefach (Gast)


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

von Lehrmann M. (ubimbo)


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ß =)

von Karl H. (kbuchegg)


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.

von lorefach (Gast)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.