Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations waross on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Serial Comm Handle Problem

Status
Not open for further replies.

laberti

Computer
Apr 12, 2005
1
0
0
BR
Hi All,

I wrote a code to do serial communication with an equipament.
When i use the code outside of threaded class it seens work properly,
but when i put inside a class and execute a thread in the first seconds the
communication is ok, later i receive read/write error.
I´ve been in MSDN site and there i discover that the read/write error is a
INVALID_HANDLE problem. But why??? I just create the serial communication
file and use it.
Anyone can help me?

Here is the code

/* cut */
/*--------------------------------------------------------------------*/
/* Main Class */

#ifndef _IGERENCIADOREQUIPAMENTO_H
#define _IGERENCIADOREQUIPAMENTO_H

#include <stdio.h>
#include <windows.h>

#define SERIAL_PARITY_NONE 0
#define SERIAL_PARITY_ODD 1
#define SERIAL_PARITY_EVEN 2

#define SERIAL_MAX_RX 256 // Input buffer max size
#define SERIAL_MAX_TX 256 // output buffer max size

#define SERIAL_CONNECTED 0
#define SERIAL_DISCONNECTED 1
#define SERIAL_DATA_SENT 2
#define SERIAL_DATA_ARRIVAL 3
#define SERIAL_RING 4
#define SERIAL_CD_ON 5
#define SERIAL_CD_OFF 6
#define SERIAL_DATA_RECV 7

#define SERIAL_SIGNAL_NBR 7

class IGerenciadorEquipamento;

typedef struct
{
HANDLE serialFD;
IGerenciadorEquipamento* pIGE;
}_SERIALCOM_IONICS;

class IGerenciadorEquipamento: public IThread
{

private:
HANDLE hSerial;
char *cPortaSerial;
DWORD dwBaudRate;
BYTE byByteSize;
BYTE byTipoParidade;
bool conectado;
bool bRX_In_Progress; // BOOL indicating if a
ReadFile is
// in progress
bool bTX_In_Progress; // BOOL indicating if a
WriteFile is
// in progress

unsigned char pacoteIN[256];
unsigned char pacoteOUT[256];

bool bConectado;

int ConfigTimeouts(COMMTIMEOUTS mCommtimeout);
int ConfigDCB(DCB mDCB);

public:
IGerenciadorEquipamento(char *mcPortaSerial, DWORD mdwBaudRate,
BYTE mbyByteSize, BYTE mbyiTipoParidade);
~IGerenciadorEquipamento();

int AtivaEquipamento(BOOL mbIniciaThread = true);
int DesativaEquipamento(BOOL mbFinalizaThread = true);
int EscreveMensagem(HANDLE hSerialCOM,unsigned char* mcMensagem, int
miTamanho);
int LeMensagem(HANDLE hSerialCOM,unsigned char* mcMensagem, int
miTamanho);
void PurgeSerial(void);
bool VerificaEstado(void);
int Run(void);
HANDLE GetSerialHND(void);
void OnSendRecv(void);
unsigned char *GetDadosRecebidos(void);
unsigned char *GetDadosEnviados(void);

int EnviaPOLLING(HANDLE hSerialCOM);
int ConcedePrivilegio(HANDLE hSerialCOM, BYTE byEndereco);
void TraduzMens(unsigned char *ucPacote, DWORD miTamanho);
DWORD IGerenciadorEquipamento::ExtraiCMD(unsigned char *ucPacoteIN,
DWORD dStartpos,
DWORD dQtdebytes,
unsigned char* ucPacoteOUT);


};

//DWORD WINAPI ComSendRecv(LPVOID p);
int ComSendRecv(LPVOID p);

#endif

/*--------------------------------------------------------------------*/
/* until here */

/* cut */
/*--------------------------------------------------------------------*/
/* Main Class Code */

//#define STRICT
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <conio.h>
#include <windows.h>
#include <iostream>
#include <math.h>
#include "IGerenciadorEquipamento.hpp"
#include "StringMethods.hpp"
#include "Consts.hpp"
#include "TipoProtocolo.hpp"

#define SIG_POWER_DOWN 0
#define SIG_READER 1
#define SIG_READ_DONE 2 // data received has been read
#define SIG_WRITER 3
#define SIG_DATA_TO_TX 4 // data waiting to be sent
#define SIG_MODEM_EVENTS 5
#define SIG_MODEM_CHECKED 6

using namespace std;

typedef struct
{
BYTE controladora;
BYTE tentativas;
bool detectaprot;
}STRU_CONFCONTROL;

STRU_CONFCONTROL ConfControl;

unsigned char *IGerenciadorEquipamento::GetDadosRecebidos(void)
{
return pacoteOUT;
}

unsigned char *IGerenciadorEquipamento::GetDadosEnviados(void)
{
return pacoteIN;
}

int IGerenciadorEquipamento::EnviaPOLLING(HANDLE hSerialCOM)
{
unsigned char ucPacoteIN[256];
unsigned char ucPacoteOUT[256];
int iTotalLido;

ZeroMemory(ucPacoteIN,3);

ucPacoteIN[0] = SYN;
ucPacoteIN[1] = '1';
ucPacoteIN[2] = 0x55;

EscreveMensagem(hSerialCOM ,ucPacoteIN,3);
iTotalLido=LeMensagem(hSerialCOM ,ucPacoteOUT,30);
if (iTotalLido)
{
if ((ucPacoteOUT[0] == SYN) && (ucPacoteOUT[1] == '1') &&
(ucPacoteOUT[2] == 0xAA))
ConfControl.detectaprot = false;
}
return iTotalLido;
}

int IGerenciadorEquipamento::ConcedePrivilegio(HANDLE hSerialCOM, BYTE
byEndereco)
{
unsigned char ucPacoteIN[256];
int iTotalEscrito;

ZeroMemory(ucPacoteIN,3);

// privilegio
ucPacoteIN[0] = SYN;
ucPacoteIN[1] = byEndereco+48;
ucPacoteIN[2] = ACK;

iTotalEscrito=EscreveMensagem(hSerialCOM ,ucPacoteIN,3);
return iTotalEscrito;
}

void IGerenciadorEquipamento::TraduzMens(unsigned char *ucPacote, DWORD
miTamanho)
{
int iCanal;
double dLitros;
char cPulsos[8];
double dPulsos;
char parcelaPacote;
char cInd;
int iInd;
int k;

dLitros = 0;


iCanal = ((((BYTE)ucPacote[1])-49)*8);
iInd = ucPacote[3] & 0x0F;

switch(iInd)
{
case 0:
iCanal += ((((BYTE)ucPacote[4])-47)+100);
printf("Bomba %i ligada\n",iCanal-100);
break;
case 1:
iCanal += ((((BYTE)ucPacote[4])-47)+100);
printf("Bomba %i desligada\n",iCanal-100);

dPulsos = 0;
k=0;
ZeroMemory(cPulsos,8);
for (int i=5;i<13;i++)
{
cPulsos[k] = ucPacote;
k++;
}
dPulsos = atof(cPulsos);

dLitros = round(dPulsos/1*100)/100;

if ((iCanal > 100) && (iCanal < 133))
{
printf("Bomba %i abasteceu %4.2f litros \n",iCanal-100, dLitros);
}
else
printf("Bomba %i abasteceu %4.2f litros \n",iCanal-100, 0.00);

break;
case 7:
printf("APM Reenergizado\n");
break;
}


}

DWORD IGerenciadorEquipamento::ExtraiCMD(unsigned char *ucPacoteIN,
DWORD dStartpos,
DWORD dQtdebytes,
unsigned char* ucPacoteOUT)
{
int i;
DWORD dPosETX = 0;
DWORD dPosSTX = 0;
DWORD dPosDC2 = 0;
bool bOneMoreSYN;
bool bMensTexto;
bool bContinuar = true;
DWORD dBytesToSYN;
int iTotalBytes;

iTotalBytes = 0;
dBytesToSYN = 0;
bMensTexto = false;
bOneMoreSYN = true;
dPosETX = 0;
dPosSTX = 0;
dPosDC2 = 0;

for(i=dQtdebytes-1;(i>=0);i--)
{

if (bOneMoreSYN)
dBytesToSYN++;

switch(ucPacoteIN)
{
case SYN:
if ((dPosETX) && (dPosSTX) && ((dPosSTX-i) == 2) && (dQtdebytes
> dPosETX))
{
bMensTexto = true;
bContinuar = false;
break;
}
else
{
if ((dPosDC2) && (dPosDC2-i) == 2)
{
if ((!bOneMoreSYN) && (dBytesToSYN > 0))
{
return iTotalBytes;
}
else
{
bContinuar = false;
break;
}
}
else
{
if (!bOneMoreSYN) { return 0; }
bOneMoreSYN = false;
dPosDC2 = 0;
dPosETX = 0;
dPosSTX = 0;
}

}
break;

case DC2: dPosDC2 = i; break;
case STX: dPosSTX = i; break;
case ETX: dPosETX = i; break;
}
if (!bContinuar) break;


}

if ((i != 0xFFFF) && (ucPacoteIN == SYN))
{
if (bMensTexto)
dPosETX++;
else
dPosETX = dPosDC2;

for(int j=i;j<=dPosETX;j++)
{
ucPacoteOUT[iTotalBytes] = ucPacoteIN[j];
iTotalBytes++;
}
}
return iTotalBytes;
}

IGerenciadorEquipamento::IGerenciadorEquipamento(char *mcPortaSerial,
DWORD mdwBaudRate,
BYTE mbyByteSize,
BYTE mbyTipoParidade)
{
cPortaSerial = mcPortaSerial;
dwBaudRate = mdwBaudRate;
mbyTipoParidade = mbyTipoParidade;
mbyByteSize = mbyByteSize;
hSerial = INVALID_HANDLE_VALUE;
conectado = false;
bRX_In_Progress = false;
bTX_In_Progress = false;
ConfControl.detectaprot = true;
ConfControl.tentativas = 0;
ConfControl.controladora = 0;

}

IGerenciadorEquipamento::~IGerenciadorEquipamento()
{
conectado = false;
cPortaSerial = "";
dwBaudRate = 0;
byTipoParidade = SERIAL_PARITY_NONE;
byByteSize = 0;

if (GetThreadHND()!=0)
WaitForSingleObject(GetThreadHND(), 2000);

bRX_In_Progress = false;
bTX_In_Progress = false;

if (hSerial != INVALID_HANDLE_VALUE)
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;
}

int IGerenciadorEquipamento::ConfigTimeouts(COMMTIMEOUTS mCommtimeout)
{

// configura os timeouts da Porta Serial
mCommtimeout.ReadIntervalTimeout = 20;
mCommtimeout.ReadTotalTimeoutMultiplier = 1;
mCommtimeout.ReadTotalTimeoutConstant = 20;
mCommtimeout.WriteTotalTimeoutMultiplier = 5;
mCommtimeout.WriteTotalTimeoutConstant = 5;

return SetCommTimeouts(hSerial,&mCommtimeout);
}

int IGerenciadorEquipamento::ConfigDCB(DCB mDCB)
{
// recupera as informações do DCB
if (!GetCommState(hSerial,&mDCB))
{
CloseHandle(hSerial);
return ERROR_INVALID_HANDLE;
}


// set DCB to configure the serial port
mDCB.DCBlength = sizeof(mDCB);

/* ---------- Serial Port Config ------- */
mDCB.BaudRate = dwBaudRate;

switch(byTipoParidade)
{
case SERIAL_PARITY_NONE:
mDCB.Parity = NOPARITY;
mDCB.fParity = 0;
break;
case SERIAL_PARITY_EVEN:
mDCB.Parity = EVENPARITY;
mDCB.fParity = 1;
break;
case SERIAL_PARITY_ODD:
mDCB.Parity = ODDPARITY;
mDCB.fParity = 1;
break;
}

mDCB.StopBits = ONESTOPBIT;
mDCB.ByteSize = 8;
mDCB.fBinary = 0;
mDCB.fAbortOnError = 0;
mDCB.wReserved = 0;
mDCB.XonLim = 100;
mDCB.XoffLim = 100;
mDCB.XonChar = 0x0D;
mDCB.XoffChar = 0x0A;
mDCB.ErrorChar = 0;
mDCB.EofChar = 0;
mDCB.EvtChar = 0;
mDCB.wReserved1 = 0;

return SetCommState(hSerial,&mDCB);

}

int IGerenciadorEquipamento::AtivaEquipamento(BOOL mbIniciaThread)
{
int iErro;
DCB dcb;
int i;

COMMTIMEOUTS cto;


if (hSerial != INVALID_HANDLE_VALUE)
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;

if (cPortaSerial != "")
{
iErro = 0;

hSerial = CreateFile(cPortaSerial, // filename
GENERIC_READ | GENERIC_WRITE, // acesso
desejado
0, // modo de
compartilhamento
NULL, // atributos
de segurança
OPEN_EXISTING, // disposição
da criação do arquivo
FILE_FLAG_NO_BUFFERING,
// flag de criação
NULL); // indica se
pode ou não copiar os
// atributos do
arquivo atual para outro
// arquivo
if (hSerial != INVALID_HANDLE_VALUE)
{
bConectado = true;

// aplica os timeous
if (!ConfigTimeouts(cto))
iErro = 2;

// aplica o DCB
if (!ConfigDCB(dcb))
iErro = 4;

}
}
else
iErro = -2;

/* --------------------------------------------- */
if (iErro > 0)
{
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;
}
else
{

HANDLE hThread1;
DWORD dThreadID1;
if(mbIniciaThread)
{
printf("Connected ! \n");

hThread1 = CreateThread(NULL, // default
security attributes
0, // use default
stack size
(DWORD (_stdcall *)(void *))ComSendRecv,
// thread function
(void*)this, // argument to thread
function
0, // use default
creation flags
&dThreadID1); // returns the
thread identifier

*/

}
}

/* --------------------------------------------- */
return iErro;

}

int IGerenciadorEquipamento::DesativaEquipamento(BOOL mbFinalizaThread)
{
conectado = false;

if(mbFinalizaThread)
{

}
if (hSerial != INVALID_HANDLE_VALUE)
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;


if (this->GetThreadHND())
{
if (WaitForSingleObject (this->GetThreadHND(), 2000) == WAIT_TIMEOUT)
{
TerminateThread (this->GetThreadHND(), 1);
CloseHandle (this->GetThreadHND());
}
else CloseHandle (this->GetThreadHND());
}
CloseHandle(this->GetThreadHND());

printf("Disconnected ! \n");

}

int IGerenciadorEquipamento::EscreveMensagem(HANDLE hSerialCOM,unsigned
char* mcMensagem, int miTamanho)

{
char cTXBuffer[SERIAL_MAX_RX];
DWORD iQtdebytesEscritos;
int iTamanhoBuffer = 0;
int iSuccess = 0;
int Error = 0;
HANDLE hCom;




if (!bTX_In_Progress)
{
PurgeComm(hSerialCOM,PURGE_TXCLEAR | PURGE_RXCLEAR);
//hCom = hSerialCOM;

iSuccess = WriteFile(hSerialCOM,
mcMensagem,
miTamanho,
&iQtdebytesEscritos,
NULL);

if (!iSuccess)
{
// failure
if((Error = GetLastError()) != ERROR_IO_PENDING )
printf("erro: %i , qtde: %i => WriteFile error (not pending)\
n", Error,iQtdebytesEscritos & 0xFFFF);
}

bTX_In_Progress = false;

}

return iQtdebytesEscritos;
}


int IGerenciadorEquipamento::LeMensagem(HANDLE hSerialCOM,unsigned char*
mcMensagem, int miTamanho)
{
DWORD iQtdebytesLidos;
DWORD iLenMensagem = 0;
int iSuccess = 0;
int Error = 0;
HANDLE hCom;

ZeroMemory(mcMensagem,SERIAL_MAX_RX);

if (!bRX_In_Progress)
{
// locking reading
bRX_In_Progress = true;
//hCom = hSerialCOM;

// starting a new read
iSuccess = ReadFile(hSerialCOM, // handle do arquivo
mcMensagem, // buffer de leitura
miTamanho, // número de bytes a serem lidos
&iQtdebytesLidos, // número de bytes realmente
lidos
NULL); // usado para leitura
concorrente
// da serial

if (!iSuccess)
{
// failure
if((Error = GetLastError()) != ERROR_IO_PENDING)
{
printf("erro: %i , qtde: %i => Readfile error (not pending)\
n", Error,iQtdebytesLidos & 0xFFFF);
}
}
bRX_In_Progress = false;
}

return iQtdebytesLidos;
}

void IGerenciadorEquipamento::purgeSerial(void)
{
PurgeComm(hSerial,PURGE_TXCLEAR | PURGE_RXCLEAR);
}

bool IGerenciadorEquipamento::VerificaEstado(void)
{
// return (bRX_In_Progress || bTX_In_Progress);
}

int ComSendRecv(LPVOID p)
{
IGerenciadorEquipamento* pIGE;

pIGE = (IGerenciadorEquipamento*)p;

if (pIGE !=0)
return pIGE->Run();

}

BYTE CalculaCRC(unsigned char *msg, int qtdeBytes)
{
BYTE valor_crc = 0;

for (int i=0; i<=qtdeBytes-1;i++)
{
valor_crc += msg;
}
return valor_crc;
}

int IGerenciadorEquipamento::Run(void)
{
bool bDone;
unsigned char ucPacoteIN[256];
unsigned char ucPacoteOUT[256];
unsigned char ucPacoteCMD[256];
int iRetry;
BYTE byPacoteCRC, byPacoteCalcCRC;
// char *lista[3];

int iTotalLido = 0;
int iTamPacoteCMD = 0;

bDone = false;
bRX_In_Progress = false;
bTX_In_Progress = false;

GetLastError(); // just to clear any pending error

HANDLE hComm = hSerial;

char cmd[5];

while(!bDone)
{

Sleep(1000);

if (ConfControl.detectaprot)
EnviaPOLLING(hSerial);

if (ConfControl.controladora)
{
iTotalLido = LeMensagem(hSerial ,pacoteOUT,30);
if (iTotalLido)
{
ConcedePrivilegio(hSerial,ConfControl.controladora);
ConfControl.tentativas = 5;
}
ConfControl.tentativas--;
if (ConfControl.tentativas <= 0)
{
ConfControl.tentativas = 0;
ConfControl.controladora = 0;
}
}

ConcedePrivilegio(hSerial,0);

iRetry = 1;

while (iRetry >0)
{

iRetry--;

iTotalLido = LeMensagem(hSerial,ucPacoteOUT,30);
if (iTotalLido)
{
ZeroMemory(ucPacoteCMD,SERIAL_MAX_RX);

iTamPacoteCMD = ExtraiCMD
(ucPacoteOUT,1,iTotalLido,ucPacoteCMD);
if (iTamPacoteCMD > 0)
{

ZeroMemory(ucPacoteIN,SERIAL_MAX_RX);

switch(ucPacoteCMD[2])
{
case DC2:
if (isdigit(ucPacoteCMD[1]))
{
iRetry = 1;
ConcedePrivilegio(hSerial,((BYTE)ucPacoteCMD[1]
-48));
}
break;

case STX:
byPacoteCalcCRC = CalculaCRC
(ucPacoteCMD,iTamPacoteCMD-1);
byPacoteCRC = (BYTE)ucPacoteCMD[iTamPacoteCMD-1];
if (byPacoteCRC == byPacoteCalcCRC)
{
iRetry = 0;
if (isdigit(ucPacoteCMD[1]))
{

ConfControl.controladora = (BYTE)(
(ucPacoteCMD[1])- 48);
ConfControl.tentativas = 5;
ConcedePrivilegio(hSerial,((BYTE)ucPacoteCMD
[1]-48));
PurgeComm(hSerial, PURGE_RXCLEAR);
}
TraduzMens(ucPacoteCMD,iTamPacoteCMD);

/* teste do comando pede abastecimento
if (gets(cmd) != NULL)
{
y = dividePorCaractere(cmd," ",lista);

if (y > 1)
{
if (strcmp(lista[0],"abast") == 0)
{
PedeAbastecimentoManual(atoi(lista[1])
+100);
}
}
if (strcmp(cmd,"quit") == 0)
{
break;
}
}
*/
}
break;
}
}
}

}

}
DesativaEquipamento(true);
}

/*--------------------------------------------------------------------*/
/* until here */

/* cut */
/*--------------------------------------------------------------------*/
/* Main Exec Code */

/***********************************************************************
main.cpp - The main() routine for all the "Basic Winsock" suite of
programs from the Winsock Programmer's FAQ. This function parses
the command line, starts up Winsock, and calls an external function
called DoWinsock to do the actual work.

This program is hereby released into the public domain. There is
ABSOLUTELY NO WARRANTY WHATSOEVER for this product. Caveat hacker.
***********************************************************************/

#include "IThreadConnect.hpp"
#include "IGerenciadorEquipamento.hpp"
#include <windows.h>
#include <vector>
#include <algorithm>

using namespace std;

BOOL CtrlHandler(DWORD fdwCtrlType)
{
switch( fdwCtrlType )
{
// Handle the CTRL+C signal.
case CTRL_C_EVENT:
//printf( "Ctrl-C event\n\n" );
Beep( 750, 300 );
return( TRUE );

// CTRL+CLOSE: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
Beep( 600, 200 );
//printf( "Ctrl-Close event\n\n" );
return( TRUE );

// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
Beep( 900, 200 );
//printf( "Ctrl-Break event\n\n" );
return FALSE;

case CTRL_LOGOFF_EVENT:
Beep( 1000, 200 );
//printf( "Ctrl-Logoff event\n\n" );
return FALSE;

case CTRL_SHUTDOWN_EVENT:
Beep( 750, 500 );
//printf( "Ctrl-Shutdown event\n\n" );
return FALSE;

default:
return FALSE;
}
system("PAUSE");
}

//// main //////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
IThreadConnect threadConnect(0);
IGerenciadorEquipamento gerente1("COM1", 9600, 8, SERIAL_PARITY_NONE);
// IGerenciadorEquipamento gerente2("COM3", 9600, 8, SERIAL_PARITY_NONE);
// IGerenciadorEquipamento gerente3("COM3", 9600, 8, SERIAL_PARITY_NONE);

vector<IGerenciadorEquipamento> vEquipamento;



if( SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE))
{

gerente1.AtivaEquipamento();
printf("1 - Connected ! \n");

}
else
printf( "\nERROR: Could not set control handler");
//system("PAUSE");


// exit(1);
}

/*--------------------------------------------------------------------*/
/* until here */

Best Regards,
Berti
 
Replies continue below

Recommended for you

Status
Not open for further replies.
Back
Top