Компонент для последовательного устройства (TRS232)

Компонент, который представлен здесь, выполняет функции синхронного чтения и записи в последовательный интерфейс RS232.
В цикле выполняется Application.ProcessMessages, чтобы все сообщения от основной программы обрабатывались.

// ----------------------------------------------------------------------

// | RS232 - Basic Driver for the RS232 port 1.0 |

// ----------------------------------------------------------------------

// | © 1997 by Marco Cocco |

// | © 1998 by enhanced by Angerer Bernhard |

// ----------------------------------------------------------------------



unit uRS232;

interface

uses

 Windows, Messages, SysUtils, Classes, Forms,

 ExtCtrls; // TTimer

////////////////////////////////////////////////////////////////////////////////

type

 TReceiveDataEvent = procedure(Sender: TObject; Msg, lParam, wParam:longint) of object;

 // COM Port Baud Rates

 TComPortBaudRate = ( br110, br300, br600, br1200, br2400, br4800,

  br9600, br14400, br19200, br38400, br56000,

  br57600, br115200 );

 // COM Port Numbers

 TComPortNumber = ( pnCOM1, pnCOM2, pnCOM3, pnCOM4 );

 // COM Port Data bits

 TComPortDataBits = ( db5BITS, db6BITS, db7BITS, db8BITS );

 // COM Port Stop bits

 TComPortStopBits = ( sb1BITS, sb1HALFBITS, sb2BITS );

 // COM Port Parity

 TComPortParity = ( ptNONE, ptODD, ptEVEN, ptMARK, ptSPACE );

 // COM Port Hardware Handshaking

 TComPortHwHandshaking = ( hhNONE, hhRTSCTS );

 // COM Port Software Handshaing

 TComPortSwHandshaking = ( shNONE, shXONXOFF );

 TCommPortDriver = class(TComponent)

 private

  hTimer: TTimer;

  FActive: boolean;

  procedure SetActive(const Value: boolean);

 protected

  FComPortHandle : THANDLE; // COM Port Device Handle

  FComPort : TComPortNumber; // COM Port to use (1..4)

  FComPortBaudRate : TComPortBaudRate; // COM Port speed (brXXXX)

  FComPortDataBits : TComPortDataBits; // Data bits size (5..8)

  FComPortStopBits : TComPortStopBits; // How many stop bits to use

  // (1,1.5,2)

  FComPortParity : TComPortParity; // Type of parity to use

  // (none,odd,even,mark,space)

  FComPortHwHandshaking : TComPortHwHandshaking; // Type of hw

  // handshaking to use

  FComPortSwHandshaking : TComPortSwHandshaking; // Type of sw

  // handshaking to use

  FComPortInBufSize : word; // Size of the input buffer

  FComPortOutBufSize : word; // Size of the output buffer

  FComPortReceiveData : TReceiveDataEvent;

  FComPortPollingDelay : word; // ms of delay between COM port pollings

  FTimeOut : integer; // sec until timeout

  FTempInBuffer : pointer;

  procedure SetComPort( Value: TComPortNumber );

  procedure SetComPortBaudRate( Value: TComPortBaudRate );

  procedure SetComPortDataBits( Value: TComPortDataBits );

  procedure SetComPortStopBits( Value: TComPortStopBits );

  procedure SetComPortParity( Value: TComPortParity );

  procedure SetComPortHwHandshaking( Value: TComPortHwHandshaking );

  procedure SetComPortSwHandshaking( Value: TComPortSwHandshaking );

  procedure SetComPortInBufSize( Value: word );

  procedure SetComPortOutBufSize( Value: word );

  procedure SetComPortPollingDelay( Value: word );

  procedure ApplyCOMSettings;

  procedure TimerEvent(Sender: TObject); virtual;

 public

  constructor Create( AOwner: TComponent ); override;

  destructor Destroy; override;

  function Connect: boolean; //override;

  function Disconnect: boolean; //override;

  function Connected: boolean;

  function SendData( DataPtr: pointer; DataSize: integer ): boolean;

  function SendString( aStr: string ): boolean;

  // Event to raise when there is data available (input buffer has data)

  property OnReceiveData: TReceiveDataEvent read FComPortReceiveData

  write FComPortReceiveData;

 published

  // Which COM Port to use

  property ComPort: TComPortNumber read FComPort write SetComPort

  default pnCOM2;

  // COM Port speed (bauds)

  property ComPortSpeed: TComPortBaudRate read FComPortBaudRate

  write SetComPortBaudRate default br9600;

  // Data bits to used (5..8, for the 8250 the use of 5 data bits with 2 stop

  // bits is an invalid combination, as is 6, 7, or 8 data bits with 1.5

  // stop bits)

  property ComPortDataBits: TComPortDataBits read FComPortDataBits

  write SetComPortDataBits default db8BITS;

  // Stop bits to use (1, 1.5, 2)

  property ComPortStopBits: TComPortStopBits read FComPortStopBits

  write SetComPortStopBits default sb1BITS;

  // Parity Type to use (none,odd,even,mark,space)

  property ComPortParity: TComPortParity read FComPortParity

  write SetComPortParity default ptNONE;

  // Hardware Handshaking Type to use:

  // cdNONE no handshaking

  // cdCTSRTS both cdCTS and cdRTS apply (This is the more common method)

  property ComPortHwHandshaking: TComPortHwHandshaking

  read FComPortHwHandshaking write SetComPortHwHandshaking default hhNONE;

  // Software Handshaking Type to use:

  // cdNONE no handshaking

  // cdXONXOFF XON/XOFF handshaking

  property ComPortSwHandshaking: TComPortSwHandshaking

  read FComPortSwHandshaking write SetComPortSwHandshaking default shNONE;

  // Input Buffer size

  property ComPortInBufSize: word read FComPortInBufSize

  write SetComPortInBufSize default 2048;

  // Output Buffer size

  property ComPortOutBufSize: word read FComPortOutBufSize

  write SetComPortOutBufSize default 2048;

  // ms of delay between COM port pollings

  property ComPortPollingDelay: word read FComPortPollingDelay

  write SetComPortPollingDelay default 100;

  property TimeOut: integer read FTimeOut write FTimeOut default 30;

  property Active: boolean read FActive write SetActive default false;

 end;



 TRS232 = class(TCommPortDriver)

 protected

 public

  // new comm parameters are set

  constructor Create( AOwner: TComponent ); override;

  // ReadStrings reads direct from the comm-buffer and waits for

  // more characters and handles the timeout

  function ReadString(var aResStr: string; aCount: word ): boolean;

 published

 end;



procedure Register;

implementation

procedure Register;

begin

 RegisterComponents('Additional', [TRS232]);

end;

constructor TCommPortDriver.Create( AOwner: TComponent );

begin

 inherited Create( AOwner );

 // Initialize to default values

 FComPortHandle := 0; // Not connected

 FComPort := pnCOM2; // COM 2

 FComPortBaudRate := br9600; // 9600 bauds

 FComPortDataBits := db8BITS; // 8 data bits

 FComPortStopBits := sb1BITS; // 1 stop bit

 FComPortParity := ptNONE; // no parity

 FComPortHwHandshaking := hhNONE; // no hardware handshaking

 FComPortSwHandshaking := shNONE; // no software handshaking

 FComPortInBufSize := 2048; // input buffer of 512 bytes

 FComPortOutBufSize := 2048; // output buffer of 512 bytes

 FComPortReceiveData := nil; // no data handler

 FTimeOut := 30; // sec until timeout

 FComPortPollingDelay := 500;

 GetMem( FTempInBuffer, FComPortInBufSize ); // Temporary buffer

  // for received data

 // Timer for teaching and messages

 hTimer := TTimer.Create(Self);

 hTimer.Enabled := false;

 hTimer.Interval := 500;

 hTimer.OnTimer := TimerEvent;

 if ComponentState = [csDesigning] then

  EXIT;

 if FActive then

  hTimer.Enabled := true; // start the timer only at application start

end;

destructor TCommPortDriver.Destroy;

begin

 // Be sure to release the COM device

 Disconnect;

 // Free the temporary buffer

 FreeMem( FTempInBuffer, FComPortInBufSize );

 // Destroy the timer's window

 inherited Destroy;

end;

procedure TCommPortDriver.SetComPort( Value: TComPortNumber );

begin

 // Be sure we are not using any COM port

 if Connected then

  exit;

 // Change COM port

 FComPort := Value;

end;

procedure TCommPortDriver.SetComPortBaudRate( Value: TComPortBaudRate );

begin

 // Set new COM speed

 FComPortBaudRate := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortDataBits( Value: TComPortDataBits );

begin

 // Set new data bits

 FComPortDataBits := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortStopBits( Value: TComPortStopBits );

begin

 // Set new stop bits

 FComPortStopBits := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortParity( Value: TComPortParity );

begin

 // Set new parity

 FComPortParity := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortHwHandshaking(Value: TComPortHwHandshaking);

begin

 // Set new hardware handshaking

 FComPortHwHandshaking := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortSwHandshaking(Value: TComPortSwHandshaking);

begin

 // Set new software handshaking

 FComPortSwHandshaking := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortInBufSize( Value: word );

begin

 // Free the temporary input buffer

 FreeMem( FTempInBuffer, FComPortInBufSize );

 // Set new input buffer size

 FComPortInBufSize := Value;

 // Allocate the temporary input buffer

 GetMem( FTempInBuffer, FComPortInBufSize );

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortOutBufSize( Value: word );

begin

 // Set new output buffer size

 FComPortOutBufSize := Value;

 // Apply changes

 if Connected then

  ApplyCOMSettings;

end;

procedure TCommPortDriver.SetComPortPollingDelay( Value: word );

begin

 FComPortPollingDelay := Value;

 hTimer.Interval := Value;

end;

const

 Win32BaudRates: array[br110..br115200] of DWORD =

  ( CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600,

  CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200 );

const

 dcb_Binary = $00000001;

 dcb_ParityCheck = $00000002;

 dcb_OutxCtsFlow = $00000004;

 dcb_OutxDsrFlow = $00000008;

 dcb_DtrControlMask = $00000030;

  dcb_DtrControlDisable = $00000000;

  dcb_DtrControlEnable = $00000010;

  dcb_DtrControlHandshake = $00000020;

 dcb_DsrSensivity = $00000040;

 dcb_TXContinueOnXoff = $00000080;

 dcb_OutX = $00000100;

 dcb_InX = $00000200;

 dcb_ErrorChar = $00000400;

 dcb_NullStrip = $00000800;

 dcb_RtsControlMask = $00003000;

  dcb_RtsControlDisable = $00000000;

  dcb_RtsControlEnable = $00001000;

  dcb_RtsControlHandshake = $00002000;

  dcb_RtsControlToggle = $00003000;

 dcb_AbortOnError = $00004000;

 dcb_Reserveds = $FFFF8000;

// Apply COM settings.

procedure TCommPortDriver.ApplyCOMSettings;

var dcb: TDCB;

begin

 // Do nothing if not connected

 if not Connected then

  exit;

 // Clear all

 fillchar( dcb, sizeof(dcb), 0 );

 // Setup dcb (Device Control Block) fields

 dcb.DCBLength := sizeof(dcb); // dcb structure size

 dcb.BaudRate := Win32BaudRates[ FComPortBaudRate ]; // baud rate to use

 dcb.Flags := dcb_Binary or // Set fBinary: Win32 does not support non

  // binary mode transfers

  // (also disable EOF check)

  dcb_RtsControlEnable; // Enables the RTS line when the device

  // is opened and leaves it on

// dcb_DtrControlEnable; // Enables the DTR line when the device

  // is opened and leaves it on

 case FComPortHwHandshaking of // Type of hw handshaking to use

  hhNONE:; // No hardware handshaking

  hhRTSCTS: // RTS/CTS (request-to-send/clear-to-send) hardware handshaking

  dcb.Flags := dcb.Flags or dcb_OutxCtsFlow or dcb_RtsControlHandshake;

 end;

  case FComPortSwHandshaking of // Type of sw handshaking to use

  shNONE:; // No software handshaking

  shXONXOFF: // XON/XOFF handshaking

  dcb.Flags := dcb.Flags or dcb_OutX or dcb_InX;

 end;

 dcb.XONLim := FComPortInBufSize div 4; // Specifies the minimum number

  // of bytes allowed

  // in the input buffer before the

  // XON character is sent

 dcb.XOFFLim := 1; // Specifies the maximum number of bytes allowed in the

  // input buffer before the XOFF character is sent.

  // The maximum number of bytes allowed is calculated by

  // subtracting this value from the size, in bytes,

  // of the input buffer

 dcb.ByteSize := 5 + ord(FComPortDataBits); // how many data bits to use

 dcb.Parity := ord(FComPortParity); // type of parity to use

 dcb.StopBits := ord(FComPortStopbits); // how many stop bits to use

 dcb.XONChar := #17; // XON ASCII char

 dcb.XOFFChar := #19; // XOFF ASCII char

 SetCommState( FComPortHandle, dcb );

 // Setup buffers size

 SetupComm( FComPortHandle, FComPortInBufSize, FComPortOutBufSize );

end;

function TCommPortDriver.Connect: boolean;

var comName: array[0..4] of char;

  tms: TCOMMTIMEOUTS;

begin

 // Do nothing if already connected

 Result := Connected;

 if Result then exit;

 // Open the COM port

 StrPCopy( comName, 'COM' );

 comName[3] := chr( ord('1') + ord(FComPort) );

 comName[4] := #0;

 FComPortHandle := CreateFile(

  comName,

  GENERIC_READ or GENERIC_WRITE,

  0, // Not shared

  nil, // No security attributes

  OPEN_EXISTING,

  FILE_ATTRIBUTE_NORMAL,

  0 // No template

  ) ;

 Result := Connected;

 if not Result then exit;

 // Apply settings

 ApplyCOMSettings;

 // Setup timeouts: we disable timeouts because we are polling the com port!

 tms.ReadIntervalTimeout := 1; // Specifies the maximum time, in milliseconds,

  // allowed to elapse between the arrival of two

  // characters on the communications line

 tms.ReadTotalTimeoutMultiplier := 0; // Specifies the multiplier, in

  // milliseconds, used to calculate

  // the total time-out period

  // for read operations.

 tms.ReadTotalTimeoutConstant := 1; // Specifies the constant, in milliseconds,

  // used to calculate the total time-out

  // period for read operations.

 tms.WriteTotalTimeoutMultiplier := 0; // Specifies the multiplier, in

  // milliseconds, used to calculate

  // the total time-out period

  // for write operations.

 tms.WriteTotalTimeoutConstant := 0; // Specifies the constant, in

  // milliseconds, used to calculate

  // the total time-out period

  // for write operations.

 SetCommTimeOuts( FComPortHandle, tms );

 Sleep(1000); // to avoid timing problems, wait until the Comm-Port is opened

end;

function TCommPortDriver.Disconnect: boolean;

begin

 Result:=false;

 if Connected then

 begin

  CloseHandle( FComPortHandle );

  FComPortHandle := 0;

 end;

 Result := true;

end;

function TCommPortDriver.Connected: boolean;

begin

 Result := FComPortHandle > 0;

end;

function TCommPortDriver.SendData(DataPtr: pointer; DataSize: integer): boolean;

var nsent: DWORD;

begin

 Result := WriteFile( FComPortHandle, DataPtr^, DataSize, nsent, nil );

 Result := Result and (nsent=DataSize);

end;

function TCommPortDriver.SendString( aStr: string ): boolean;

begin

 if not Connected then

  if not Connect then raise Exception.CreateHelp('RS232.SendString:'+

  ' Connect not possible !', 101);

 Result:=SendData( pchar(aStr), length(aStr) );

 if not Result then raise

  Exception.CreateHelp('RS232.SendString: Send not possible !', 102);

end;



// Event for teaching and messages

procedure TCommPortDriver.TimerEvent(Sender: TObject);

var InQueue, OutQueue: integer;

 // Test if data in inQueue(outQueue)

 procedure DataInBuffer(Handle: THandle; var aInQueue, aOutQueue: integer);

 var ComStat: TComStat;

  e: cardinal;

 begin

  aInQueue := 0;

  aOutQueue := 0;

  if ClearCommError(Handle, e, @ComStat) then

  begin

  aInQueue := ComStat.cbInQue;

  aOutQueue := ComStat.cbOutQue;

  end;

 end;

begin

 if not Connected then

  if not Connect then raise Exception.CreateHelp('RS232.TimerEvent:'+

  ' Connect not possible !', 101);

 if Connected then

 begin

  DataInBuffer(FComPortHandle, InQueue, OutQueue);

  // data in inQueue

  if InQueue > 0 then

  if Assigned(FComPortReceiveData) then FComPortReceiveData(Self , 0, 0, 0);

 end;

end;

// RS232 implementation ////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

constructor TRS232.Create( AOwner: TComponent );

begin

 inherited Create( AOwner );

 //OnReceiveData := ReceiveData;

 FComPort := pnCOM1; // COM 1

 FComPortBaudRate := br9600; // 9600 bauds

 FComPortDataBits := db8BITS; // 8 data bits

 FComPortStopBits := sb1BITS; // 1 stop bits

 FComPortParity := ptEVEN; // even parity

 FComPortHwHandshaking := hhNONE; // no hardware handshaking

 FComPortSwHandshaking := shNONE; // no software handshaking

 FComPortInBufSize := 2048; // input buffer of 512 ? bytes

 FComPortOutBufSize := 2048; // output buffer of 512 ? bytes

 FTimeOut := 30; // sec until timeout

end;

function TRS232.ReadString(VAR aResStr: string; aCount: word ): boolean;

var

 nRead: dword;

 Buffer: string;

 Actual, Before: TDateTime;

 TimeOutMin, TimeOutSec, lCount: word;

begin

 Result := false;

 if not Connected then

  if not Connect then raise Exception.CreateHelp('RS232.ReadString:'+

  ' Connect not possible !', 101);

 aResStr := '';

 TimeOutMin:=TimeOut div 60;

 TimeOutSec:=TimeOut mod 60;

 if (not Connected) or (aCount <= 0) then EXIT;

 nRead := 0; lCount := 0;

 Before := Time;

 while lCount<aCount do

 begin

  Application.ProcessMessages;

  SetLength(Buffer,1);

  if ReadFile( FComPortHandle, PChar(Buffer)^, 1, nRead, nil ) then

  begin

  if nRead > 0 then

  begin

  aResStr := aResStr + Buffer;

  inc(lCount);

  end;

  Actual := Time;

  if Actual-Before>EncodeTime(0, TimeOutMin, TimeOutSec, 0)

  then raise Exception.CreateHelp('RS232.ReadString: TimeOut !', 103);

  end

  else begin

  raise Exception.CreateHelp('RS232.ReadString: Read not possible !', 104);

  end;

 end; // while

 Result:=true;

end;



[OBJECT]{$A+,B-,C+,D-,E-,F-,G+,H+,I+,J+,K-,L-,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y-,Z1}

{$MINSTACKSIZE $00004000}

{$MAXSTACKSIZE $00100000}

{$IMAGEBASE $51000000}

{$APPTYPE GUI}

unit ComportDriverThread;

interface

uses

 //Include "ExtCtrl" for the TTimer component.

 Windows, Messages, SysUtils, Classes, Forms, ExtCtrls;

type

 TComPortNumber = (pnCOM1,pnCOM2,pnCOM3,pnCOM4);

 TComPortBaudRate = (br110,br300,br600,br1200,br2400,br4800,br9600,

  br14400,br19200,br38400,br56000,br57600,br115200);

 TComPortDataBits = (db5BITS,db6BITS,db7BITS,db8BITS);

 TComPortStopBits = (sb1BITS,sb1HALFBITS,sb2BITS);

 TComPortParity = (ptNONE,ptODD,ptEVEN,ptMARK,ptSPACE);

 TComportHwHandshaking = (hhNONE,hhRTSCTS);

 TComPortSwHandshaking = (shNONE,shXONXOFF);

 TTimerThread = class(TThread)

 private

  { Private declarations }

  FOnTimer : TThreadMethod;

  FEnabled: Boolean;

 protected

  { Protected declarations }

  procedure Execute; override;

  procedure SupRes;

 public

  { Public declarations }

 published

  { Published declarations }

  property Enabled: Boolean read FEnabled write FEnabled;

 end;

 TComportDriverThread = class(TComponent)

 private

  { Private declarations }

  FTimer : TTimerThread;

  FOnReceiveData : TNotifyEvent;

  FReceiving : Boolean;

 protected

  { Protected declarations }

  FComPortActive : Boolean;

  FComportHandle : THandle;

  FComportNumber : TComPortNumber;

  FComportBaudRate : TComPortBaudRate;

  FComportDataBits : TComPortDataBits;

  FComportStopBits : TComPortStopBits;

  FComportParity : TComPortParity;

  FComportHwHandshaking : TComportHwHandshaking;

  FComportSwHandshaking : TComPortSwHandshaking;

  FComportInputBufferSize : Word;

  FComportOutputBufferSize : Word;

  FComportPollingDelay : Word;

  FTimeOut : Integer;

  FTempInputBuffer : Pointer;

  procedure SetComPortActive(Value: Boolean);

  procedure SetComPortNumber(Value: TComPortNumber);

  procedure SetComPortBaudRate(Value: TComPortBaudRate);

  procedure SetComPortDataBits(Value: TComPortDataBits);

  procedure SetComPortStopBits(Value: TComPortStopBits);

  procedure SetComPortParity(Value: TComPortParity);

  procedure SetComPortHwHandshaking(Value: TComportHwHandshaking);

  procedure SetComPortSwHandshaking(Value: TComPortSwHandshaking);

  procedure SetComPortInputBufferSize(Value: Word);

  procedure SetComPortOutputBufferSize(Value: Word);

  procedure SetComPortPollingDelay(Value: Word);

  procedure ApplyComPortSettings;

  procedure TimerEvent; virtual;

  procedure doDataReceived; virtual;

 public

  { Public declarations }

  constructor Create(AOwner: TComponent); override;

  destructor Destroy; override;

  function Connect: Boolean;

  function Disconnect: Boolean;

  function Connected: Boolean;

  function Disconnected: Boolean;

  function SendData(DataPtr: Pointer; DataSize: Integer): Boolean;

  function SendString(Input: String): Boolean;

  function ReadString(var Str: string): Integer;

 published

  { Published declarations }

  property Active: Boolean read FComPortActive write SetComPortActive default False;

  property ComPort: TComPortNumber read FComportNumber write SetComportNumber

  default pnCOM1;

  property ComPortSpeed: TComPortBaudRate read FComportBaudRate write

  SetComportBaudRate default br9600;

  property ComPortDataBits: TComPortDataBits read FComportDataBits write

  SetComportDataBits default db8BITS;

  property ComPortStopBits: TComPortStopBits read FComportStopBits write

  SetComportStopBits default sb1BITS;

  property ComPortParity: TComPortParity read FComportParity write

  SetComportParity default ptNONE;

  property ComPortHwHandshaking: TComportHwHandshaking read FComportHwHandshaking

  write SetComportHwHandshaking default

  hhNONE;

  property ComPortSwHandshaking: TComPortSwHandshaking read FComportSwHandshaking

  write SetComportSwHandshaking default

  shNONE;

  property ComPortInputBufferSize: Word read FComportInputBufferSize

  write SetComportInputBufferSize default

  2048;

  property ComPortOutputBufferSize: Word read FComportOutputBufferSize

  write SetComportOutputBufferSize default

  2048;

  property ComPortPollingDelay: Word read FComportPollingDelay write

  SetComportPollingDelay default 100;

  property OnReceiveData: TNotifyEvent read FOnReceiveData

  write FOnReceiveData;

  property TimeOut: Integer read FTimeOut write FTimeOut default 30;

 end;

procedure Register;

implementation

procedure Register;

begin

 RegisterComponents('Self-made Components', [TComportDriverThread]);

end;

{ TComportDriver }

constructor TComportDriverThread.Create(AOwner: TComponent);

begin

 inherited;

 FReceiving := False;

 FComportHandle := 0;

 FComportNumber := pnCOM1;

 FComportBaudRate := br9600;

 FComportDataBits := db8BITS;

 FComportStopBits := sb1BITS;

 FComportParity := ptNONE;

 FComportHwHandshaking := hhNONE;

 FComportSwHandshaking := shNONE;

 FComportInputBufferSize := 2048;

 FComportOutputBufferSize := 2048;

 FOnReceiveData := nil;

 FTimeOut := 30;

 FComportPollingDelay := 500;

 GetMem(FTempInputBuffer,FComportInputBufferSize);

 if csDesigning in ComponentState then

  Exit;

 FTimer := TTimerThread.Create(False);

 FTimer.FOnTimer := TimerEvent;

 if FComPortActive then

  FTimer.Enabled := True;

 FTimer.SupRes;

end;

destructor TComportDriverThread.Destroy;

begin

 Disconnect;

 FreeMem(FTempInputBuffer,FComportInputBufferSize);

 inherited Destroy;

end;

function TComportDriverThread.Connect: Boolean;

var

 comName: array[0..4] of Char;

 tms: TCommTimeouts;

begin

 if Connected then

  Exit;

 StrPCopy(comName,'COM');

 comName[3] := chr(ord('1') + ord(FComportNumber));

 comName[4] := #0;

 FComportHandle := CreateFile(comName,GENERIC_READ OR GENERIC_WRITE,0,nil,

  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

 if not Connected then

  Exit;

 ApplyComPortSettings;

 tms.ReadIntervalTimeout := 1;

 tms.ReadTotalTimeoutMultiplier := 0;

 tms.ReadTotalTimeoutConstant := 1;

 tms.WriteTotalTimeoutMultiplier := 0;

 tms.WriteTotalTimeoutConstant := 0;

 SetCommTimeouts(FComportHandle,tms);

 Sleep(1000);

end;

function TComportDriverThread.Connected: Boolean;

begin

 Result := FComportHandle > 0;

end;

function TComportDriverThread.Disconnect: Boolean;

begin

 Result := False;

 if Connected then

 begin

  CloseHandle(FComportHandle);

  FComportHandle := 0;

 end;

 Result := True;

end;

function TComportDriverThread.Disconnected: Boolean;

begin

 if (FComportHandle <> 0) then

  Result := False

 else

  Result := True;

end;

const

 Win32BaudRates: array[br110..br115200] of DWORD =

  (CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_14400,

  CBR_19200,CBR_38400,CBR_56000,CBR_57600,CBR_115200);

const

 dcb_Binary = $00000001;

 dcb_ParityCheck = $00000002;

 dcb_OutxCtsFlow = $00000004;

 dcb_OutxDsrFlow = $00000008;

 dcb_DtrControlMask = $00000030;

 dcb_DtrControlDisable = $00000000;

 dcb_DtrControlEnable = $00000010;

 dcb_DtrControlHandshake = $00000020;

 dcb_DsrSensitvity = $00000040;

 dcb_TXContinueOnXoff = $00000080;

 dcb_OutX = $00000100;

 dcb_InX = $00000200;

 dcb_ErrorChar = $00000400;

 dcb_NullStrip = $00000800;

 dcb_RtsControlMask = $00003000;

 dcb_RtsControlDisable = $00000000;

 dcb_RtsControlEnable = $00001000;

 dcb_RtsControlHandshake = $00002000;

 dcb_RtsControlToggle = $00003000;

 dcb_AbortOnError = $00004000;

 dcb_Reserveds = $FFFF8000;

procedure TComportDriverThread.ApplyComPortSettings;

var

 //Device Control Block (= dcb)

 dcb: TDCB;

begin

 if not Connected then

  Exit;

 FillChar(dcb,sizeOf(dcb),0);

 dcb.DCBlength := sizeOf(dcb);

 dcb.Flags := dcb_Binary or dcb_RtsControlEnable;

 dcb.BaudRate := Win32BaudRates[FComPortBaudRate];

 case FComportHwHandshaking of

  hhNONE : ;

  hhRTSCTS:

  dcb.Flags := dcb.Flags or dcb_OutxCtsFlow or dcb_RtsControlHandshake;

 end;

 case FComportSwHandshaking of

  shNONE : ;

  shXONXOFF:

  dcb.Flags := dcb.Flags or dcb_OutX or dcb_Inx;

 end;

 dcb.XonLim := FComportInputBufferSize div 4;

 dcb.XoffLim := 1;

 dcb.ByteSize := 5 + ord(FComportDataBits);

 dcb.Parity := ord(FComportParity);

 dcb.StopBits := ord(FComportStopBits);

 dcb.XonChar := #17;

 dcb.XoffChar := #19;

 SetCommState(FComportHandle,dcb);

 SetupComm(FComportHandle,FComPortInputBufferSize,FComPortOutputBufferSize);

end;

function TComportDriverThread.ReadString(var Str: string): Integer;

var

 BytesTrans, nRead: DWORD;

 Buffer : String;

 i : Integer;

 temp : string;

begin

 BytesTrans := 0;

 Str := '';

 SetLength(Buffer,1);

 ReadFile(FComportHandle,PChar(Buffer)^, 1, nRead, nil);

 while nRead > 0 do

 begin

  temp := temp + PChar(Buffer);

  ReadFile(FComportHandle,PChar(Buffer)^, 1, nRead, nil);

 end;

 //Remove the end token.

 BytesTrans := Length(temp);

 SetLength(str,BytesTrans-2);

 for i:=0 to BytesTrans-2 do

 begin

  str[i] := temp[i];

 end;

 Result := BytesTrans;

end;

function TComportDriverThread.SendData(DataPtr: Pointer;

 DataSize: Integer): Boolean;

var

 nsent : DWORD;

begin

 Result := WriteFile(FComportHandle,DataPtr^,DataSize,nsent,nil);

 Result := Result and (nsent = DataSize);

end;

function TComportDriverThread.SendString(Input: String): Boolean;

begin

 if not Connected then

  if not Connect then

  raise Exception.CreateHelp('Could not connect to COM-port !',101);

 Result := SendData(PChar(Input),Length(Input));

 if not Result then

  raise Exception.CreateHelp('Could not send to COM-port !',102);

end;

procedure TComportDriverThread.TimerEvent;

var

 InQueue, OutQueue: Integer;

 Buffer : String;

 nRead : DWORD;

 procedure DataInBuffer(Handle: THandle; var aInQueue, aOutQueue: Integer);

 var

  ComStat : TComStat;

  e : Cardinal;

 begin

  aInQueue := 0;

  aOutQueue := 0;

  if ClearCommError(Handle,e,@ComStat) then

  begin

  aInQueue := ComStat.cbInQue;

  aOutQueue := ComStat.cbOutQue;

  end;

 end;

begin

 if csDesigning in ComponentState then

  Exit;

 if not Connected then

  if not Connect then

  raise Exception.CreateHelp('TimerEvent: Could not connect to COM-port !',101);

 Application.ProcessMessages;

 if Connected then

 begin

  DataInBuffer(FComportHandle,InQueue,OutQueue);

  if InQueue > 0 then

  begin

  if (Assigned(FOnReceiveData) ) then

  begin

  FReceiving := True;

  FOnReceiveData(Self);

  end;

  end;

 end;

end;

procedure TComportDriverThread.SetComportBaudRate(Value: TComPortBaudRate);

begin

 FComportBaudRate := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportDataBits(Value: TComPortDataBits);

begin

 FComportDataBits := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportHwHandshaking(Value: TComportHwHandshaking);

begin

 FComportHwHandshaking := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportInputBufferSize(Value: Word);

begin

 FreeMem(FTempInputBuffer,FComportInputBufferSize);

 FComportInputBufferSize := Value;

 GetMem(FTempInputBuffer,FComportInputBufferSize);

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportNumber(Value: TComPortNumber);

begin

 if Connected then

  exit;

 FComportNumber := Value;

end;

procedure TComportDriverThread.SetComportOutputBufferSize(Value: Word);

begin

 FComportOutputBufferSize := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportParity(Value: TComPortParity);

begin

 FComportParity := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportPollingDelay(Value: Word);

begin

 FComportPollingDelay := Value;

end;

procedure TComportDriverThread.SetComportStopBits(Value: TComPortStopBits);

begin

 FComportStopBits := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.SetComportSwHandshaking(Value: TComPortSwHandshaking);

begin

 FComportSwHandshaking := Value;

 if Connected then

  ApplyComPortSettings;

end;

procedure TComportDriverThread.DoDataReceived;

begin

 if Assigned(FOnReceiveData) then FOnReceiveData(Self);

end;

procedure TComportDriverThread.SetComPortActive(Value: Boolean);

var

 DumpString : String;

begin

 FComPortActive := Value;

 if csDesigning in ComponentState then

  Exit;

 if FComPortActive then

 begin

  //Just dump the contents of the input buffer of the com-port.

  ReadString(DumpString);

  FTimer.Enabled := True;

 end

 else

  FTimer.Enabled := False;

 FTimer.SupRes;

end;

{ TTimerThread }

procedure TTimerThread.Execute;

begin

 Priority := tpNormal;

 repeat

  Sleep(500);

  if Assigned(FOnTimer) then Synchronize(FOnTimer);

 until Terminated;

end;

procedure TTimerThread.SupRes;

begin

 if not Suspended then

  Suspend;

 if FEnabled then

  Resume;

end;

end.

Взято из http://forum.sources.ru

procedure TCommPortDriver.SetActive(const Value: boolean);
begin
 FActive := Value;
end;
end.

Взято из http://forum.sources.ru

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...