Autor
|
Tema: Problema leer/escribir puerto serie (C++ WINAPI) (Leído 6,117 veces)
|
SARGE553413
Desconectado
Mensajes: 176
|
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): #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: 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
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
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
Mensajes: 176
|
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
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
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
Mensajes: 176
|
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
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
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
Mensajes: 176
|
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: ... 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
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
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
Mensajes: 176
|
Ok, gracias.
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
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
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Librerias para leer el puerto Serie desde PHP
PHP
|
Graphixx
|
2
|
7,242
|
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,387
|
8 Diciembre 2014, 18:55 pm
por x64core
|
|
|
Leer puerto serie y mostrar texto en cuadro de texto
Java
|
Meta
|
0
|
3,698
|
6 Marzo 2015, 21:33 pm
por Meta
|
|
|
[Python] leer puerto serie desde PyQt5 y arduino y mostrase interfaz grafica
Python
|
jenju302
|
4
|
6,411
|
5 Noviembre 2016, 04:03 am
por Once
|
|
|
Leer puro byte del puerto serie
.NET (C#, VB.NET, ASP)
|
Meta
|
0
|
4,441
|
8 Noviembre 2023, 21:40 pm
por Meta
|
|