Работа с СОМ портом
От: IRINIC Украина  
Дата: 19.02.11 18:35
Оценка:
Есть такая вот проблема.
К СОМ порту у меня посредством 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;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.