Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Problema leer/escribir puerto serie (C++ WINAPI)

Estas en el tema de Problema leer/escribir puerto serie (C++ WINAPI) en el foro de C/C++ en Foros del Web. 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 ...
  #1 (permalink)  
Antiguo 18/08/2014, 04:19
 
Fecha de Ingreso: febrero-2014
Mensajes: 55
Antigüedad: 10 años, 1 mes
Puntos: 3
Problema leer/escribir puerto serie (C++ WINAPI)

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/libr...(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.

EDITO: Lo que me da problemas es el overlapped, si lo quito, todo va bien. Entonces mi problema es que no se usar el overlapped bien, que hago mal?

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 buff[20];
	DWORD bW;
	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 edición por SARGE553413; 18/08/2014 a las 05:12
  #2 (permalink)  
Antiguo 18/08/2014, 11:56
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Problema leer/escribir puerto serie (C++ WINAPI)

Buenas,

Overlapped te permite lanzar una operación de entrada/salida de forma asíncrona y retornar sin esperar siquiera a que esta operación haya finalizado. Por eso cuando tratas de recuperar el error te da problemas, porque la operación aún no ha retornado y por lo tanto no lo puede recuperar.
Es un modo que si se usa bien puede proporcionar más rendimiento sobre todo al desarrollar servidores, pero probablemente en tu caso con utilizar operaciones síncronas te servirá perfectamente.

Un saludo

Etiquetas: funcion, int, programa, puerto, serie
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 15:31.