2011-05-10 71 views
5

Estoy intentando escribir un programa C# 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.Sincronización del puerto serie Lectura/escritura

Tenía planeado usar un mutex, pero creo que el problema no se debe a la multitracción. 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 esperar que no se ejecutara el manejador de eventos de datos recibidos?

(ambos métodos son de 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 datos recibidos controlador de eventos:

//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 = ""; 
    } 

} 
+0

Resulta que yo estaba malinterpretando forma en que se envían y se reciben en el puerto serie de datos. Los datos que se envían y reciben nunca entran en conflicto entre ellos, ya que los mensajes enviados y recibidos se almacenan en el lado del microcontrolador y en el lado de la PC. El marco de la comunicación serial entre las dos fuentes clasifica todos los detalles. Mi problema fue con la forma en que procesé los datos recibidos. – isometrik

+0

Err, no. Es cierto que enviar y recibir no entran en conflicto, pero la razón no es el almacenamiento en búfer. Enviar y recibir utiliza pines completamente separados, por lo que un puerto serie admite full-duplex. –

Respuesta

0

me gustaría utilizar solo 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 
0

tengo el mismo problema en el pasado y he resuelto de esta manera:

añadí método SendAndWaitResponse que recibe el buffer para ser enviado por el puerto, la longitud esperada de la respuesta, un tiempo de espera en segundos (si acaso), y una devolución de llamada, cuando se ha recibido 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!!! 
      } 
     } 
+0

¡No he ejecutado este código! Avíseme si no funciona y lo arreglará. (No tengo ningún dispositivo serial para probarlo atm). –

0

Si desea comprobar si hay bytes con enviar al dispositivo de salida (bytes de buffer de escritura), por lo que puede leer la propiedad BytesToWrite.

SerialPort.BytesToWrite Property

Cuestiones relacionadas