2010. szeptember 20., hétfő

Access the serial port in Windows XP


Problem/Question/Abstract:

How I do to access the serial or paralell port in Windows XP?

Answer:

The example below sends a char 'R' to the port, then reads a line until CR or LF is encountered, then processes a line via ParseData. Then all is repeated until Terminated is True.

procedure ProcessCOMPortData(FPortName: string);
var
  LPortHandle: THandle;
  LInBuffer: array[0..1023] of Char;
  LBytesWritten, LBytesRead: Cardinal;
  LOutBuffer: Char;
  LOverlapped: TOverlapped;
  LEvent: TEvent;
  LOldCommTimeouts, LCommTimeouts: TCommTimeouts;
  LPCommConfig: PCommConfig;
  LCommConfig: TCommConfig;
  CommConfigSize: Cardinal;
  LEOL: Boolean;
  LIndex: Integer;
begin
  ZeroMemory(@LOverlapped, SizeOf(TOverlapped));
  ZeroMemory(@LCommTimeouts, SizeOf(TCommTimeouts));
  ZeroMemory(@LCommConfig, SizeOf(TCommConfig));
  LPortHandle := INVALID_HANDLE_VALUE;
  LEvent := nil;
  LPCommConfig := nil;
  try
    CommConfigSize := 0;
    LPCommConfig := @LCommConfig;
    GetDefaultCommConfig(PChar(FPortName), LPCommConfig^, CommConfigSize);
    GetMem(LPCommConfig, CommConfigSize);
    GetDefaultCommConfig(PChar(FPortName), LPCommConfig^, CommConfigSize);
    LEvent := TEvent.Create(nil, True, False, '');
    LOverlapped.hEvent := LEvent.Handle;
    LPortHandle := CreateFile(PChar(FPortName), GENERIC_READ or GENERIC_WRITE, 0,
      nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
    if (LPortHandle = INVALID_HANDLE_VALUE) then
      Exit;
    SetCommConfig(LPortHandle, LPCommConfig^, CommConfigSize);
    GetCommTimeouts(LPortHandle, LOldCommTimeouts);
    SetCommTimeouts(LPortHandle, LCommTimeouts);
    while not Terminated do
    begin
      PurgeComm(LPortHandle, PURGE_TXCLEAR or PURGE_RXCLEAR or
        PURGE_RXABORT or PURGE_TXABORT);
      LOutBuffer := 'R';
      WriteFile(LPortHandle, LOutBuffer, Length(LOutBuffer), LBytesWritten,
        @LOverlapped);
      GetOverlappedResult(LPortHandle, LOverlapped, LBytesWritten, True);
      if LBytesWritten = 1 then
      begin
        ZeroMemory(@LInBuffer, SizeOf(LInBuffer));
        ReadFile(LPortHandle, LInBuffer[0], 1, LBytesRead, @LOverlapped);
        case LEvent.WaitFor(50) of
          wrSignaled:
            begin
              GetOverlappedResult(LPortHandle, LOverlapped, LBytesRead, True);
              LEOL := False;
              LIndex := LBytesRead;
              while not LEOL and (LIndex < SizeOf(LInBuffer)) do
              begin
                ReadFile(LPortHandle, LInBuffer[LIndex], 1, LBytesRead, @LOverlapped);
                GetOverlappedResult(LPortHandle, LOverlapped, LBytesRead, True);
                LEOL := (LInBuffer[LIndex] = #$0A) or (LInBuffer[LIndex] = #$0D);
                Inc(LIndex);
              end;
              try
                ParseData(LInBuffer);
              except
              end;
            end;
          wrTimeout, wrAbandoned, wrError:
            begin
              Sleep(100);
            end;
        end;
      end;
    end;
  finally
    SetCommTimeouts(LPortHandle, LOldCommTimeouts);
    CloseHandle(LPortHandle);
    FreeAndNil(LEvent);
    if Assigned(LPCommConfig) then
      FreeMem(LPCommConfig);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése