2010-06-01 36 views
5

He configurado un SerialDataReceivedEventHandler, con un programa basado en formularios en VS2008 express. Mi puerto serie está configurado de la siguiente manera:C# .Net Serial DataReceived Respuesta de evento demasiado lenta para datos de alta velocidad

115200, 8N1

DTR y RTS habilitado

ReceivedBytesThreshold = 1

tengo un dispositivo que estoy interfaz con más de un Bluetooth, USB a Serial . Hyper Terminal recibe los datos muy bien a cualquier velocidad de datos. Los datos se envían regularmente en paquetes de 22 bytes de longitud. Este dispositivo tiene una velocidad ajustable a la cual se envían los datos. A velocidades de datos bajas, 10-20Hz, el siguiente código funciona muy bien, sin problemas. Sin embargo, cuando aumento la velocidad de datos más allá de 25Hz, comienza a recibir paquetes múltiples en una llamada. Lo que quiero decir con esto es que debería haber un activador de evento para cada paquete entrante. Con tasas de salida más altas, he probado el tamaño del búfer (comando BytesToRead) inmediatamente cuando se llama al evento y luego hay múltiples paquetes en el búfer. Creo que el evento se dispara lentamente y para cuando alcanza el código, más paquetes han golpeado el buffer. Una prueba que hago es ver cuántas veces se dispara el evento por segundo. En 10Hz, obtengo 10 desencadenantes de eventos, increíble. A 100 Hz, obtengo algo así como 40 desencadenantes de eventos, no es bueno. Mi objetivo para la velocidad de datos es 100HZ es aceptable, se prefiere 200Hz y 300Hz óptimo. Esto debería funcionar porque incluso a 300Hz, eso es solo 52800bps, menos de la mitad de la velocidad establecida de 115200 baudios. ¿Algo que esté buscando?

public Form1() 
    { 
     InitializeComponent(); 
     serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);    
    } 


    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     this.Invoke(new EventHandler(Display_Results)); 
    } 


    private void Display_Results(object s, EventArgs e) 
    { 
     serialPort1.Read(IMU, 0, serial_Port1.BytesToRead); 
    } 

Respuesta

3

¿Por qué invoca() la llamada a DisplayResults?

Esto lo enviará al MessageLoop, un retraso innecesario.

Sería mejor si DataReceived() insertara datos en una cola (thread-safe) para el procesamiento desacoplado.

También creo que podría tener problemas con los paquetes divididos.

+0

Intenté eliminar la llamada Invoke() y leer los datos directamente en el evento DataReceived() con los mismos resultados. Lamento ser un poco ingenuo, pero ¿podría decirme más acerca de cómo se hace la cola y por qué eso funciona más rápido? Gracias por la ayuda. – Matthew

1

Usted podría intenta establecer ReceivedBytesThreshold = 22, lo que resultará en caso de ser despedido cuando hay al menos 22 bytes a leer. Tenga en cuenta que será al menos 22. Puede haber más.

No creo que yo personalmente lo haga, porque ¿qué ocurre si el tamaño de su paquete cambia en el futuro, por ejemplo, a 12 bytes? Usted terminaría con 12 bytes en el búfer pero sin disparar el evento.

Mucho mejor dejarlo configurado en 1, que activará el evento cuando al menos 1 byte esté disponible. Luego inserte todos los bytes recibidos en una lista o cola como Henk ya ha publicado.

Tenga en cuenta que DataReceivedEvent no tiene conocimiento de lo que usted considera un paquete de datos por supuesto. Simplemente se dispara cuando hay bytes disponibles. Depende del desarrollador ensamblar estos bytes en un mensaje o paquete significativo.

4

¿Intentó ajustar la latencia de tiempo en el convertidor serie USB? Tuve el mismo problema con un convertidor USB a serie FTDI. Utilizo un osciloscopio para ver mis datos de ENTRADA y SALIDA que provienen del dispositivo y pude ver que la computadora siempre respondía con lentitud. De forma predeterminada, la latencia de tiempo en el dispositivo se establece en 16 ms. Lo cambié a 2 ms y hace una gran diferencia. Vaya a su Convertidor serie USB en el Administrador de dispositivos y en la configuración avanzada, cambie el tiempo de Latencia a 2 ms. Debería funcionarIntentalo.

+1

¿Alguna idea de por qué una latencia de "16 ms" se traduce en cientos de milisegundos entre los conjuntos de datos recibidos? – supercat

0

El problema radica en el manejador de datos recibidos.

ejecuté un hilo por separado con un lazo while(true) y serial.ReadLine(), todo funciona perfectamente.

using System.Threading; 

Thread readThread = new Thread(Read); 
readThread.Start(); 

Espero que alguien más no necesite gastar 3 horas arreglando esto.

Cuestiones relacionadas