Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

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

01.01.2007

Компонент, который представлен здесь, выполняет функции синхронного чтения и записи в последовательный интерфейс 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.

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

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

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