Есть такая вот проблема.
К СОМ порту у меня посредством MODBUS подключен некий девайс, который принимает запрос, а потом отдает ответ.
Изначально использовалось асинхронное подключение, но метод WriteFile возвращал статус "997", т.е. ERROR_IO_PENDING.
Я написал тестовое приложение, используя уже синхронное подключение. Оно работает и возвращает правильные ответы на запросы. Но когда я перенес эти изменения в проект, ReadFile возвращает пустой буфер. Подскажите, пожалуйста, как можно решить эту проблему.
Код работы по синхронному подключению:
P.S. Повторюсь, в тестовом приложении, где присутствует только эта функция, все работает отлично.
function ExecCmd(CmdID: Byte; CmdParams: array of Byte): Boolean;
var SendBuf: TSDCTBuffer;
I, Count: Integer;
OutB: Cardinal;
b: Boolean;
s: string;
ComStat: TComStat;
Errs: DWORD;
DCB: TDCB;
Timeouts: _COMMTIMEOUTS;
Handle: Cardinal;
Overlapped: POverlapped;
begin
Result := False;
FillChar(SendBuf, SizeOf(SendBuf), 0);
FillChar(FOutBuffer, SizeOf(SendBuf), 0);
SendBuf[0] := CmdParams[0];
SendBuf[1] := CmdID;
for I := 2 to SizeOf(CmdParams) - 1 do SendBuf[I + 1] := CmdParams[I];
SendBuf[SizeOf(CmdParams) + 1] := CRCXOR(SendBuf, SizeOf(CmdParams));
SendBuf[SizeOf(CmdParams) + 2] := CRCOR(SendBuf, SizeOf(CmdParams));
I := 0;
repeat
try
new(Overlapped);
Handle := CreateFile(PChar('\\.\COM1'), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if Handle <> INVALID_HANDLE_VALUE then begin
PurgeComm(Handle, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
with DCB do
begin
BaudRate := CBR_9600;
Parity := NOPARITY;
StopBits := ONESTOPBIT;
ByteSize := 8;
XonLim := 100;
XoffLim := 100;
ByteSize := 8;
end;
if SetCommState(Handle, DCB) then begin
if SetCommMask (Handle, EV_BREAK or EV_RXCHAR) then begin
GetCommTimeouts(Handle, Timeouts);
PurgeComm(Handle, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
with Timeouts do begin
ReadIntervalTimeout := 20;
ReadTotalTimeoutMultiplier := 1;
ReadTotalTimeoutConstant := 300;
WriteTotalTimeoutMultiplier := 20;
WriteTotalTimeoutConstant := 300;
end;
SetCommTimeouts(Handle, Timeouts);
Overlapped.hEvent := CreateEvent(nil, True, True, nil);
PurgeComm(Handle, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
end;
end;
b := True;
end;
if b then begin
b := WriteFile(Handle, SendBuf, SizeOf(CmdParams) + SDCTCountDiff, OutB, Overlapped);
if not b then s := IntToStr(GetLastError);
if b then begin
b := ReadFile(Handle, FOutBuffer, 29, OutB, Overlapped); // <<<===== Тут и возвращается нулевой буфер
if not b then s := IntToStr(GetLastError);
PurgeComm(Handle, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
end;
end;
CloseHandle(Overlapped.hEvent);
CloseHandle(Handle);
Result := True;
Break;
except
end;
end;
until False;
SetLength(FOutParams, FOutBuffer[1]);
for I := 0 to FOutBuffer[1] - 1 do FOutParams[I] := FOutBuffer[I + 2];
end;