Enviar comandos AT por el puerto serie
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.
- MovidoToni Recio [SecondNug.com]MVPterça-feira, 26 de maio de 2009 9:24 ([Loc]From:Lenguaje VB.NET)
Todas as Respostas
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
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 Recibidos
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,
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 lineaCOMPort.ReadTimeout = 5000; // tiempo de lectura maximo
de las formas anteriores hay veces que funciona y otras que no pero no encuentro el fallo.
Salu2.
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,
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.
- Hola:Puedes descargar el manual en pdf sobre VB y puerto serie.Saludo.
http://electronica-pic.blogspot.com

