By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,357 Members | 1,021 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,357 IT Pros & Developers. It's quick & easy.

Problems with Serial Comm Handle

P: n/a
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[i];
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[i])
{
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[i] == SYN))
{
if (bMensTexto)
dPosETX++;
else
dPosETX = dPosDC2;

for(int j=i;j<=dPosETX;j++)
{
ucPacoteOUT[iTotalBytes] = ucPacoteIN[j];
iTotalBytes++;
}
}
return iTotalBytes;
}
IGerenciadorEquipamento::IGerenciadorEquipamento(c har *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(COMMTIMEOU TS 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[i];
}
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,
Leandro

--
Message posted via http://www.dotnetmonster.com
Nov 17 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
"Leandro Berti via DotNetMonster.com" <fo***@nospam.DotNetMonster.com> wrote in message news:<01******************************@DotNetMonst er.com>...
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[i];
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[i])
{
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[i] == SYN))
{
if (bMensTexto)
dPosETX++;
else
dPosETX = dPosDC2;

for(int j=i;j<=dPosETX;j++)
{
ucPacoteOUT[iTotalBytes] = ucPacoteIN[j];
iTotalBytes++;
}
}
return iTotalBytes;
}
IGerenciadorEquipamento::IGerenciadorEquipamento(c har *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(COMMTIMEOU TS 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[i];
}
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,
Leandro

Hi Leandro

It seems that your primary thread creates the new thread and then
return and exit the process, causing the ~IGerenciadorEquipamento
destructor to run, hence closing the handle.

To find out if this is the problem, let the primary thread to Sleep()
after it creates the new thread.

Alon Fliess
Nov 17 '05 #2

P: n/a
Hi Alon,

Thanks for the help.
I try to put a Sleep() after the CreateThread() but doesn?t work and i mark
the breakpoint at the Destructor method and the execution don?t reach it.
The problem is at the beginning the communication work, then goes to
error state:
error: 6 => WriteFile error (not pending)
error: 6 => Readfile error (not pending)
Best Regards,
Berti

--
Message posted via http://www.dotnetmonster.com
Nov 17 '05 #3

P: n/a
Berti,

Can you tell if the handle value is the same right after you create it and
at the time when you get errors?

Your code looks ok (as long as you take into account Alon's suggestion).
One thing I'd suggest you change is replace CreateThread() with
_beginthread[ex](). You should not use the former in a multi-threaded
environment unless you are absolutely sure that your thread proc will not
call (implicitly or explicitly) runtime library functions that utilize
thread local storage.

I've written quite a bit of code that does rs232 to a lot of different
devices. Under Win32 I've done it with and without overlapped io and always
in a multi-threaded environment. This stuff seems to work fine. I don't
recall any gotchas. So, as in most of the cases, it's gotta be something in
your code :)

Bogdan
"Leandro Berti via DotNetMonster.com" <fo***@DotNetMonster.com> wrote in
message news:9f******************************@DotNetMonste r.com...
Hi Alon,

Thanks for the help.
I try to put a Sleep() after the CreateThread() but doesn?t work and i
mark
the breakpoint at the Destructor method and the execution don?t reach it.
The problem is at the beginning the communication work, then goes to
error state:
error: 6 => WriteFile error (not pending)
error: 6 => Readfile error (not pending)
Best Regards,
Berti

--
Message posted via http://www.dotnetmonster.com

Nov 17 '05 #4

P: n/a
Hi Bogdan,

Answering your first question the Handle value is the same in all the cases.
I try your sugestion changed the CreateThread() to _beginthread[ex] and
doesn't work.
That is very weird because everything seems ok.
Can you tell me more about that shouldn?t use CreatThread in a Multi-thread
environment?
And maybe send me (le***********@gmail.com) any code with multi-thread
architecture.

Best Regards,
Berti

--
Message posted via http://www.dotnetmonster.com
Nov 17 '05 #5

P: n/a
Berti,

It is very unlikely that CreateThread() vs _beginthread() issue is causing
your problems. Still, it is a good practice to use _beginthread() when you
use CRT. The compiler/linker will force you to use multi-threaded libraries
(one less thing to remember) and you'll make sure that all static buffers
are properly cleaned up when threads terminate. See "Multithreading"
(specifically "Multithreading with C and Win32") in MSDN.

Your problems might be caused by a lack of synchronization when it comes to
access to class members. You've got quite a bit of public methods (I'm not
sure if this is intentional) that could potentially lead to race conditions.
Some of the methods take a comm handle which is also confusing. Another
thing that you might try to avoid is to pass structures by value (e.g. DCB,
timeouts) - simply unnecessary burden on the stack.

I'd suggest that you start with refactoring the code so the serial comms
related stuff is not mixed with your application code. I'm pretty sure that
this would make it much easier for you and guys in this newsgroup to
troubleshoot problems.

Let's see if I can be of any help off-line. I'll send you an e-mail later
today.

Bogdan
"Leandro Berti via DotNetMonster.com" <fo***@DotNetMonster.com> wrote in
message news:e7******************************@DotNetMonste r.com...
Hi Bogdan,

Answering your first question the Handle value is the same in all the
cases.
I try your sugestion changed the CreateThread() to _beginthread[ex] and
doesn't work.
That is very weird because everything seems ok.
Can you tell me more about that shouldn?t use CreatThread in a
Multi-thread
environment?
And maybe send me (le***********@gmail.com) any code with multi-thread
architecture.

Best Regards,
Berti

--
Message posted via http://www.dotnetmonster.com

Nov 17 '05 #6

P: n/a
"Leandro Berti via DotNetMonster.com" <fo***@DotNetMonster.com> wrote in message news:<e7******************************@DotNetMonst er.com>...
Hi Bogdan,

Answering your first question the Handle value is the same in all the cases.
I try your sugestion changed the CreateThread() to _beginthread[ex] and
doesn't work.
That is very weird because everything seems ok.
Can you tell me more about that shouldn?t use CreatThread in a Multi-thread
environment?
And maybe send me (le***********@gmail.com) any code with multi-thread
architecture.

Best Regards,
Berti


CreateThread is a Win32 API that does not take into account the C++
runtime. When you call some of the C/C++ runtime functions, they may
need to refer to a buffer created and initiated by the runtime. The
main thread creates this buffer before it calls your main() function.
In MT program, each thread should use its own buffer, so there has to
be a way to create this buffer for each of them. Using the
_beginthread[ex]() function lets the runtime prepare this buffer. It
also add a default exception handler around your code (for un-handled
exceptions and ANSI-C signal handling, and handles the atexit()
function (hence it handles destructors of static objects in C++) ).
CreateThread still works because whenever you call a function that
needs the buffer it checks if the buffer does not exist, and if so it
creates one. however this buffer will stay in memory even if your
thread has exit and there will be no other c/c++ support (signal and
atexit()). If you use _beginthread, c/c++ runtime will free the
buffer. There is one case the C/C++ runtime can create/destroy the
buffer for you even if you use CreateThread, and it is when you use
the DLL version of the runtime. The runtime uses the
DLL_THREAD_ATTACHED/DETACHED to handle initialization/finalization.
In any case you always have to use the MT runtime (even if you use
CreateThread) and this is one of the main reason to use the
_beginthread[ex] function, it forces you to compile in MT.

After all this explanation, I don't think that CreateThread is your
problem.
First, check if you compile with the MT version of the runtime.
Second, use Process Explorer from www.sysinternals.com. Check if the
handle is valid (you may also see when it becomes invalid - it will
become red and will disappear).

Alon Fliess
CTO
The Sela Group
Nov 17 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.