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
CodePudding user response:
You must always check the return value from input functions. In this case you have ignored it, and processed the input from the first iteration twice. It wasn't sent twice, but on the second iteration was already in the buffer.
Also, you should nul-terminate any data that you are going to pass to a string-handling function. And to do that, the buffer must be big enough. It's usually worth allocating a buffer a little larger than you actually need.
So the modified code is
unsigned char dst[32]; // large enough buffer
//...
while (1) {
WaitCommEvent(hCom, &state, NULL);
if (state == EV_RXCHAR) {
if (ReadFile(hCom, dst, 20, &read, NULL)) {
dst[read] = '\0'; // nul terminate
printf("%s", dst);
data = atoi(dst);
switch (data) {
case 16724175:
printf("yes\n");
break;
}
}
//...