Problém se čtením ze sériového portu   otázka

VB.NET, I/O operace

K PC mám skrze USB připojené míchací zařízení. V PC mám nainstalovaný nejnovější ovladač zařízení, který vytvoří virtuální COM port. Zařízení bez problémů reaguje na příkazy odeslané z aplikace (Visual Basic 2013). Nejsem ale schopen data ze zařízení načíst (viz funkce "CtiData").

Pro stejné zařízení jsem napsal aplikaci ve VB6, která načítala data ze sériového portu (via komponentu MSComm 6.0). Při načítání dat ale aplikace obvykle do 15 načítacích cyklů zatuhla. Proto jsem se ji rozhodl přepsat do VB.NET 2013 s pomocí System.IO.Portsts.SerialPorts.

Čtení vždy skončí ve větvi "Catch ex As TimeoutException", jako by na vstupu nebyla žádná data. Zkoušel jsem načítat pomocí ".ReadLine()", ale výsledkem byl opět timeout.

Zde je kód:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      TextESC = Chr(13) & " " & Chr(10)     ' Ukončovací sekvence znaků

      ' Načte dostupné COM porty 
      Dim Portnames As String() = System.IO.Ports.SerialPort.GetPortNames
      If Portnames Is Nothing Then
         MsgBox("Žádné COM porty.")
         Me.Close()
      End If
      cboPort.Items.AddRange(Portnames)
      cboPort.Text = Portnames(0)
      ' Parametry spojení
      With serM
         If .IsOpen Then .Close()
         .BaudRate = 9600
         .Parity = IO.Ports.Parity.Even
         .DataBits = 7
         .StopBits = 1
         .ReadTimeout = 1000
         .PortName = cboPort.Text
      End With
   End Sub

   Private Sub cmdCti_Click(sender As Object, e As EventArgs) Handles cmdCti.Click
      lblO.Text = CtiData("IN_PV_3")
   End Sub

   Private Sub cmdStart_Click(sender As Object, e As EventArgs) Handles cmdStart.Click
      serM.PortName = cboPort.Text
      Prikaz("START_4")   ' Spustit motor
      Prikaz("OUT_SP_4" & " " & Trim(txtOtacky.Text))   ' Otáčky
   End Sub

   Private Sub cmdStop_Click(sender As Object, e As EventArgs) Handles cmdStop.Click
      serM.PortName = cboPort.Text
      Prikaz("STOP_4")   ' Zastavit motor
   End Sub

   ' Pošle příkaz
   Private Sub Prikaz(TextPrikazu As String)
      With serM
         If Not .IsOpen Then .Open()
         .Write(TextPrikazu & TextESC)
      End With
      serM.Close()
   End Sub

    ' (Ne)Čte data ze sériového portu
   Function CtiData(TextPrikazu As String) As String
      Dim returnStr As String = ""

      Try
         With serM
            If Not .IsOpen Then .Open()
            .DiscardInBuffer()
            .Write(TextPrikazu & TextESC)
         End With
         ' Až sem to skočí
         Do

            Dim Incoming As String = serM.ReadChar()   ' serM.ReadLine()
            If Incoming Is Nothing Then
               Exit Do
            Else
               'Console.WriteLine(Incoming)
               returnStr &= Incoming
            End If
         Loop
      Catch ex As TimeoutException
         returnStr = "ErrTimeout"
      Finally
         If serM IsNot Nothing Then serM.Close()
      End Try


      Return returnStr
   End Function

Kde dělám chybu? Ve VB6 jsem problém čtení rozlousknul za pár minut, s VB.NET2013 na řešení nemůžu přijít. Prošel jsem spoustu návodů, ale bez úspěchu. Můžete mi poradit, jak načíst data?

Poznámka: Zařízení používá místo standardního ukončení vstupu/výstupu (vbCrLf) posloupnost vbCr & " " & vbLf.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Se čtením ze sériového portu jsem měl vždy problémy.

Největších úspěchů se mi podařilo dosáhnout s tímto: http://serialportstream.codeplex.com/

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Zkuste pro čtení použít metodu ReadExisting(), která je neblokující, a čekání na data si realizovat ve vlastní režii.

Inspirovat se můžete v příkladu zde:

http://www.dotnetportal.cz/forum/tema/26...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

V C#:

SerialPort SPort = new SerialPort("COM5");
SPort.BaudRate = 9600;
            
SPort.DataBits = 8;
SPort.Parity = Parity.None;
SPort.StopBits = StopBits.One;
SPort.Handshake = Handshake.None;
            
SPort.DataReceived += SPort_DataReceived;
SPort.Open();

Console.WriteLine("Pro ukonceni stisknout libovolnou klavesu!");
Console.ReadKey();
if (SPort.IsOpen) {
    SPort.Close();
}

static void SPort_DataRecieved (object sender, SerialDataReceivedEventArgs e)
{
    string dataFromSerPort = ((SerialPort)sender).ReadLine();
    Console.WriteLine(dataFromSerPort);
}

Je to vynatek z kodu, ale je tam to podstatne. Jede v pohode - nikdy nesklamal ;)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback