Hi,
I have a problem with the serial communication. I need to write a C++
program that makes synchronous communication in a NON-trheaded
application.
My program is quite simple, the basic commands are:
HANDLE h = CreateFile(porta, GENERIC_READ|GENERIC_WRITE, 0,NULL,
OPEN_EXISTING, 0,NULL);
WriteFile(h,command,write,&write,NULL);
ReadFile(h, buffer, 64, &read, NULL);
on the other side of the serial communication there is a robot; I can
communicate to it via physical cable (COM1) or a bluetooth module
(COM4). The two com have the same settings.
The program seems to work with COM1, however it works for a while and
get stucked while using COM4. My idea is that the bluetooth module can
not answer anymore.
- I can I prevent my program to stop forever?
- why the timeout seems not to be working?
- if I use a WaitCommEvent with a non overlapped structure is there a
way to pass it a timeout as well? from the MSDN help it seems that in
such a case it will wait for ever
- can I check if there is at least 1 character waiting in the com
before calling the ReadFile function?
thanks in advance,
gianluca
here is the complete code:
#include "stdafx.h"
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void MySettings(HANDLE h, COMMTIMEOUTS cto, DCB porta_sett, int
speed);
int MyRead(HANDLE h, char buffer[64], bool flag_debug, double
timeout);
void MyWrite(HANDLE h, char *comando, bool flag_debug);
void PrintError( LPCSTR str);
int main(void) {
char *porta = "com1";
int speed = 115200; //38400; //115200;
char *comando = "N\n";
COMMTIMEOUTS cto = { 2, 1, 10, 1, 10};
DCB porta_sett; // device control block
memset(&porta_sett,0,sizeof(porta_sett));
time_t t1, t2, tfly1, tfly2;
double tfly, min = 1000, max = 0, avg = 0;
int loop = 10000, n_failed = 0, i =0;
char buffer[64];
int buffer_size;
bool flag_debug = true;
double timeout = 100; // ms
printf("\n porta : %s",porta);
printf("\n speed : %d bit/s",speed);
printf("\n command : %s",comando);
printf(" loop : %d",loop);
printf("\n timeout : %2.f ms",timeout);
HANDLE h = CreateFile(porta, GENERIC_READ|GENERIC_WRITE, 0,NULL,
OPEN_EXISTING, 0,NULL);
if(h == INVALID_HANDLE_VALUE) {
printf("E012_Failed to open port");
} else {
MySettings(h, cto, porta_sett, speed);
//buffer_size = MyRead(h, buffer, flag_debug, timeout);
t1 = clock();
for (i=0; i<loop; i++) {
tfly1 = clock();
if (flag_debug) printf("\nloop n. %d - ",i);
MyWrite(h, comando, flag_debug);
buffer_size = MyRead(h, buffer, flag_debug, timeout);
n_failed = buffer_size<1 ? n_failed + 1 : n_failed;
tfly2 = clock();
tfly = (double)1000.0*(tfly2-tfly1)/CLOCKS_PER_SEC;
min = tfly<min ? tfly : min;
max = tfly>max ? tfly : max;
avg += tfly/((double)loop);
}
t2 = clock();
// output stats to the console
printf("\n\nmin/avg/max = %.0f/%.2f/%.0f ms",min,avg,max);
printf("\ntotal elapsed time : %ld
s",(t2-t1)/CLOCKS_PER_SEC);
printf("\ntotal average sampling : %.0f
ms",(double)(1000.0*(t2-t1)/CLOCKS_PER_SEC)/loop);
printf("\nfailed messagges : %d
(%.2f%%)",n_failed,(double)100.0*n_failed/loop);
printf("\ntotal messages send : %d\n",loop);
CloseHandle(h);
}
return 0;
}
/*---------------------------------
settings of the port
---------------------------------*/
void MySettings(HANDLE h, COMMTIMEOUTS cto, DCB porta_sett, int speed)
{
if(!SetCommTimeouts(h,&cto))
printf("E013_SetCommTimeouts failed\n");
// memset(&porta_sett,0,sizeof(porta_sett));
GetCommState( h, &porta_sett );
porta_sett.DCBlength = sizeof(porta_sett);
porta_sett.BaudRate = speed;
porta_sett.fBinary = 1;
porta_sett.fDtrControl = DTR_CONTROL_ENABLE;
porta_sett.fRtsControl = RTS_CONTROL_ENABLE;
porta_sett.Parity = NOPARITY;
porta_sett.StopBits = ONESTOPBIT;
porta_sett.ByteSize = 8;
if(!SetCommState(h,&porta_sett))
printf("E014_SetCommState failed\n");
if(!SetCommMask(h, EV_RXCHAR))
printf("E007_SetCommMask failed\n");
}
/*---------------------------------
read from the port
return zero if fails
---------------------------------*/
int MyRead(HANDLE h, char buffer[64], bool flag_debug, double timeout)
{
DWORD read = 0;
char buf;
int buffer_size = 0, i =0;
bool continua = true;
time_t t1;//, t2;
double elapsed = 0.0;
OVERLAPPED ov;
DWORD mask;
ZeroMemory(&ov,sizeof(ov));
// create event for overlapped I/O
ov.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
if(ov.hEvent == INVALID_HANDLE_VALUE)
printf("E006_CreateEvent failed");
if( !WaitCommEvent(h,&mask,&ov) ) {
DWORD e = GetLastError();
if( e == ERROR_IO_PENDING ) {
DWORD r;
if( !GetOverlappedResult(h,&ov,&r,TRUE) ) {
PrintError("E008_GetOverlappedResult failed");
}
} else {
PrintError("E009_WaitCommEvent failed");
}
}
continua = ((mask==1)&(EV_RXCHAR==1));
t1 = clock();
while (continua) {
//printf("|");
/* if(ReadFile(h, &buf, 1, &read, NULL) != 0) {
if(read > 0) {
buffer[buffer_size] = buf;
buffer_size += 1;
}
} else
printf("-2%d-",mask); */
ReadFile(h, buffer, 64, &read, NULL);
buffer_size = read;
elapsed = (double)1000.0*(clock()-t1)/CLOCKS_PER_SEC;
if (buffer[buffer_size-1]=='\n') {
continua = false;
} else if (buffer_size>45) {
buffer_size = 0;
continua = false;
}/* else if (elapsed>timeout) {
buffer_size = -1;
continua = false;
}*/
}
if ((flag_debug)&&(buffer_size>0)) {
for (i=0;i<(buffer_size-2);i++)
printf("%c",buffer[i]);
printf(" %4.2f ms",elapsed);
} else if (flag_debug)
if (buffer_size==0)
printf("FAILED : too many characters");
else if (buffer_size==-1)
printf("FAILED : elapsed time %4.2f",elapsed);
// CloseHandle(ov.hEvent); // close the event
return buffer_size;
}
/*---------------------------------
write to the port
---------------------------------*/
void MyWrite(HANDLE h, char *comando, bool flag_debug) {
DWORD write=sizeof(comando)-2;
int len_com = (sizeof(comando)-3), i =0;
if (!WriteFile(h,comando,write,&write,NULL)) {
PrintError("E004_WriteFile failed");
}
if (flag_debug) for (i=0;i<len_com;i++) printf("%c", comando[i]);
//Sleep(10);
}