my goal: I`m writing an application which writes a file to the serial port 128 bytes at a time (137 total, with ModBUS header and CRC) and waits for the reply. The writing I have managed to implement successfully. After sending a 137 byte packet I would like to wait on the serial com for a reply and process it, in case that modbus exception is thrown.
my problem: The ReadFile function returns 170 which, from windows documentation, is 170 (0xAA) - The requested resource is in use. The only resource I am actually using is the serial port handle, which I doubt that it is this, the error is referring to.
Note - - not using available ModBUS libraries because I use the address registers in a specific way, needing full control - I am using overlapped I/O only because (according to WinApi doc) ReadFile never returns if no bytes come at the serial port; If timeouts are require overlapped access is a must (correct me if I`m wrong). - I have a 2 sec max timeout (timeout for actually waiting for the reply) and 20 ms between bytes; if more than 20 ms between bytes pass I assume that no more bytes are coming;
Has anyone had any previous experience working with ReadFile and possibly Erro 170? Appreciate all the help I can get.
part of my code:
u8 WaitModBusReply(void)
{
u8 i = 0;
u8 ReplyStatus = 0xAA;
u8 ReplyBuff[ReplyBuffSize];
u8 * ptr = &ReplyBuff[0];
static u16 TotalRX_Bytes;
DWORD dwCommEvent;
DWORD dwBytesRead;
COMSTAT ComStatus;
DWORD comErrors = 0;
OVERLAPPED read_s = {0};
read_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
for (int z=0; z< ReplyBuffSize; z++)
ReplyBuff[z] = 0;
ClearCommError(ModBUS_Port, &comErrors, &ComStatus);
ResetEvent(read_s.hEvent);
if ( !WaitCommEvent(ModBUS_Port, &dwCommEvent, &read_s) )
{
//byte_timeout += MCU_Getms_TimeConsumption();
if ( (ReadFile(ModBUS_Port, ptr+TotalRX_Bytes, ReplyBuffSize-
TotalRX_Bytes, &dwBytesRead, NULL) )) //&dwBytesRead &modbus_reply
{
fprintf(stderr, "\n EXEC 3");
// ReadFile(PC_TestCenterPort, pBufPtr+TotalRX_Bytes, BufSize-
TotalRX_Bytes, &BytesRead, NULL);
TotalRX_Bytes += dwBytesRead;
i++;
ReplyStatus = Reply_Received;
}
}
else
printf("Error setting Com event mask:%d ", GetLastError());
if ( ReplyStatus == Reply_Received)
{
fprintf(stderr, "\nExit error3: %d\n", GetLastError() );
if ( (i == 4) ) // Exception returned. Parse it
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = ReplyBuff[i-2];
}
else if ( (i == 7) ) // Reply returned
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = Reply_OK;
}
}
/*
for ( int j=0; j<= 256; j++)
printf("\nReplyBuff[%d]: %X", j, ReplyBuff[j]); */
return ReplyStatus;
}
The logic for checking the reply array is not implemented so ignore that part. This function is called by:
u8 SerialDataSend(void)
{
u8 t_status = BufferSent;
int write_status = -1;
int read_status = -1;
DWORD bytes_written = 0;
OVERLAPPED write_s;
memset(&write_s, 0, sizeof(write_s));
write_s.Internal = 0;
write_s.InternalHigh = 0;
write_s.Offset = 0;
write_s.OffsetHigh = 0;
write_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if ( !SerialInit() )
{
while (!t_status)
{
fprintf(stderr, "Starting transmission -\n");
while(packages_left > 0 && !t_status)
{
write_status = WriteFile(ModBUS_Port, ModBUS_Buffer(), 137,
&bytes_written, &write_s); //&write_s
fprintf(stderr,"\r ModBUS transaction - Packages left:%4d",
packages_left);
if( write_status ) // Return values for success and
overlapped access ongoing
{
fprintf(stderr, "Error :%d.\n", GetLastError());
t_status = BufferFailed;
CloseHandle(ModBUS_Port);
break;
}
//FlushFileBuffers(ModBUS_Port);
read_status = WaitModBusReply();
printf("READ STATUS: %d\n", read_status);
if ( !read_status && !write_status )
{
fprintf(stderr, "\n------------------------------------------------------------");
fprintf(stderr, "\n Exception occurred: %X\n",
read_status);
t_status = BufferFailed;
Sleep(1);
break;
}
packages_left--;
Sleep(200);
}
//printf("EXEC 1\n");
if (!t_status)
{
fprintf(stderr, "\n\nTransaction Complete. Bytes written :
%d\n", FileSize);
packages_left = 10;
}
break;
}
fclose(HMI_Program);
if ( t_status != BufferFailed )
{
fprintf(stderr, "Closing serial port - ");
if ( !CloseHandle(ModBUS_Port) )
fprintf(stderr, "Error :%d.\n", GetLastError());
else
fprintf(stderr, "OK.\n");
}
}
fflush(stdout);
fflush(stderr);
return t_status;
}
and the function which initializes the Serial port:
u8 SerialInit(void)
{
memset(&SerialSettings,0,sizeof(SerialSettings));
SerialSettings.DCBlength = sizeof(SerialSettings);
SerialSettings.BaudRate = CBR_115200;
SerialSettings.ByteSize = 8;
SerialSettings.StopBits = TWOSTOPBITS;
SerialSettings.Parity = NOPARITY;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutConstant = 2000;
timeouts.ReadTotalTimeoutMultiplier = 1 ;
memset(&timeouts,0,sizeof(timeouts));
fprintf(stderr, "Opening serial port - ");
sprintf(COM_Port, "\\\\.\\COM%d", port_no);
ModBUS_Port = CreateFile(COM_Port, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (ModBUS_Port == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error\n\n");
else
fprintf(stderr, "OK\n");
if ( !GetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error getting device state.");
CloseHandle(ModBUS_Port);
}
else if( !SetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error setting device parameters.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommTimeouts(ModBUS_Port, &timeouts) )
{
fprintf(stderr, "Error setting timeouts.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommMask(ModBUS_Port, EV_RXCHAR | EV_ERR ) )
{
fprintf(stderr, "\nError setting com mask.");
CloseHandle(ModBUS_Port);
}
return GetLastError();
}
Thanks.