Domanda

Ho scritto una semplice app in C # 2.0 utilizzando la classe Serialport .Net Framework 2.0 per comunicare con una scheda controller tramite COM1.

Di recente si è verificato un problema se i byte restituiti dal metodo Read non sono corretti. Restituiva la giusta quantità di byte, solo i valori erano errati. Un'app simile scritta in Delphi ha comunque restituito i valori corretti.

Ho usato Portmon per registrare l'attività sulla porta seriale di entrambe le app, confrontando i due log e lì dove alcune (apparentemente) minori impostazioni diverse e ho provato a imitare l'app Delphi il più vicino possibile, ma senza risultati.

Quindi, cosa potrebbe influenzare i valori dei byte restituiti dal metodo Read?

La maggior parte delle impostazioni tra le due app sono identiche.

Ecco un elenco delle linee che differivano nel registro di Portmon:

App Delphi:

  

IOCTL_SERIAL_SET_CHAR Seriale0 SUCCESSO EOF: dc   ERR: 0 BRK: 0 EVT: 0 XON: 11 XOFF: 13
  IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Agitazione: 0   Sostituisci: 0 Limite Xon: 256    XoffLimit: 256 IOCTL_SERIAL_SET_TIMEOUTS Seriale0 SUCCESS RI: -1    RM: 100 RC: 1000 WM: 100 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 Maschera SUCCESS:   RXCHAR RXFLAG TXEMPTY CTS DSR RLSD   BRK ERR RING RX80FULL

App C #:

  

IOCTL_SERIAL_SET_CHAR Seriale0 SUCCESSO EOF: 1a   ERR: 0 BRK: 0 EVT: 1a XON: 11 XOFF: 13   IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Agitazione: 0   Sostituisci: 0 Limite Xon: 1024    XoffLimit: 1024 IOCTL_SERIAL_SET_TIMEOUTS Seriale0 SUCCESS RI: -1    RM: -1 RC: 1000 WM: 0 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask:   RXCHAR RXFLAG CTS DSR RLSD BRK ERR   ANELLO

UPDATE:

I byte restituiti corretti erano: 91, 1, 1, 3, 48, 48, 50, 69, 66, 51, 70, 55, 52, 93 (14 byte). L'ultimo valore è un semplice checksum.

I valori errati restituiti erano: 91, 241, 254, 252, 242, 146, 42, 201, 51, 70, 55, 52, 93 (13 byte).

Come puoi vedere, il primo e gli ultimi cinque byte restituiti corrispondono.

L'evento ErrorReceived indica che si è verificato un errore di frame, che potrebbe spiegare i valori errati. Ma la domanda è: perché SerialPort dovrebbe riscontrare un errore di inquadratura quando l'app Delphi apparentemente no?

È stato utile?

Soluzione

Beh, sembra che il problema sia stato risolto (almeno per il momento).

Apparentemente un errore di inquadratura ha causato la restituzione di valori errati. Ho scritto un'app VB6, usando il controllo MSComm, che ha funzionato bene e ho confrontato i file di registro generati da Portmon.

Ho raccolto le seguenti differenze

App VB6:

  

IOCTL_SERIAL_SET_HANDFLOW Serial0   SUCCESSO Agita: 1 Sostituisci: 0   XonLimit: 256 XoffLimit: 256

App C #:

  

IOCTL_SERIAL_SET_HANDFLOW Serial0   SUCCESSO Agita: 0 Sostituisci: 0   XonLimit: 1024 XoffLimit: 1024

Giocando con le impostazioni ho scoperto che se avessi impostato _serialPort.DtrEnable = true l'app C # genera la seguente voce di registro:

  

IOCTL_SERIAL_SET_HANDFLOW Serial0   SUCCESSO Agita: 1 Sostituisci: 0   XonLimit: 1024 XoffLimit: 1024

Ciò sembrava impedire l'errore di inquadratura e l'applicazione sembra funzionare correttamente.

Altri suggerimenti

Hai controllato le impostazioni per numero di bit di dati, bit di stop e parità?

Il bit di parità è una specie di meccanismo di rilevamento degli errori. Ad esempio: se si invia utilizzando 7 bit di dati e un bit di parità, l'ottavo bit verrà utilizzato per rilevare errori di inversione dei bit. Se il ricevitore si aspetta 8 bit di dati e nessun bit di parità, il risultato sarà confuso.

Sfortunatamente non hai menzionato esattamente il tipo di differenze che ottieni. È un personaggio occasionale diverso o tutti i tuoi dati in arrivo sono confusi? Si noti che i caratteri letti tramite la funzione SerialPort.Read potrebbero essere modificati dal sistema a causa dell'impostazione di proprietà SerialPort.Encoding . Questa impostazione influisce sull'interpretazione del testo in arrivo in quanto era testo in ASCII, Unicode, UTF8 o qualsiasi altro schema di codifica utilizzato da Windows per la conversione da "byte grezzi" a "testo leggibile".

Se stai leggendo in un array di byte (es: SerialPort.Read) dovresti ottenere esattamente i byte che vedi su PortMon.

Se stai convertendo in caratteri (SerialPort.ReadLine o SerialPort.ReadChar), i dati verranno codificati usando la codifica corrente (proprietà SerialPort.Encoding), che spiega le differenze che stai vedendo.

Se vuoi vedere caratteri con gli stessi valori binari dei byte sul filo, una buona codifica da usare è Latin-1 come descritto in questo post .

Esempio:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top