elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema leer/escribir puerto serie (C++ WINAPI)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema leer/escribir puerto serie (C++ WINAPI)  (Leído 6,050 veces)
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Problema leer/escribir puerto serie (C++ WINAPI)
« en: 18 Agosto 2014, 12:22 pm »

Hola a todos.

Estoy intentando hacer una clase con la funcionalidad básica (abrir,cerrar,leer,escribir) para manejar el puerto serie.
Esto es debido a que el puerto serie que tengo que usar lo genera "virtualmente" un programa y la clase SerialPort del .NET Framework no consigue ni abrirlo. (Pregunté en foros de microsof (msdn) y me dijeron que tenía que hacerlo con la WINAPI).

Tras hacer la clase y probarla, he conseguido abrir el puerto y cerrarlo bien. El problema es que no consigo leer ni escribir. En ambas operaciones, si hago "GetLastError()" el error resultante es 997, que según microsoft es: ERROR_IO_PENDING - Overlapped I/O operation is in progress.
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms681388(v=vs.85).aspx)

NOTA: si llamo a las funciones de lectura / escritura con el parámetro LPOVERLAPPED como NULL, el código de error (GetLastError) es 87 (el parámetro es incorrecto), el mismo error que tuve cuando traté de usar la clase Net Framework SerialPort.

Adjunto el código de la clase (solo el cpp, el .h no lo veo necesario):
Código:
#include "StdAfx.h"
#include "SerialPort_WINAPI.h"

/*** Atributos constantes definidos en el .h ***/
const wchar_t *const SerialPort_WINAPI::DEFAULT_PORT_NAME = L"COM6";
static const wchar_t *const DEFAULT_PORT_NAME; //Inicializado en el cpp.
static const DWORD BAUD_RATE = 9600;
static const BYTE STOP_BITS = 1;
static const BYTE PARITY = 0; //0==None
static const BYTE DATA_BITS = 8;
static const DWORD HANDSHAKE = 0x00;

SerialPort_WINAPI::SerialPort_WINAPI(void){

}

SerialPort_WINAPI::~SerialPort_WINAPI(void){

}

SerialPortErr SerialPort_WINAPI::openConnection(){
port = CreateFile(SerialPort_WINAPI::DEFAULT_PORT_NAME, //\\\\.\\COM4"
GENERIC_READ | GENERIC_WRITE,
0,    // exclusive access
NULL, // default security attributes
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (port == INVALID_HANDLE_VALUE)
return Create_File_Err;

if (GetCommState(port, &portConfig) == 0){
closeConnection();
return Get_Comm_State_Err;
}

initData();
if (SetCommState(port, &portConfig) == 0){
closeConnection();
return Set_Comm_State_Err;
}

if (SetCommMask(port, EV_DSR) == 0){ //EV_CTS | EV_DSR
closeConnection();
return Set_Comm_Mask_Err;
}

initOverlapped();
portEvents.hEvent = CreateEvent(
NULL,   // default security attributes
TRUE,   // manual-reset event
FALSE,  // not signaled
NULL    // no name
);

return Exit_Success;
};

void SerialPort_WINAPI::initData(){
portConfig.BaudRate = BAUD_RATE;
portConfig.fRtsControl = HANDSHAKE;
portConfig.Parity = PARITY;
portConfig.ByteSize = DATA_BITS;
portConfig.StopBits = STOP_BITS;
};

void SerialPort_WINAPI::initOverlapped(){
portEvents.Internal = 0;
portEvents.InternalHigh = 0;
portEvents.Offset = 0;
portEvents.OffsetHigh = 0;
};

SerialPortErr SerialPort_WINAPI::closeConnection(){
SetCommMask(port,0);
if (CloseHandle(port) == 0)
return Close_Err;
return Exit_Success;
};

SerialPortErr SerialPort_WINAPI::read(char *buffer,int length,LPDWORD read){
if(!ReadFile(this->port,buffer,length,read,&this->portEvents)){
return Read_Err;
}
}

SerialPortErr SerialPort_WINAPI::write(char *buffer,int nBytesToWrite,LPDWORD write){
if(!WriteFile(this->port,buffer,nBytesToWrite,write,&this->portEvents)){
return Write_Err;
}
}

Y aquí el main:
Código:
int main(){
SerialPort_WINAPI sp;
char readBuffer[128];
DWORD read;
char writeBuffer[10];
DWORD write;
for(int i=0;i<10;i++) writeBuffer[i]='a';

SerialPortErr err=sp.openConnection();
if(err!=Exit_Success){
cout<<"open: "<<(int)err<<endl;
return -1;
}else{
cout<<"Openned..."<<endl;
}

err=sp.write(writeBuffer,10,&write);
if(err!=Exit_Success){
cout<<"write: "<<GetLastError()<<endl;
}

err=sp.read(readBuffer,128,&read);
if(err!=Exit_Success){
cout<<"read: "<<GetLastError()<<endl;
}


err=sp.closeConnection();
cout<<"close: "<<(int)err<<endl;
return 0;
}

He estado intentando aprender a usar esta API para el puerto serie, pero aunque he leído algunos ejemplos etc. hay muchas cosas que no entiendo.
Por ej. : ¿OVERLAPPED sirve para añadir funciones de callback a distintos eventos del puerto serie, como leer o escribir?

Gracias y saludos.


« Última modificación: 18 Agosto 2014, 12:47 pm por SARGE553413 » En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.966


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #1 en: 18 Agosto 2014, 12:58 pm »

Overlapped es para trabajar con I/O asincrona, en este caso el evento sera señalado cuando se complete el I/O.

Synchronous and Asynchronous I/O.

En realidad ese no es un error, como dice la MSDN:
Note  The GetLastError code ERROR_IO_PENDING is not a failure; it designates the read operation is pending completion asynchronously. For more information, see Remarks.

En fin, te aconsejo no usar overlapped, al menos no al principio, primero hacelo funcionar de manera sincrona.

Synchronization and Overlapped Input and Output.


En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #2 en: 18 Agosto 2014, 13:09 pm »

Si, justo lo acabo de leer lo del error, gracias.

[INNECESARIO]
El caso es que ahora si he podido leer y escribir, pero la función ReadFile() siempre me devuelve 0 (error) y no entiendo por qué. EDITO: Se me había olvidad añadir el "return Exit_Success" en caso de que todo fuese bien .... "
[/INNECESARIO]

Realmente creo que quizá no necesite usarlo de manera asíncrona, explico lo que tengo que hacer:

1 - Por un lado, enviar a la máquina conectada al serie señales para setear algunos parámetros (como por ej. temperaturas de peligro y no-peligro).

2 - Además, quiero tener un hilo en background escuchando "constantemente" (osea cada x milis) al puerto serie, porque esta máquina envía una señal si se alcanza una temperatura designada como "peligrosa" y vuelve a mandar una señal si se vuelve a la temperatura "no-peligrosa".

Entonces para el segundo punto si que necesito lo asíncrono, ¿cierto?

Gracias, saludos.

« Última modificación: 18 Agosto 2014, 13:11 pm por SARGE553413 » En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.966


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #3 en: 18 Agosto 2014, 13:50 pm »

Realmente creo que quizá no necesite usarlo de manera asíncrona, explico lo que tengo que hacer:

1 - Por un lado, enviar a la máquina conectada al serie señales para setear algunos parámetros (como por ej. temperaturas de peligro y no-peligro).

2 - Además, quiero tener un hilo en background escuchando "constantemente" (osea cada x milis) al puerto serie, porque esta máquina envía una señal si se alcanza una temperatura designada como "peligrosa" y vuelve a mandar una señal si se vuelve a la temperatura "no-peligrosa".

Entonces para el segundo punto si que necesito lo asíncrono, ¿cierto?

No hace falta, si la operacion de I/O no retorna cuando es sincrona es que no hay datos que procesar. En el segundo punto si el hilo solo se dedica a I/O no hay problema.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #4 en: 19 Agosto 2014, 11:03 am »

Hola de nuevo, gracias por la respuesta.

Entonces de momento no haré nada asíncrono. Pero me queda una pregunta, se supone que ReadFile() no es bloqueante, es decir, si hago ReadFile() y el serie no escribe nada, continúa la ejecución del programa, no se queda ahí esperando para siempre.

Entonces ¿qué pasa si le mando algo al serie y antes de que le de tiempo a escribir yo hago ReadFile() ? ¿Hay alguna manera de esperar con ReadFile() un tiempo determinado, y después seguir?
Se qué se puede configurar el serie con timeouts por lo que he leído, pero no entiendo muy a qué se refiere, si a cerrar el serie tras un tiempo o a lo que digo yo.

Gracias, saludos.
En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.966


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #5 en: 19 Agosto 2014, 11:39 am »

Si no usas Overlapped ReadFile es bloqueante.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #6 en: 19 Agosto 2014, 14:40 pm »

Ok, gracias de nuevo.

Entonces tengo otra duda:
Tengo que tener un hilo escuchando constantemente al serie. Esto en principio parece fácil porque ReadFile() es bloqueante, de manera que dejo al hilo en un bucle "infinito"
haciendo esta operación.

El problema es que, en algunos momentos, el programa tendrá que escribir y leer cosas en el serie, entonces la manera de hacer esto sería:
1 - Decirle al "hilo escuchador" que pare de escuchar y espere hasta nueva orden (con un evento por ej.)
2 - Realizar las operaciones de lectura/escritura.
3 - Decirle al hilo que vuelva a empezar a escuchar.

Bien, lo que no tengo claro como hacer es, estando el hilo bloqueado por el ReadFile(), conseguir que salga de ese bloqueo.

NOTA: EL hilo del que hablo, no es de la API de windows, es el del .Net Framework, quizá una posibilidad sería esta:

Código:
...
bool shouldStop=false;
ManualResetEvent ^mre=gcnew ManualResetEvent(false);
...

void warningListener(){
while(!stop){
try{
ReadFile(...);
//Hacer algo...
}catch(ThreadInterruptException ^ie){
mre->WaitOne();
}
}
}

Pero no se si al hacer Thread.Interrupt() estando el hilo bloqueado, saltará alguna excepción...

Saludos, gracias.
« Última modificación: 19 Agosto 2014, 14:48 pm por SARGE553413 » En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.966


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #7 en: 19 Agosto 2014, 14:55 pm »

No conozco tu problema en profundidad pero tal vez en lugar de intentar desbloquear el hilo a mano una mejor alternativa sea realizar todas las lecturas en el hilo, dependiendo de que lea puede procesarlo, ignorarlo, crear otro hilo para que actue, etc..; cuando escribas desde el hilo principal u otro hilo esto va a terminar desbloqueando el hilo de lectura si el dispositivo en el puerto responde.

Por favor, no preguntes sobre .NET en este subforo, no es el lugar adecuado.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #8 en: 20 Agosto 2014, 10:41 am »

Ok, gracias.
En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.966


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema leer/escribir puerto serie (C++ WINAPI)
« Respuesta #9 en: 20 Agosto 2014, 11:36 am »

De nada.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Librerias para leer el puerto Serie desde PHP
PHP
Graphixx 2 7,231 Último mensaje 23 Agosto 2011, 13:57 pm
por [u]nsigned
Evitar quedarse bloqueado al leer del puerto serie (C++ WinAPI)
Programación C/C++
SARGE553413 3 3,354 Último mensaje 8 Diciembre 2014, 18:55 pm
por x64core
Leer puerto serie y mostrar texto en cuadro de texto
Java
Meta 0 3,676 Último mensaje 6 Marzo 2015, 21:33 pm
por Meta
[Python] leer puerto serie desde PyQt5 y arduino y mostrase interfaz grafica
Scripting
jenju302 4 6,364 Último mensaje 5 Noviembre 2016, 04:03 am
por Once
Leer puro byte del puerto serie
.NET (C#, VB.NET, ASP)
Meta 0 4,256 Último mensaje 8 Noviembre 2023, 21:40 pm
por Meta
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines