È richiesto l'aiuto della porta seriale .NET, principalmente con i dati ricevuti in più "pacchetti"

StackOverflow https://stackoverflow.com/questions/891475

  •  23-08-2019
  •  | 
  •  

Domanda

Sono molto nuovo nell'invio di dati su una porta seriale tramite .net e ho notato, dopo aver implementato una controparte TCP, che non otterrei tutto così facilmente con seriale!

Quindi, per iniziare dall'alto, sono quasi arrivato con la mia implementazione della comunicazione seriale bidirezionale. Sono solo bloccato su alcune cose:-

  1. Le mie letture vengono suddivise tra più messaggi o ricevute come risposta frammentata sulla porta COM e non so di quali impostazioni potrei aver bisogno o come dovrei scrivere il codice in modo diverso per risolvere questo problema.Cosa potrebbe causare questo?Sto controllando il messaggio in corrispondenza di un punto di interruzione SerialPort_DataReceived.

Fondamentalmente i dati dovrebbero essere inviati come:

01: LS|DA090521|TI111043|q
02: PS|RN102|PTC|TA1040000|P#0|DA090521|TI111429|j

ma viene suddiviso (in posizioni casuali su ciascuna lettura richiesta)

01: LS|DA090521|TI111
02: 043|q
03: PS|RN102|PTC|TA1
04: 0000|P#0|DA090521|TI111429|j

- Alla domanda 1 è stata data risposta, grazie Chris W.e altri!Ora ho il messaggio che mi aspetto venga creato progressivamente dai frammenti (cercando STX, {msg body}, ETX) e quindi un'azione eseguita quando il messaggio è stato completamente creato e l'ho fatto funzionare con una coda thread-safe, molto felice .

.2.Sto ricevendo un "|" Simbolo attraverso la mia lettura quasi ogni ciclo, questo è dovuto a un comando che ho impostato erroneamente in qualche modo, un artefatto di comunicazione seriale o qualcosa che il dispositivo mi sta inviando?(Non credo, però, poiché la connettività Hyperterminal rivela che questo personaggio non viene inviato continuamente.)

.3.Puoi confermare che sto leggendo e scrivendo i dati correttamente nei rispettivi metodi.

Grazie ragazzi per aver preso in considerazione anche le mie altre due domande.

Codice rilevante come segue:

...
    //                          COM3,    9600,     None,   8,        One
    SerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits);
    if (SerialPort.IsOpen) SerialPort.Close();
    // SerialPort.RtsEnable = true; // Request-to-send
    // SerialPort.DtrEnable = true; // Data-terminal-ready
    SerialPort.ReadTimeout = 150; // tried this, but didn't help
    SerialPort.WriteTimeout = 150; // tried this, but didn't help
    SerialPort.Open();

    SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
}

void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // Process received data
    SerialPort sp = (SerialPort)sender;
    byte[] buffer = new byte[sp.BytesToRead];
    int bytesRead = sp.Read(buffer, 0, buffer.Length);

    // message has successfully been received
    message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
}

public bool SendMessage(string text)
{
    // Only send message if a client is connected
    if (SerialPort != null && SerialPort.IsOpen)
    {
        byte[] buffer = Encoding.ASCII.GetBytes(text);
        SerialPort.Write(buffer, 0, buffer.Length);
    }
}
È stato utile?

Soluzione

Le mie letture vengono suddivise in più messaggi

Questo è un comportamento normale, previsto, inevitabile.Può succedere anche con dati su TCP.Per l'interfaccia seriale è solo un flusso infinito di byte.È responsabilità della tua applicazione riconfezionare quei byte in pacchetti.

Se la posizione dei confini del pacchetto è importante e se non è possibile stabilire dove dovrebbero essere i confini del pacchetto osservando i dati ricevuti, potrebbe essere necessario ripensare il formato dei dati in modo da Potere dire dove sono i confini del pacchetto.

Sto ricevendo un "|" simbolo attraverso la mia lettura quasi ogni ciclo

Qual è il valore esadecimale di quel personaggio?Verifica se impostare il file Handshake proprietà a XOnXOff O RequestToSendXOnXOff migliora la situazione.

Altri suggerimenti

Al livello inferiore la porta seriale può decidere quando attivare l'evento di ricezione dei dati.Potrebbe decidere di farlo prima che arrivi il pacchetto "completo".Ma sembra che tu abbia un carattere terminatore nel set di dati previsto.Se è così puoi fare quanto segue (nota che ho cambiato l'assegnazione di SerialPort per evitare confusione di sintassi:

        p = new SerialPort(PortName, BaudRate, Prty, DataBits, SBits);
        p.NewLine = Terminator;

dove Terminatore è una stringa contenente i caratteri di terminazione.Quindi puoi utilizzare SerialPort.ReadLine() (e SerialPort.WriteLine() se applicabile).Questo potrebbe almeno aiutarti con il tuo primo problema.

Ho fatto molta programmazione della porta seriale Win32, ma solo un po' con .NET, quindi prendi il mio consiglio con le pinze.

Le mie letture vengono suddivise tra più messaggi o ricevute come risposta frammentata sulla porta COM e non so di quali impostazioni potrei aver bisogno o come dovrei scrivere il codice in modo diverso per risolvere questo problema.

Come altri hanno già detto, questo è perfettamente normale.A seconda del tipo di attrezzatura presente sul lato DCE, potrebbe essere necessario effettuare il reimballaggio da solo.Non sono sicuro del tipo di attrezzatura a cui sei collegato, quindi non posso dire molto di più.

Se desideri ottenere più dati, puoi provare quanto segue:

  • modificando la proprietà System.Int32 ReceivedBytesThreshold
  • utilizzando l'I/O sincrono e specificando un numero fisso di byte da leggere anziché la ricezione basata sugli eventi

Sto ricevendo un "|" Simbolo attraverso la mia lettura quasi ogni ciclo, questo è dovuto a un comando che ho impostato erroneamente in qualche modo, un artefatto di comunicazione seriale o qualcosa che il dispositivo mi sta inviando?(Non credo però, poiché la connettività iperterminale rivela che questo personaggio non viene inviato continuamente.)

Se sei curioso di sapere cosa sta succedendo oltre il limite, dai un'occhiata PortMon da SysInternals, un'app gratuita che scruterà la tua porta COM mentre trasferisci i dati sulla linea.Sembra tecnico, ma in realtà devi solo guardare i comandi IRP_MJ_WRITE e IRP_MJ_READ e sulla riga vedrai la lunghezza in byte e i dati inviati via cavo.Con questo dovresti essere in grado di dire se il problema è l'oggetto .NET SERIALPORT o se il dispositivo sta effettivamente inviando "|" sopra la linea.

Puoi confermare che sto leggendo e scrivendo correttamente i dati nei rispettivi metodi.

Sembra appropriato per il metodo di ricezione dei dati basato sugli eventi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top