visual studio serial read ejemplo .net serial-port

.net - studio - Lo que podría afectar los valores devueltos por Serialport.Read()



serial port c# ejemplo (4)

Escribí una aplicación simple en C # 2.0 usando la clase .Net Framework 2.0 Serialport para comunicarme con una tarjeta controladora a través de COM1.

Recientemente se ha producido un problema si los bytes devueltos por el método Read son incorrectos. Devolvió la cantidad correcta de bytes, solo los valores fueron incorrectos. Sin embargo, una aplicación similar escrita en Delphi aún devolvió los valores correctos.

Utilicé Portmon para registrar la actividad en el puerto serie de ambas aplicaciones, comparé los dos registros y algunos ajustes menores (aparentemente) e intenté imitar la aplicación Delphi lo más cerca posible, pero fue en vano.

Entonces, ¿qué podría afectar los valores de bytes devueltos por el método Read?

La mayoría de las configuraciones entre las dos aplicaciones son idénticas.

Aquí hay una lista de las líneas que difieren en el registro de Portmon:

Aplicación Delphi:

IOCTL_SERIAL_SET_CHAR Serial0 ÉXITO EOF: dc ERR: 0 BRK: 0 EVT: 0 XON: 11 XOFF: 13
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 0 Replace: 0 XonLimit: 256 XoffLimit: 256 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI: -1 RM: 100 RC: 1000 WM: 100 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Máscara: RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR RING RX80FULL

Aplicación C #:

IOCTL_SERIAL_SET_CHAR Serial0 ÉXITO EOF: 1a ERR: 0 BRK: 0 EVT: 1a XON: 11 XOFF: 13 IOCTL_SERIAL_SET_HANDFLOW Serial0 EXITO Batido: 0 Reemplazar: 0 XonLimit: 1024 XoffLimit: 1024 IOCTL_SERIAL_SET_TIMEOUTS Serial0 ÉXITO RI: -1 RM: -1 RC: 1000 WM: 0 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Máscara: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING

ACTUALIZAR:

Los bytes devueltos correctos fueron: 91, 1, 1, 3, 48, 48, 50, 69, 66, 51, 70, 55, 52, 93 (14 bytes). El último valor es una suma de comprobación simple.

Los valores incorrectos devueltos fueron: 91, 241, 254, 252, 242, 146, 42, 201, 51, 70, 55, 52, 93 (13 bytes).

Como puede ver, corresponderán los primeros y los últimos cinco bytes devueltos.

El evento ErrorReceived indica que se produjo un error de trama, que podría explicar los valores incorrectos. Pero la pregunta es por qué SerialPort se encontraría con un error de encuadre cuando aparentemente la aplicación Delphi no lo hace.


¿Ha comprobado la configuración de la cantidad de bits de datos, bits de parada y paridad?

El bit de paridad es un tipo de mecanismo de detección de errores. Por ejemplo: si envía usando 7 bits de datos y un bit de paridad, el octavo bit se usará para detectar errores de inversión de bit. Si el receptor espera 8 bits de datos y no bits de paridad, el resultado será distorsionado.


Desafortunadamente, no mencionaste exactamente qué tipo de diferencias obtienes. ¿Es un personaje ocasional que es diferente o todos tus datos entrantes están distorsionados? Tenga en cuenta que los caracteres leídos a través de la función SerialPort.Read podrían ser cambiados por el sistema debido a la configuración de la propiedad SerialPort.Encoding . Esta configuración afecta la interpretación del texto entrante, ya que era texto en ASCII, Unicode, UTF8 o cualquier otro esquema de codificación que Windows usa para ''bytes sin formato'' a conversión de ''texto legible''.


Bueno, parece como si el problema se hubiera resuelto (al menos por el momento).

Aparentemente, un error de encuadre provocó la devolución de valores incorrectos. Escribí una aplicación VB6, usando el control MSComm, que funcionó bien, y comparé los archivos de registro generados por Portmon.

Recogí las siguientes diferencias

Aplicación VB6:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 1 Replace: 0 XonLimit: 256 XoffLimit: 256

Aplicación C #:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 0 Replace: 0 XonLimit: 1024 XoffLimit: 1024

Jugando con la configuración encontré que si configuro _serialPort.DtrEnable = true la aplicación C # genera la siguiente entrada de registro:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 1 Reemplazar: 0 XonLimit: 1024 XoffLimit: 1024

Eso pareció evitar el error de encuadre y la aplicación parece funcionar bien.


Si está leyendo en una matriz de bytes (por ejemplo, SerialPort.Read), debería obtener exactamente los bytes que está viendo en PortMon.

Si está convirtiendo a caracteres (SerialPort.ReadLine o SerialPort.ReadChar), los datos se codificarán utilizando la codificación actual (SerialPort.Encoding property), que explica las diferencias que está viendo.

Si desea ver caracteres con los mismos valores binarios que los bytes en el cable, una buena codificación para usar es Latin-1 como se describe en esta publicación .

Ejemplo:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")