Ver Mensaje Individual
  #1 (permalink)  
Antiguo 18/08/2014, 04:19
SARGE553413
 
Fecha de Ingreso: febrero-2014
Mensajes: 55
Antigüedad: 10 años, 2 meses
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