visual studio serialport1_datareceived serialdatareceivedeventargs serial received event ejemplo datareceived data c# serial-port

studio - using system io ports c#



¿Cómo uso el evento dataReceived del objeto de puerto SerialPort en C#? (7)

Por cierto, puede usar el siguiente código en su controlador de eventos:

switch(e.EventType) { case SerialData.Chars: { // means you receives something break; } case SerialData.Eof: { // means receiving ended break; } }

Estoy intentando crear una pequeña aplicación para recopilar datos recibidos de un sensor externo conectado a COM10. He creado con éxito un pequeño objeto de consola C # y una aplicación que abre el puerto y transmite datos a un archivo durante un período de tiempo fijo utilizando un for-loop.

Me gustaría convertir esta aplicación para usar el evento dataReceived para transmitir en su lugar. Después de leer los 5 mejores consejos de SerialPort , todavía no puedo hacerlo y no sé lo que me estoy perdiendo. Reescribí la aplicación de la consola para que todo el código esté en Main y se pegue debajo. ¿Puede alguien ayudarme a aclararme por qué el controlador de eventos port_OnReceiveDatazz no se está llamando aunque sé que el hardware está enviando datos al puerto?

Gracias

Azim

PD: gracias a @Gabe , @Jason Down y @abatishchev por todas las sugerencias. Estoy perplejo y parece que no puedo hacer que funcione el controlador de eventos. Tal vez tiene algo que ver con el dispositivo. Puedo vivir con solo leer el puerto en un hilo y transmitir los datos directamente al archivo.

Código

namespace serialPortCollection { class Program { static void Main(string[] args) { const int bufSize = 2048; Byte[] buf = new Byte[bufSize]; //To store the received data. SerialPort sp = new SerialPort("COM10", 115200); sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler sp.Open(); sp.WriteLine("$"); //Command to start Data Stream // Wait for data or user input to continue. Console.ReadLine(); sp.WriteLine("!"); //Stop Data Stream Command sp.Close(); } // My Event Handler Method private static void port_OnReceiveDatazz(object sender, SerialDataReceivedEventArgs e) { SerialPort spL = (SerialPort) sender; const int bufSize = 12; Byte[] buf = new Byte[bufSize]; Console.WriteLine("DATA RECEIVED!"); Console.WriteLine(spL.Read(buf, 0, bufSize)); } } }


Primero, te recomiendo que uses el siguiente constructor en lugar del que usas actualmente:

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

Luego, deberías eliminar este código:

// Wait 10 Seconds for data... for (int i = 0; i < 1000; i++) { Thread.Sleep(10); Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console }

Y en su lugar simplemente bucle hasta que el usuario presiona una tecla o algo así, como así:

namespace serialPortCollection { class Program { static void Main(string[] args) { SerialPort sp = new SerialPort("COM10", 115200); sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler sp.Open(); sp.WriteLine("$"); //Command to start Data Stream Console.ReadLine(); sp.WriteLine("!"); //Stop Data Stream Command sp.Close(); } // My Event Handler Method private static void port_OnReceiveDatazz(object sender, SerialDataReceivedEventArgs e) { SerialPort spL = (SerialPort) sender; byte[] buf = new byte[spL.BytesToRead]; Console.WriteLine("DATA RECEIVED!"); spL.Read(buf, 0, buf.Length); foreach (Byte b in buf) { Console.Write(b.ToString()); } Console.WriteLine(); } } }

Además, tenga en cuenta las revisiones del controlador de eventos de datos recibidos, en realidad debería imprimir el búfer ahora.

ACTUALIZACIÓN 1

Acabo de ejecutar correctamente el siguiente código en mi máquina (utilizando un cable de módem nulo entre COM33 y COM34)

namespace TestApp { class Program { static void Main(string[] args) { Thread writeThread = new Thread(new ThreadStart(WriteThread)); SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One); sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler sp.Open(); sp.WriteLine("$"); //Command to start Data Stream writeThread.Start(); Console.ReadLine(); sp.WriteLine("!"); //Stop Data Stream Command sp.Close(); } private static void port_OnReceiveDatazz(object sender, SerialDataReceivedEventArgs e) { SerialPort spL = (SerialPort) sender; byte[] buf = new byte[spL.BytesToRead]; Console.WriteLine("DATA RECEIVED!"); spL.Read(buf, 0, buf.Length); foreach (Byte b in buf) { Console.Write(b.ToString() + " "); } Console.WriteLine(); } private static void WriteThread() { SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One); sp2.Open(); byte[] buf = new byte[100]; for (byte i = 0; i < 100; i++) { buf[i] = i; } sp2.Write(buf, 0, buf.Length); sp2.Close(); } } }

ACTUALIZACIÓN 2

Dado todo el tráfico en esta pregunta recientemente. Estoy empezando a sospechar que el puerto serie no está configurado correctamente o que el dispositivo no responde.

Recomiendo encarecidamente que intente comunicarse con el dispositivo utilizando otros medios (utilizo hyperterminal con frecuencia). Luego puede jugar con todos estos ajustes (velocidad de bits, paridad, bits de datos, bits de parada, control de flujo) hasta que encuentre el conjunto que funciona. La documentación del dispositivo también debe especificar estas configuraciones. Una vez que los descubrí, me aseguraré de que mi .NET SerialPort esté configurado correctamente para usar esa configuración.

Algunos consejos sobre cómo configurar el puerto serie:

Tenga en cuenta que cuando dije que debería usar el siguiente constructor, quise decir que use esa función, ¡no necesariamente esos parámetros! Debe completar los parámetros para su dispositivo, las configuraciones a continuación son comunes, pero pueden ser diferentes para su dispositivo.

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

También es importante que configure .NET SerialPort para usar el mismo control de flujo que su dispositivo (como otras personas lo han indicado anteriormente). Puedes encontrar más información aquí:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html


Estaba teniendo el mismo problema con un módem que había funcionado anteriormente y luego un día simplemente dejé de generar el evento DataReceived.

La solución en mi caso, muy al azar, fue habilitar RTS, por ejemplo

sp.RtsEnable = true;

No tenía idea de por qué funcionaba este kit en particular (no era realmente un hombre de comunicaciones), ni por qué había funcionado y luego se había detenido, pero podría ayudar a alguien más un día, así que simplemente publícalo por si acaso ...


Creo que esto no funcionará porque estás usando una aplicación de consola y no hay ningún Evento en ejecución. Un Event Loop / Message Pump utilizado para el manejo de eventos se configura automáticamente cuando se crea una aplicación Winforms, pero no para una aplicación de consola.


Creo que su problema es la línea: **

sp.DataReceived + = port_OnReceiveDatazz;

No debería ser:

sp.DataReceived + = new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

** No importa, la sintaxis está bien (no se dio cuenta del atajo en el momento en que originalmente respondí esta pregunta).

También he visto sugerencias de que debes activar las siguientes opciones para tu puerto serie:

sp.DtrEnable = true; // Data-terminal-ready sp.RtsEnable = true; // Request-to-send

También puede tener que establecer el protocolo de enlace a RequestToSend (a través de la enumeración de handshake).

ACTUALIZAR:

Encontré una sugerencia que dice que primero debe abrir su puerto, luego asigne el controlador de eventos. Tal vez es un error?

Entonces en vez de esto:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz); sp.Open();

Hacer esto:

sp.Open(); sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

Déjame saber cómo va eso.


Tenga en cuenta que hay problemas con .NET / C # y cualquier puerto COM superior a COM9.

Ver: CÓMO: Especificar puertos serie más grandes que COM9

Hay una solución en el formato: "//. / COM10" que es compatible con el método CreateFile subyacente, pero .NET evita el uso de ese formato de solución; ni el constructor SerialPort ni la propiedad PortName permitirán un nombre de puerto que comience con "/"

He estado luchando para obtener comunicaciones confiables para COM10 en C # /. NET. Como ejemplo, si tengo un dispositivo en COM9 y COM10, el tráfico destinado para COM10 va al dispositivo en COM9. Si elimino el dispositivo en COM9, el tráfico COM10 va al dispositivo en COM10.

Todavía no he calculado cómo usar el identificador devuelto por CreateFile para crear un objeto SerialPort de estilo C # /. NET, si supiera cómo hacerlo, entonces creo que podría usar COM10 + muy bien desde C #.


Muy bien podría ser la Console.ReadLine bloqueando la línea de Console.Writeline , de hecho. El ejemplo en MSDN parece CASI idéntico, excepto que usan ReadKey (que no bloquea la consola).