visual serie serial puerto por manejo leer enviar entre encender datos comunicacion cerrar c# synchronization serial-port

c# - serie - manejo de puerto serial en visual basic 2010



Sincronización del puerto serie Lectura/escritura (3)

Estoy intentando escribir el programa de CA # en Visual Studio 2010 que se comunica con un microcontrolador a través de una conexión en serie. Puedo leer y escribir en el puerto muy bien, simplemente no estoy seguro de cómo hacer que el método de envío espere hasta que se hayan recibido todos los datos del comando de envío anterior antes de que se ejecute. Implementé el manejador de eventos de datos recibidos de modo que determina cuándo se ha recibido la cantidad adecuada de datos solicitados en el puerto serie. Solo necesito saber cómo hacer eso para decirle al método de envío que el puerto es libre.

Había planeado usar un mutex, pero creo que el problema no se debe al multihilo. El mismo hilo está enviando cadenas en el puerto serie una después de otra y los datos que se reciben en respuesta a la primera solicitud entran en conflicto con la segunda solicitud.

Además, si la comunicación se realiza por un hilo, ¿esperaría ese hilo a que el manejador de eventos de datos recibidos no se ejecutara?

(ambos métodos están en la misma clase)

Mi método de envío de datos:

//method for sending data public void send(String s) { sp.Write(s + "/r"); }

Mi manejador de eventos de datos recibidos:

//data received event handler private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { string tmp; tmp = sp.ReadExisting(); //put all received data into the read buffer readBuffer += tmp; //add various flag checks to determine end of transmission if (firmwareFlag) { if (readBuffer.EndsWith("/n")) { firmwareFlag = false; //trigger event to tell object owner data is ready dataReady(this, new CustomEventArgs(readBuffer, "firmware")); readBuffer = ""; } } else if (parameterFlag) { if (System.Text.RegularExpressions.Regex.IsMatch(readBuffer, "K90", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) { parameterFlag = false; dataReady(this, new CustomEventArgs(readBuffer, "parameters")); readBuffer = ""; } } else { dataReady(this, new CustomEventArgs(readBuffer, null)); readBuffer = ""; } }


Solo usaría una variable bool en la clase y un temporizador. Cuando el temporizador marca, verifica ese bool y envía los datos si está permitido.

boolean isAllowed; DispatcherTimer tmr1; //...etc


Tengo el mismo problema en el pasado y lo resolví de esta manera:

Agregué el método SendAndWaitResponse que recibe el buffer que enviará el puerto, la duración esperada de la respuesta, un tiempo de espera en segundos (por si acaso) y una devolución de llamada, cuando se recibió la respuesta esperada:

//System.IO.Ports.SerialPort port; //port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived); void SendAndWaitResponse(String buffer, int expectedLenght, int timeoutInSeconds, Action<String> callback) { TimeSpan _timeout = new TimeSpan(0, 0, 0, timeoutInSeconds); //may not be necesary if (!string.IsNullOrEmpty(buffer) && buffer != "" && port != null) { //Remove current dataReceived event handler, as we will manually manage it for now, will restore later! this.port.DataReceived -= port_DataReceived; if (!this.port.IsOpen) this.port.Open(); // open the port if it was closed this.send(buffer); // send buffer, changed port.write(buffer) so it now usses your own send DateTime startToWait = DateTime.Now; //start timeout bool isTimeout = false; int totalRead = 0; String read = ""; while (!(isTimeout) && totalRead < expectedLenght) { do { if (port.BytesToRead > 0) { read += (char)this.port.ReadByte(); totalRead++; //you can add a System.Threading.Thread.Sleep(int); if all bytes come in parts } } while (port.BytesToRead > 0); isTimeout = (DateTime.Now.Subtract(_timeout) >= startToWait); } this.port.DataReceived += port_DataReceived; // restore listener callback(read); //invoke callback!!! } }


Si desea comprobar si hay bytes sin enviar al dispositivo (bytes en el búfer de escritura), entonces puede leer la propiedad BytesToWrite.

Propiedad SerialPort.BytesToWrite