The program's goal is to endlessly wait for data from the com port. When it receives specific data - it does specific action.
The problem is that the program processes the incoming data 2 times and I can't figure out why.
It was assumed that WaitCommEvent(hCom, &state, NULL); will wait for some data if (state == EV_RXCHAR) to arrive, then we read (ReadFile(hCom, dst, 20, &read, NULL)) and check the data.
With these timeouts I thought, that we will read data until the delay between two bytes is not greater than 20ms or the total reading time is not greater than 20*20+100 ms. After that we processing the data.
comTimeOuts.ReadIntervalTimeout = 20;
comTimeOuts.ReadTotalTimeoutMultiplier = 20;
comTimeOuts.ReadTotalTimeoutConstant = 100;
comTimeOuts.WriteTotalTimeoutMultiplier = 0;
Can you tell please, I was wrong in understanding of the timeout's logic?
If I try to catch data without endless loop - the program processes the data 1 time, not 2.
How can I avoid double processing with infinite loop? Thank you in advance!
Full code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <signal.h>
//#include <stdlib.h>
HANDLE hCom;
HANDLE hEvent;
void diediedie(int sig) {
//puts("Bye, brutal world!");
if (hEvent)
CloseHandle(hEvent);
if (hCom)
CloseHandle(hCom);
exit(1);
}
void comError(HANDLE hCom, char* s) {
printf("%s\n", s);
CloseHandle(hCom);
printf("Press any key to exit...");
_getch();
exit(1);
}
int main()
{
signal(SIGINT, diediedie);
unsigned long int data = 0;
/******************* Port opening *********************/
hCom = CreateFileA("\\\\.\\COM3", // port name
GENERIC_READ, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hCom == INVALID_HANDLE_VALUE)
comError(hCom, "Error in opening serial port");
else
printf("\n Port \\\\.\\COM3 Opened\n");
/******************* Setting DCB structure *********************/
DCB comDCB;
memset(&comDCB, 0, sizeof(comDCB));
comDCB.DCBlength = sizeof(DCB);
comDCB.BaudRate = CBR_9600;
comDCB.ByteSize = 8;
comDCB.Parity = NOPARITY;
comDCB.StopBits = ONESTOPBIT;
comDCB.fBinary = TRUE;
comDCB.fParity = FALSE;
comDCB.fAbortOnError = TRUE;
comDCB.fDtrControl = DTR_CONTROL_DISABLE;
comDCB.fRtsControl = RTS_CONTROL_DISABLE;
comDCB.fInX = FALSE;
comDCB.fOutX = FALSE;
comDCB.XonChar = 0x11;
comDCB.XoffChar = 0x13;
comDCB.fErrorChar = FALSE;
comDCB.fNull = FALSE;
comDCB.fOutxCtsFlow = FALSE;
comDCB.fOutxDsrFlow = FALSE;
comDCB.XonLim = 128;
comDCB.XoffLim = 128;
if (!SetCommState(hCom, &comDCB))
comError(hCom, "Error in SetCommState");
else
printf("\n Setting DCB Structure Successfull\n");
GetCommState(hCom, &comDCB);
printf("\n\tBaudrate = %d\n\tByteSize = %d\n\tStopBits = %d\n\tParity = %d\n", comDCB.BaudRate, comDCB.ByteSize, comDCB.StopBits, comDCB.Parity);
/******************* Setting Timeouts *********************/
COMMTIMEOUTS comTimeOuts;
comTimeOuts.ReadIntervalTimeout = 20;
comTimeOuts.ReadTotalTimeoutMultiplier = 20;
comTimeOuts.ReadTotalTimeoutConstant = 100;
comTimeOuts.WriteTotalTimeoutMultiplier = 0;
comTimeOuts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(hCom, &comTimeOuts))
comError(hCom, "Error in setting timeouts");
else
printf("\n Setting Serial Port Timeouts Successfull\n");
/******************* Setting Buffer *********************/
SetupComm(hCom, 20, 0);
if (!SetupComm(hCom, 20, 0))
comError(hCom, "Error in setting buffer");
unsigned long wait = 0, read = 0, state = 0;
unsigned char dst[20] = { 0 };
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
/* Setting event mask */
if (!SetCommMask(hCom, EV_RXCHAR))
comError(hCom, "Error in setting SetCommMask");
else {
while (1) {
WaitCommEvent(hCom, &state, NULL);
if (state == EV_RXCHAR) {
if (ReadFile(hCom, dst, 20, &read, NULL)) {
printf("%s", dst);
data = atoi(dst);
switch (data) {
case 16724175:
printf("yes\n");
break;
}
}
}
}
}
CloseHandle(hEvent);
CloseHandle(hCom);//Closing the Serial Port
return 0;
}
Output:
Port \\.\COM3 Opened
Setting DCB Structure Successfull
Baudrate = 9600
ByteSize = 8
StopBits = 0
Parity = 0
Setting Serial Port Timeouts Successfull
16718055
16718055
readthe number of bytes actually read, but assumed there will be a nul-terminated string available.... if (!read) { ... }. Yes, it works, thanks! But why did the previous code check the data 2 times (not 1 or not 3 times)? Can't understand the logic.while (1) { WaitCommEvent(hCom, &state, NULL); if (state == EV_RXCHAR) if (ReadFile(hCom, dst, 20, &read, NULL)) { printf("read: %d\n", read); printf("data: %s", dst); ...output is:read: 10 data: 16718055 read: 0 data: 16718055As you can see the loop runs 2 times with each sending and the second time read = 0, Isn't it a crutch usingif (read>0)condition?0yet you handled the previously read data twice. It was placed in the buffer at the first iteration, not the second. If you are going to pass the data as a string, then you must dodst[read] = '\0';and make the buffer big enough.