MSDN > 論壇首頁 > Comunicación con dispositivos externos > Enviar comandos AT por el puerto serie
發問發問
 

問題Enviar comandos AT por el puerto serie

  • 2007年3月29日 下午 06:23gonzalo4 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    Buenas, soy nuevo programando en C# y tengo un problemilla.

    Debo enviar un comando AT a un dispositivo, y esperar a recibir la respuesta del mismo para procesarla. El dispositivo envia la respuesta terminando en "\r".

     

    Lo he intentado de las siguientes formas pero nada.


    DateTime TimeOut = DateTime.Now.AddSeconds(5);
    string AT_Response = "";
    COMPort.Write(AT_Command);
    do
    {
    ATResponse += COMPort.ReadExisting();
    if (DateTime.Now > TimeOut)
    {
    throw new Exception("AT Command timed out without receiving 'OK'.");
    }
    }
    while (!ATResponse.Contains("OK"));


    ************************************************************************
     Otra manera

     


    COMPort.ReadTimeout = 5000;
    COMPort.NewLine = "\r";
    COMPort.Write(AT_Command);
    AT_Response = COMPort.ReadLine();

     

     

    Agradeceria que me ayudaseis.

所有回覆

  • 2007年3月30日 上午 06:31Luis Ruiz Pavón 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    Hola Gonzalo :

     

    Porqué no haces una pausa:

     

    _SerialPort.Write(sTrama);
      System.Threading.Thread.Sleep(iSegundos*1000);
      sRespuesta = _SerialPort.ReadExisting();
       _SerialPort.DiscardInBuffer();

     

    De todas maneras  a ver si se pasa Pep y lo lee que el es el experto en estos temas.

     

    Salu2

  • 2007年3月30日 上午 07:54PepLluisMVP, 版主使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    Gracias Luis y Hola Gonzalo.

    Tienes que empezar, definiendo el evento de recepcion (puede estas justo despues de ‘InitializeComponent()’…

    this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.Recepcion);

     

    Luego puede procesar los caracteres recibidos en espera de ‘\r’ que supuestamente es el carácter 13 de la tabla ASCII.

    // Al recibir datos

    private void Recepcion(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

       {

       // Acumular los caracteres recibidos a nuestro 'buffer' (string)

       Recibidos += this.serialPort1.ReadExisting();

       // Invocar al proceso de tramas

       // para evitar la llamada ilegal entre threats

       this.Invoke(new EventHandler(Actualizar));

       }

     

    Como observaras en este caso usaremos un (string RecibidosWink para procesar los caracteres. Cada vez que se reciba algun carater dispararemos la actualizacion para controlar si la trama de recepcion esta completa.

    private void Actualizar(object s, EventArgs e)

       {

       int Inicio = Recibidos.IndexOf("\x01"); // Posicion Inicio trama (Ejemplo)

       int Final = Recibidos.IndexOf("\x0D");  // Posicion Final trama (13 en hex)

       //

       // Si exiset posicion de inicio y una despues del final

       if ((Inicio > -1) & (Final > Inicio))

          {

          // procesar la trama completa

          }

          else

          // De no cumplirse las condiciones de Inicio/Fin

          {

          }

        }

     

    No dudes en continuar este hilo para ir discutiendo los detalles,

    Saludos a los dos,

    Pep Lluis,

  • 2007年3月30日 上午 11:18gonzalo4 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    Gracias por intentar ayudarme Luis y Pep Lluis.

     

    Mi problema es que defino el evento de recepcion:

     

    COMPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);

     

      Envio datos al dispositivo y tambien los recivo (estos datos solamente hay que mostrarlos en una ventana de texto),

    pero cuando envio un comando AT, debo recoger la respuesta y comprobar si se a ejecutado correctamente (recibir "OK\r").

     

     

    private void ReceiveData(object sender, SerialDataReceivedEventArgs e)

    {

         if (CurrentDataMode == DataMode.Text)   // modo texto

         {

           string Data_R = COMPort.ReadExisting();

            Message(TxtType.Incoming, Data_R);   //mostrar en ventana de texto

         }

         else    // modo hexadecimal

         {

            int Bytes = COMPort.BytesToRead;

            byte[] Buffer = new byte[Bytes];

           COMPort.Read(Buffer, 0, Bytes);

          Message(TxtType.Incoming, ByteArrayToHexString(Buffer) + "\r");  //mostrar en ventana de texto

        }

    }

     

     

    Para entrar en el modo de comandos AT, debo enviar "+++" y esperar a recibir la respuesta "OK\r"

     

     

    string Response = "";

    DateTime TimeOut = DateTime.Now.AddSeconds(2);

    try

      {

        COMPort.Write("+++");

        do

        {

          Response += COMPort.ReadExisting();

          if (DateTime.Now > TimeOut)

          {

            throw new Exception("AT Command timed out without receiving 'OK'.");

          }

        }

        while (!Response.Contains("OK"));

      }

     

    catch (Exception)

      {

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

     

     

    En internet encontre que se podria hacer de la siguiente manera tambien:

     

     

    string Response = "";

    COMPort.Write("+++");

     

    try

      {

        Response = COMPort.ReadLine();

      }

     

    catch (Exception)

      {

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

     

    para ello antes he configurado los parametros del puerto:

     

    COMPort.NewLine = "\r"//caracter que determina fianl de linea

    COMPort.ReadTimeout = 5000; // tiempo de lectura maximo

     

    de las formas anteriores hay veces que funciona y otras que no pero no encuentro el fallo.

     

    Salu2.

     

  • 2007年3月30日 下午 04:20PepLluisMVP, 版主使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    Hola de nuevo,

    El error reside en que nunca puedes esperar la respuesta de una comunicacion dentro de un bucle, ni tampoco en un readline... :-(

     

    En muchas ocasiones dependiendo del dispositivo, no respondera la primera vez que envies el '+++' o dependiendo de la configuracion del mismo, no respondera con un "OK"... si te parece bien vamos a empezar de nuevo. Dime exactamente el primer objetivo a conseguir y que tipo de dispositivo estas enchufando al puerto... si un modem / telefono... y si me das tiempo montamos un ejemplo especifico.

    Saludos,

    Pep Lluis,

     

  • 2007年3月31日 上午 08:22gonzalo4 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

     

    Hola Pep Lluis.

     

    Creo que ya he conseguido resolver el fallo, te explico.

     

    Una vez definido el evento recibirpor el puerto serie,

     

    COMPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);

     

     

    private void ReceiveData(object sender, SerialDataReceivedEventArgs e)

    {

      if (CurrentDataMode == DataMode.Text)

      {

        if (ATMode == true)

        {

          Response = COMPort.ReadLine();

        }

        else

        {

          string Data_R = COMPort.ReadExisting();

          Message(TxtType.Incoming, Data_R);

        }

      }

      else

      {

        int Bytes = COMPort.BytesToRead;

        byte[] Buffer = new byte[Bytes];

        COMPort.Read(Buffer, 0, Bytes);

        Message(TxtType.Incoming, ByteArrayToHexString(Buffer) + "\r");

      }

    }

     

     

    He creado una funcion para entrar en el modo de comandos AT:

     

     

    private bool EnterATCommandMode()

    {

      bool EnterAT = false;

      DateTime TimeOut = DateTime.Now.AddSeconds(2);

      try

      {

        COMPort.Write("+++");

        ATMode = true;

        do

        {

          if (DateTime.Now > TimeOut)

          {

            ATMode = false;

            throw new Exception("AT Command timed out without receiving 'OK'.");

          }

        }

        while (!Response.Contains("OK"));

      }

      catch (Exception)

      {

        ATMode = false;

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

      if (Response.Contains("OK"))

      {

        EnterAT = true;

        TimeOutATMode = DateTime.Now.AddSeconds(9);

        Response = "";

      }

      return EnterAT;

    }

     

    Podrias decirme si lo que he heco estaria bien.

     

     

    El dispositivo que conecto al puerto serie, es un kit de desarrollo ZigBee.

    Si envias mensajes al dispositivo, este los envia a los dispositivos indicados en la configuracion.

    Para configurar las direcciones de envio debo entrar en el modo de comandos AT y comprobar que la configuracion es correcta.

     

     

    Salu2.

     

  • 2009年5月26日 上午 08:36Metaconta 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     
    Hola:

    Puedes descargar el manual en pdf sobre VB y  puerto serie.

    Saludo.

    http://electronica-pic.blogspot.com