⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spcomm258.pas

📁 spcomm串口编程
💻 PAS
📖 第 1 页 / 共 5 页
字号:
unit SPComm258;
//
//hotpower改编
// Version 2.58     2004/10/8

interface

uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

const
     // messages from read/write threads
     PWM_GOTCOMMDATA = WM_USER + 1;
     PWM_RECEIVEERROR = WM_USER + 2;
     PWM_REQUESTHANGUP = WM_USER + 3;
     PWM_MODEMSTATECHANGE = WM_USER + 4;
     PWM_SENDDATAEMPTY = WM_USER + 5;

type
    TParity = ( None, Odd, Even, Mark, Space );
    TStopBits = ( _1, _1_5, _2 );
    TByteSize = ( _5, _6, _7, _8 );
    TDtrControl = ( DtrEnable, DtrDisable, DtrHandshake );
    TRtsControl = ( RtsEnable, RtsDisable, RtsHandshake, RtsTransmissionAvailable );

    ECommsError = class( Exception );
    TReceiveDataEvent = procedure(Sender: TObject; Buffer: Pointer;
                                  BufferLength: Word) of object;
    TReceiveErrorEvent = procedure(Sender: TObject; EventMask : DWORD) of object;
    TModemStateChangeEvent = procedure(Sender: TObject; ModemEvent : DWORD) of object;
    TSendDataEmptyEvent = procedure(Sender: TObject) of object;

const
     //
     // Modem Event Constant
     //
     ME_CTS = 1;
     ME_DSR = 2;
     ME_RING = 4;
     ME_RLSD = 8;

type
    TReadThread = class( TThread )
    protected
      procedure Execute; override;
    public
      hCommFile:          THandle;
      hCloseEvent:        THandle;
      hComm32Window:      THandle;

      function SetupCommEvent( lpOverlappedCommEvent: POverlapped;
                               var lpfdwEvtMask: DWORD ): Boolean;
      function SetupReadEvent( lpOverlappedRead: POverlapped;
                               lpszInputBuffer: LPSTR; dwSizeofBuffer: DWORD;
                               var lpnNumberOfBytesRead: DWORD ): Boolean;
      function HandleCommEvent( lpOverlappedCommEvent: POverlapped;
                                var lpfdwEvtMask: DWORD; fRetrieveEvent: Boolean ): Boolean;
      function HandleReadEvent( lpOverlappedRead: POverlapped;
                                lpszInputBuffer: LPSTR; dwSizeofBuffer: DWORD;
                                var lpnNumberOfBytesRead: DWORD ): Boolean;
      function HandleReadData( lpszInputBuffer: LPCSTR; dwSizeofBuffer: DWORD ): Boolean;
      function ReceiveData( lpNewString: LPSTR; dwSizeofNewString: DWORD ): BOOL;
      function ReceiveError( EvtMask : DWORD ): BOOL;
      function ModemStateChange( ModemEvent : DWORD ) : BOOL;
      procedure PostHangupCall;
    end;

    TWriteThread = class( TThread )
    protected
      procedure Execute; override;
      function HandleWriteData( lpOverlappedWrite: POverlapped;
                                pDataToWrite: PChar; dwNumberOfBytesToWrite: DWORD): Boolean;
    public
      hCommFile:          THandle;
      hCloseEvent:        THandle;
      hComm32Window:      THandle;
      pFSendDataEmpty:    ^Boolean;
      procedure PostHangupCall;
    end;

    TComm = class( TComponent )
    private
      { Private declarations }
      ReadThread:         TReadThread;
      WriteThread:        TWriteThread;
      hCommFile:          THandle;
      hCloseEvent:        THandle;
      FHWnd:              THandle;
      FSendDataEmpty:     Boolean;            // True if send buffer become empty
//--------------------------------------------------------------------------------
      FPortOpen:          Boolean;            //追加端口控制字段
      FCommPort:          BYTE;               //追加端口号字段
      FPortOpenError:     String;             //追加端口打开错误字段
      FOutput:            variant;         //追加端口打开错误字段
//--------------------------------------------------------------------------------
      FCommName:          String;             //端口名字段,MSComm为端口号CommPort
      FBaudRate:          DWORD;              //波特率字段,MSComm在Settings内
      FParityCheck:       Boolean;            //校验位字段,MSComm在Settings内
      FOutx_CtsFlow:      Boolean;
      FOutx_DsrFlow:      Boolean;
      FDtrControl:        TDtrControl;
      FDsrSensitivity:    Boolean;
      FTxContinueOnXoff:  Boolean;
      FOutx_XonXoffFlow:  Boolean;
      FInx_XonXoffFlow:   Boolean;
      FReplaceWhenParityError:    Boolean;
      FIgnoreNullChar:    Boolean;
      FRtsControl:        TRtsControl;
      FXonLimit:          WORD;
      FXoffLimit:         WORD;
      FByteSize:          TByteSize;
      FParity:            TParity;
      FStopBits:          TStopBits;
      FXonChar:           AnsiChar;
      FXoffChar:          AnsiChar;
      FReplacedChar:      AnsiChar;

      FReadIntervalTimeout: DWORD;
      FReadTotalTimeoutMultiplier: DWORD;
      FReadTotalTimeoutConstant: DWORD;
      FWriteTotalTimeoutMultiplier: DWORD;
      FWriteTotalTimeoutConstant: DWORD;
      FOnReceiveData:     TReceiveDataEvent;
      FOnRequestHangup:   TNotifyEvent;
      FOnReceiveError:    TReceiveErrorEvent;
      FOnModemStateChange:TModemStateChangeEvent;
      FOnSendDataEmpty: TSendDataEmptyEvent;
//--------------------------------------------------------------------------------
      procedure SetPortOpen( b : Boolean );//打开端口
      function  GetPortOpen: Boolean;//打开端口
      procedure SetCommPort( CommPort : BYTE );//设置端口号
      procedure SetOutput( Buffer: variant );
//--------------------------------------------------------------------------------
      procedure SetBaudRate( Rate : DWORD );
      procedure SetParityCheck( b : Boolean );
      procedure SetOutx_CtsFlow( b : Boolean );
      procedure SetOutx_DsrFlow( b : Boolean );
      procedure SetDtrControl( c : TDtrControl );
      procedure SetDsrSensitivity( b : Boolean );
      procedure SetTxContinueOnXoff( b : Boolean );
      procedure SetOutx_XonXoffFlow( b : Boolean );
      procedure SetInx_XonXoffFlow( b : Boolean );
      procedure SetReplaceWhenParityError( b : Boolean );
      procedure SetIgnoreNullChar( b : Boolean );
      procedure SetRtsControl( c : TRtsControl );
      procedure SetXonLimit( Limit : WORD );
      procedure SetXoffLimit( Limit : WORD );
      procedure SetByteSize( Size : TByteSize );
      procedure SetParity( p : TParity );
      procedure SetStopBits( Bits : TStopBits );
      procedure SetXonChar( c : AnsiChar );
      procedure SetXoffChar( c : AnsiChar );
      procedure SetReplacedChar( c : AnsiChar );

      procedure SetReadIntervalTimeout( v : DWORD );
      procedure SetReadTotalTimeoutMultiplier( v : DWORD );
      procedure SetReadTotalTimeoutConstant( v : DWORD );
      procedure SetWriteTotalTimeoutMultiplier( v : DWORD );
      procedure SetWriteTotalTimeoutConstant( v : DWORD );

      procedure CommWndProc( var msg: TMessage );
      procedure _SetCommState;
      procedure _SetCommTimeout;
    protected
      { Protected declarations }
      procedure CloseReadThread;
      procedure CloseWriteThread;
      procedure ReceiveData(Buffer: PChar; BufferLength: Word);
      procedure ReceiveError( EvtMask : DWORD );
      procedure ModemStateChange( ModemEvent : DWORD );
      procedure RequestHangup;
      procedure _SendDataEmpty;
    public
      { Public declarations }
      property Handle: THandle read hCommFile;
      property SendDataEmpty : Boolean read FSendDataEmpty;
      constructor Create( AOwner: TComponent ); override;
      destructor Destroy; override;
      procedure StartComm;
      procedure StopComm;
      function WriteCommData( pDataToWrite: PChar; dwSizeofDataToWrite: Word ): Boolean;
      function GetModemState : DWORD;
    published
      { Published declarations }
//--------------------------------------------------------------------------------
      property PortOpen: Boolean read GetPortOpen write SetPortOpen;//追加端口号属性
      property CommPort: BYTE read FCommPort write SetCommPort;//追加端口号属性
      property PortOpenError: String read FPortOpenError write FPortOpenError;//追加只读端口打开错误字段
      property Output: variant read FOutput write SetOutput;//追加发送数据属性
//--------------------------------------------------------------------------------
      property CommName: String read FCommName write FCommName;
      property BaudRate: DWORD read FBaudRate write SetBaudRate;
      property ParityCheck: Boolean read FParityCheck write SetParityCheck;
      property Outx_CtsFlow: Boolean read FOutx_CtsFlow write SetOutx_CtsFlow;
      property Outx_DsrFlow: Boolean read FOutx_DsrFlow write SetOutx_DsrFlow;
      property DtrControl: TDtrControl read FDtrControl write SetDtrControl;
      property DsrSensitivity: Boolean read FDsrSensitivity write SetDsrSensitivity;
      property TxContinueOnXoff: Boolean read FTxContinueOnXoff write SetTxContinueOnXoff;
      property Outx_XonXoffFlow: Boolean read FOutx_XonXoffFlow write SetOutx_XonXoffFlow;
      property Inx_XonXoffFlow: Boolean read FInx_XonXoffFlow write SetInx_XonXoffFlow;
      property ReplaceWhenParityError: Boolean read FReplaceWhenParityError write SetReplaceWhenParityError;
      property IgnoreNullChar: Boolean read FIgnoreNullChar write SetIgnoreNullChar;
      property RtsControl: TRtsControl read FRtsControl write SetRtsControl;
      property XonLimit: WORD read FXonLimit write SetXonLimit;
      property XoffLimit: WORD read FXoffLimit write SetXoffLimit;
      property ByteSize: TByteSize read FByteSize write SetByteSize;
      property Parity: TParity read FParity write FParity;
      property StopBits: TStopBits read FStopBits write SetStopBits;
      property XonChar: AnsiChar read FXonChar write SetXonChar;
      property XoffChar: AnsiChar read FXoffChar write SetXoffChar;
      property ReplacedChar: AnsiChar read FReplacedChar write SetReplacedChar;

      property ReadIntervalTimeout: DWORD         read FReadIntervalTimeout         write SetReadIntervalTimeout;
      property ReadTotalTimeoutMultiplier: DWORD  read FReadTotalTimeoutMultiplier  write SetReadTotalTimeoutMultiplier;
      property ReadTotalTimeoutConstant: DWORD    read FReadTotalTimeoutConstant    write SetReadTotalTimeoutConstant;
      property WriteTotalTimeoutMultiplier: DWORD read FWriteTotalTimeoutMultiplier write SetWriteTotalTimeoutMultiplier;
      property WriteTotalTimeoutConstant: DWORD   read FWriteTotalTimeoutConstant   write SetWriteTotalTimeoutConstant;

      property OnReceiveData: TReceiveDataEvent
               read FOnReceiveData write FOnReceiveData;
      property OnReceiveError: TReceiveErrorEvent
               read FOnReceiveError write FOnReceiveError;
      property OnModemStateChange: TModemStateChangeEvent
               read FOnModemStateChange write FOnModemStateChange;
      property OnRequestHangup: TNotifyEvent
               read FOnRequestHangup write FOnRequestHangup;
      property OnSendDataEmpty: TSendDataEmptyEvent
               read FOnSendDataEmpty write FOnSendDataEmpty;
    end;

const
// This is the message posted to the WriteThread
// When we have something to write.
     PWM_COMMWRITE = WM_USER+1;

// Default size of the Input Buffer used by this code.
//     INPUTBUFFERSIZE = 2048;
     INPUTBUFFERSIZE = 1;

procedure Register;

implementation

(******************************************************************************)
//   TComm PUBLIC METHODS
(******************************************************************************)

constructor TComm.Create( AOwner: TComponent );
begin
     inherited Create( AOwner );

     ReadThread := nil;
     WriteThread := nil;
     hCommFile := 0;
     hCloseEvent := 0;
     FSendDataEmpty := True;

     FCommPort := 2;//
     FCommName := 'COM2';
     FBaudRate := 9600;
     FParityCheck := False;
     FOutx_CtsFlow := False;
     FOutx_DsrFlow := False;
     FDtrControl := DtrEnable;
     FDsrSensitivity := False;
     FTxContinueOnXoff := True;
     FOutx_XonXoffFlow := True;
     FInx_XonXoffFlow := True;
     FReplaceWhenParityError := False;
     FIgnoreNullChar := False;
     FRtsControl := RtsEnable;
     FXonLimit := 500;
     FXoffLimit := 500;
     FByteSize := _8;
     FParity := None;
     FStopBits := _1;
     FXonChar := chr($11);      // Ctrl-Q
     FXoffChar := chr($13);     // Ctrl-S
     FReplacedChar := chr(0);
     FReadIntervalTimeout         := 100;
     FReadTotalTimeoutMultiplier  := 0;
     FReadTotalTimeoutConstant    := 0;
     FWriteTotalTimeoutMultiplier := 0;
     FWriteTotalTimeoutConstant   := 0;

     if not (csDesigning in ComponentState) then
        FHWnd := AllocateHWnd(CommWndProc)
end;

destructor TComm.Destroy;
begin
     if not (csDesigning in ComponentState) then
        DeallocateHWnd(FHwnd);
        
     inherited Destroy;
end;

//
//  FUNCTION: StartComm
//
//  PURPOSE: Starts communications over the comm port.
//
//  PARAMETERS:
//    hNewCommFile - This is the COMM File handle to communicate with.
//                   This handle is obtained from TAPI.
//
//  Output:
//    Successful: Startup the communications.
//    Failure: Raise a exception
//
//  COMMENTS:
//
//    StartComm makes sure there isn't communication in progress already,
//    creates a Comm file, and creates the read and write threads.  It
//    also configures the hNewCommFile for the appropriate COMM settings.
//
//    If StartComm fails for any reason, it's up to the calling application
//    to close the Comm file handle.
//
//
procedure TComm.StartComm;
var
   hNewCommFile:   THandle;
begin
     FPortOpenError := '';
     FPortOpen := false;
     // Are we already doing comm?
     if (hCommFile <> 0) then
     begin
        FPortOpenError := 'This serial port already opened';
//        raise ECommsError.Create( FPortOpenError );
        Exit;
     end;

     hNewCommFile := CreateFile( PChar(FCommName),
                                 GENERIC_READ or GENERIC_WRITE,
                                 0, {not shared}
                                 nil, {no security ??}
                                 OPEN_EXISTING,
                                 FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,
                                 0 {template} );

     if hNewCommFile = INVALID_HANDLE_VALUE then
     begin
        FPortOpenError := 'Error opening serial port';
//        raise ECommsError.Create( FPortOpenError );
        Exit;
     end;

     // Is this a valid comm handle?
     if GetFileType( hNewCommFile ) <> FILE_TYPE_CHAR then
     begin
          CloseHandle( hNewCommFile );
          FPortOpenError := 'File handle is not a comm handle ';
//          raise ECommsError.Create( FPortOpenError );
          Exit;
     end;

     if not SetupComm( hNewCommFile, 4096, 4096 ) then
     begin
          CloseHandle( hCommFile );
          FPortOpenError := 'Cannot setup comm buffer';
          raise ECommsError.Create( FPortOpenError );
     end;

     // It is ok to continue.

     hCommFile := hNewCommFile;

     // purge any information in the buffer

     PurgeComm( hCommFile, PURGE_TXABORT or PURGE_RXABORT or
                           PURGE_TXCLEAR or PURGE_RXCLEAR ) ;
     FSendDataEmpty := True;

     // Setting the time-out value
     _SetCommTimeout;

     // Querying then setting the comm port configurations.
     _SetCommState;

     // Create the event that will signal the threads to close.
     hCloseEvent := CreateEvent( nil, True, False, nil );

     if hCloseEvent = 0 then
     begin
          CloseHandle( hCommFile );
          hCommFile := 0;
          FPortOpenError := 'Unable to create event';
//          raise ECommsError.Create( FPortOpenError );
          Exit;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -