2009-03-13 26 views
12

Ho provato a utilizzare Readline() e i dati vengono eliminati, ho provato a utilizzare Read() ma non sono sicuro di come avere un metodo di prova degli errori, dato che potrei ottenere diversi pacchetti uno dopo l'altro e non ho modo di sapere che ci sarà un altro pacchetto in arrivo. Tra i pacchetti BytesToRead è 0, quindi non posso usarlo. Quando leggi dati nel buffer hai un timer o metti il ​​thread in stop per consentire l'arrivo di tutti i pacchetti?Lettura dalla porta seriale in C#

Sono perso. Non so cosa provare dopo.

Devo dire che non ho alcuna garanzia che la stringa proveniente dalla porta seriale venga terminata con \ n o \ r o \ r \ n. Ho semplicemente bisogno di un modo stupido per leggere TUTTI i pacchetti che arriveranno dalla bilancia quando l'utente preme su PRINT.

Qualcuno ha risposto qui con l'idea che mi piaceva - in attesa di un certo periodo di tempo per tutti i pacchetti, ma hanno cancellato la loro risposta. Qualche possibilità che potresti ri-postare?

risposta

23

Hai provato ad ascoltare l'evento DataRecieved della classe SerialPort?

public class MySerialReader : IDisposable 
{ 
    private SerialPort serialPort; 
    private Queue<byte> recievedData = new Queue<byte>(); 

    public MySerialReader() 
    { 
     serialPort = new SerialPort(); 
     serialPort.Open(); 

     serialPort.DataReceived += serialPort_DataReceived; 
    } 

    void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e) 
    { 
     byte[] data = new byte[serialPort.BytesToRead]; 
     serialPort.Read(data, 0, data.Length); 

     data.ToList().ForEach(b => recievedData.Enqueue(b)); 

     processData(); 
    } 

    void processData() 
    { 
     // Determine if we have a "packet" in the queue 
     if (recievedData.Count > 50) 
     { 
      var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue()); 
     } 
    } 

    public void Dispose() 
    { 
     if (serialPort != null) 
      serialPort.Dispose(); 
    } 
+0

Non v'è alcuna garanzia che i dati effettivamente letto sulla porta seriale è serialPort.BytesToRead. Suggerirei di verificare il valore di ritorno di serialPort.Read. – Roger

10

Abbiamo fatto lo stesso processo qualche tempo fa.

L'unico modo per leggere "pacchetti" è avere un'idea di dove l'inizio e la fine di essi sono in un flusso.

Da msdn:

Poiché i dati buffer di classe SerialPort, e il flusso contenuto nella proprietà BaseStream non, i due potrebbero essere in conflitto su quanti byte sono disponibili per la lettura. La proprietà BytesToRead può indicare che ci sono byte da leggere, ma questi byte potrebbero non essere accessibili allo stream contenuto nella proprietà BaseStream perché sono stati memorizzati nella classe SerialPort.

Abbiamo utilizzato un thread di backround (è possibile utilizzare un BackgroundWorker) per leggere i dati in un buffer. Se non è possibile impostare in modo affidabile il carattere di terminazione utilizzando la proprietà SerialPort.Newline (perché, ad esempio, varia!), Sarà necessario implementare il proprio sistema di rilevamento dei pacchetti perché non sarà possibile utilizzare il blocco SerialPort.Readline () metodo.

Si può semplicemente leggere in un buffer di byte utilizzando SerialPort.Read() (o una stringa utilizzando il metodo SerialPort.ReadExisting()) e generare un evento quando si rileva un pacchetto valido nei dati. Nota che Read() (e presumo ReadExisting()) svuota il buffer di SerialPort, quindi dovrai conservare i dati da qualche altra parte.

Se si imposta SerialPort.ReadTimeout, è possibile gestire TimeoutException e disporre di un modo semplice per gestire le condizioni in cui il dispositivo non sta trasmettendo. Questo è un buon modo per ripristinare il rilevamento dei pacchetti se si utilizza un numero fisso di byte o qualche altro schema non terminato. (usa SerialPort.DiscardInBuffer() su un timeout se non hai bisogno di pacchetti parziali).

Buona fortuna

+0

da quello che so non esiste uno schema di rilevamento. Proverò a crearlo - ad attendere alcuni millisecondi prima dell'elaborazione per consentire l'arrivo dei pacchetti. Non vedo altre alternative. Stavo usando ReadLine() per 6 mesi fino a quando qualcuno ha notato un bug in cui i dati vengono eliminati. – sarsnake

+0

Utilizziamo molte scale industriali e normalmente è possibile impostare il carattere di terminazione nel dispositivo. Hai il controllo sui dispositivi di input in modo da poterlo guardare? ReadLine è * molto * più facile :) –

+0

facciamo: \ n (ascii 13). Quello che sto cercando di fare è leggere i dati byte per byte con SerialPort.ReadByte() e cercare 13. Sto anche andando a impostare SerialPort.NewLine su \ n (lo ho impostato su \ r \ n adesso .... hmmm, forse questo è il problema Grazie! – sarsnake

3

Dal byte possono venire in qualsiasi momento, il buffering dei dati in entrata è fondamentale.Così si dovrebbe

  1. buffer dei dati in arrivo
  2. scansione buffer per trovare dati completi
  3. rimuovere i dati utilizzati dal buffer

Mi chiedo solo se si continua ad avere problemi con la porta seriale In tal caso, ho sviluppato un linguaggio di programmazione della porta seriale in C# e credo che risolva quasi tutti i problemi che tutti incontrano.

Volete dare un'occhiata e provarlo? Per esempio; puoi tamponare i dati in arrivo dalla porta seriale come segue e fare facilmente operazioni con le stringhe.

state Init 
    // define a global variable 
    our $BUFFER = ""; 
    jump(Receive); 
end state 

state Receive 
    recv(); 
    $len = length($DATA_PACKET); 
    if("$len > 0") { 
    $BUFFER += $DATA_PACKET; 
    call(Parser); 
    } 
end state 

state Parser 
    // check if buffer matchs regular expression pattern 
    if(match($BUFFER, "(?<WILLDELETE>.*?<STX>(?<DATA>.*?)<ETX>(?<CHECKSUM>[0-9A-F]{2}))")) { 
    // Received complete data 
    $lenData = length($WILLDELETE); 
    $BUFFER = remove($BUFFER, 0, $lenData); 

    // Do operations with the other parsed fields. $DATA and $CHECKSUM in this example. 
    } 
end state 

Il progetto è disponibile gratuitamente su sourceforge e se avete domande, non esitate a chiedere.

Project Homepage

Download Link

Problemi correlati