Ассинхронная связь
unit Comm; interface uses Messages,WinTypes,WinProcs,Classes,Forms; type TPort=(tptNone,tptOne,tptTwo,tptThree,tptFour,tptFive,tptSix,tptSeven, tptEight); TBaudRate=(tbr110,tbr300,tbr600,tbr1200,tbr2400,tbr4800,tbr9600,tbr14400, tbr19200,tbr38400,tbr56000,tbr128000,tbr256000); TParity=(tpNone,tpOdd,tpEven,tpMark,tpSpace); TDataBits=(tdbFour,tdbFive,tdbSix,tdbSeven,tdbEight); TStopBits=(tsbOne,tsbOnePointFive,tsbTwo); TCommEvent=(tceBreak,tceCts,tceCtss,tceDsr,tceErr,tcePErr,tceRing,tceRlsd, tceRlsds,tceRxChar,tceRxFlag,tceTxEmpty); TCommEvents=set of TCommEvent; const PortDefault=tptNone; BaudRateDefault=tbr9600; ParityDefault=tpNone; DataBitsDefault=tdbEight; StopBitsDefault=tsbOne; ReadBufferSizeDefault=2048; WriteBufferSizeDefault=2048; RxFullDefault=1024; TxLowDefault=1024; EventsDefault=[]; type TNotifyEventEvent=procedure(Sender:TObject;CommEvent:TCommEvents) of object; TNotifyReceiveEvent=procedure(Sender:TObject;Count:Word) of object; TNotifyTransmitEvent=procedure(Sender:TObject;Count:Word) of object; TComm=class(TComponent) private FPort:TPort; FBaudRate:TBaudRate; FParity:TParity; FDataBits:TDataBits; FStopBits:TStopBits; FReadBufferSize:Word; FWriteBufferSize:Word; FRxFull:Word; FTxLow:Word; FEvents:TCommEvents; FOnEvent:TNotifyEventEvent; FOnReceive:TNotifyReceiveEvent; FOnTransmit:TNotifyTransmitEvent; FWindowHandle:hWnd; hComm:Integer; HasBeenLoaded:Boolean; Error:Boolean; procedure SetPort(Value:TPort); procedure SetBaudRate(Value:TBaudRate); procedure SetParity(Value:TParity); procedure SetDataBits(Value:TDataBits); procedure SetStopBits(Value:TStopBits); procedure SetReadBufferSize(Value:Word); procedure SetWriteBufferSize(Value:Word); procedure SetRxFull(Value:Word); procedure SetTxLow(Value:Word); procedure SetEvents(Value:TCommEvents); procedure WndProc(var Msg:TMessage); procedure DoEvent; procedure DoReceive; procedure DoTransmit; protected procedure Loaded;override; public constructor Create(AOwner:TComponent);override; destructor Destroy;override; procedure Write(Data:PChar;Len:Word); procedure Read(Data:PChar;Len:Word); function IsError:Boolean; published property Port:TPort read FPort write SetPort default PortDefault; property BaudRate:TBaudRate read FBaudRate write SetBaudRate default BaudRateDefault; property Parity:TParity read FParity write SetParity default ParityDefault; property DataBits:TDataBits read FDataBits write SetDataBits default DataBitsDefault; property StopBits:TStopBits read FStopBits write SetStopBits default StopBitsDefault; property WriteBufferSize:Word read FWriteBufferSize write SetWriteBufferSize default WriteBufferSizeDefault; property ReadBufferSize:Word read FReadBufferSize write SetReadBufferSize default ReadBufferSizeDefault; property RxFullCount:Word read FRxFull write SetRxFull default RxFullDefault; property TxLowCount:Word read FTxLow write SetTxLow default TxLowDefault; property Events:TCommEvents read FEvents write SetEvents default EventsDefault; property OnEvent:TNotifyEventEvent read FOnEvent write FOnEvent; property OnReceive:TNotifyReceiveEvent read FOnReceive write FOnReceive; property OnTransmit:TNotifyTransmitEvent read FOnTransmit write FOnTransmit; end; procedure Register; implementation procedure TComm.SetPort(Value:TPort); const CommStr:PChar='COM1:'; beginFPort:=Value; if (csDesigning in ComponentState) or (Value=tptNone) or (not HasBeenLoaded) then exit; if hComm>=0 then CloseComm(hComm); CommStr[3]:=chr(48+ord(Value)); hComm:=OpenComm(CommStr,ReadBufferSize,WriteBufferSize); if hComm<0 then begin Error:=True; exit; end; SetBaudRate(FBaudRate); SetParity(FParity); SetDataBits(FDataBits); SetStopBits(FStopBits); SetEvents(FEvents); EnableCommNotification(hComm,FWindowHandle,FRxFull,FTxLow); end;procedure TComm.SetBaudRate(Value:TBaudRate); var DCB:TDCB; beginFBaudRate:=Value; if hComm>=0 then begin GetCommState(hComm,DCB); case Value of tbr110:DCB.BaudRate:=CBR_110; tbr300:DCB.BaudRate:=CBR_300; tbr600:DCB.BaudRate:=CBR_600; tbr1200:DCB.BaudRate:=CBR_1200; tbr2400:DCB.BaudRate:=CBR_2400; tbr4800:DCB.BaudRate:=CBR_4800; tbr9600:DCB.BaudRate:=CBR_9600; tbr14400:DCB.BaudRate:=CBR_14400; tbr19200:DCB.BaudRate:=CBR_19200; tbr38400:DCB.BaudRate:=CBR_38400; tbr56000:DCB.BaudRate:=CBR_56000; tbr128000:DCB.BaudRate:=CBR_128000; tbr256000:DCB.BaudRate:=CBR_256000; end; SetCommState(DCB); end; end;procedure TComm.SetParity(Value:TParity); var DCB:TDCB; beginFParity:=Value; if hComm<0 then exit; GetCommState(hComm,DCB); case Value of tpNone:DCB.Parity:=0; tpOdd:DCB.Parity:=1; tpEven:DCB.Parity:=2; tpMark:DCB.Parity:=3; tpSpace:DCB.Parity:=4; end; SetCommState(DCB); end;procedure TComm.SetDataBits(Value:TDataBits); var DCB:TDCB; beginFDataBits:=Value; if hComm<0 then exit; GetCommState(hComm,DCB); case Value of tdbFour:DCB.ByteSize:=4; tdbFive:DCB.ByteSize:=5; tdbSix:DCB.ByteSize:=6; tdbSeven:DCB.ByteSize:=7; tdbEight:DCB.ByteSize:=8; end; SetCommState(DCB); end;procedure TComm.SetStopBits(Value:TStopBits); var DCB:TDCB; beginFStopBits:=Value; if hComm<0 then exit; GetCommState(hComm,DCB); case Value of tsbOne:DCB.StopBits:=0; tsbOnePointFive:DCB.StopBits:=1; tsbTwo:DCB.StopBits:=2; end; SetCommState(DCB); end;procedure TComm.SetReadBufferSize(Value:Word); begin FReadBufferSize:=Value; SetPort(FPort); end;procedure TComm.SetWriteBufferSize(Value:Word); begin FWriteBufferSize:=Value; SetPort(FPort); end;procedure TComm.SetRxFull(Value:Word); begin FRxFull:=Value; if hComm<0 then exit; EnableCommNotification(hComm,FWindowHandle,FRxFull,FTxLow); end;procedure TComm.SetTxLow(Value:Word); begin FTxLow:=Value; if hComm<0 then exit; EnableCommNotification(hComm,FWindowHandle,FRxFull,FTxLow); end;procedure TComm.SetEvents(Value:TCommEvents); var EventMask:Word; beginFEvents:=Value; if hComm<0 then exit; EventMask:=0; if tceBreak in FEvents then inc(EventMask,EV_BREAK); if tceCts in FEvents then inc(EventMask,EV_CTS); if tceCtss in FEvents then inc(EventMask,EV_CTSS); if tceDsr in FEvents then inc(EventMask,EV_DSR); if tceErr in FEvents then inc(EventMask,EV_ERR); if tcePErr in FEvents then inc(EventMask,EV_PERR); if tceRing in FEvents then inc(EventMask,EV_RING); if tceRlsd in FEvents then inc(EventMask,EV_RLSD); if tceRlsds in FEvents then inc(EventMask,EV_RLSDS); if tceRxChar in FEvents then inc(EventMask,EV_RXCHAR); if tceRxFlag in FEvents then inc(EventMask,EV_RXFLAG); if tceTxEmpty in FEvents then inc(EventMask,EV_TXEMPTY); SetCommEventMask(hComm,EventMask); end;procedure TComm.WndProc(var Msg:TMessage); begin with Msg do begin if Msg=WM_COMMNOTIFY then begin case lParamLo of CN_EVENT:DoEvent; CN_RECEIVE:DoReceive; CN_TRANSMIT:DoTransmit; end; end else Result:=DefWindowProc(FWindowHandle,Msg,wParam,lParam); end; end;procedure TComm.DoEvent; var CommEvent:TCommEvents; EventMask:Word; beginif (hComm<0) or not Assigned(FOnEvent) then exit; EventMask:=GetCommEventMask(hComm,Integer($FFFF)); CommEvent:=[]; if (tceBreak in Events) and (EventMask and EV_BREAK<>0) then CommEvent:=CommEvent+[tceBreak]; if (tceCts in Events) and (EventMask and EV_CTS<>0) then CommEvent:=CommEvent+[tceCts]; if (tceCtss in Events) and (EventMask and EV_CTSS<>0) then CommEvent:=CommEvent+[tceCtss]; if (tceDsr in Events) and (EventMask and EV_DSR<>0) then CommEvent:=CommEvent+[tceDsr]; if (tceErr in Events) and (EventMask and EV_ERR<>0) then CommEvent:=CommEvent+[tceErr]; if (tcePErr in Events) and (EventMask and EV_PERR<>0) then CommEvent:=CommEvent+[tcePErr]; if (tceRing in Events) and (EventMask and EV_RING<>0) then CommEvent:=CommEvent+[tceRing]; if (tceRlsd in Events) and (EventMask and EV_RLSD<>0) then CommEvent:=CommEvent+[tceRlsd]; if (tceRlsds in Events) and (EventMask and EV_Rlsds<>0) then CommEvent:=CommEvent+[tceRlsds]; if (tceRxChar in Events) and (EventMask and EV_RXCHAR<>0) then CommEvent:=CommEvent+[tceRxChar]; if (tceRxFlag in Events) and (EventMask and EV_RXFLAG<>0) then CommEvent:=CommEvent+[tceRxFlag]; if (tceTxEmpty in Events) and (EventMask and EV_TXEMPTY<>0) then CommEvent:=CommEvent+[tceTxEmpty]; FOnEvent(Self,CommEvent); end;procedure TComm.DoReceive; var Stat:TComStat; beginif (hComm<0) or not Assigned(FOnReceive) then exit; GetCommError(hComm,Stat); FOnReceive(Self,Stat.cbInQue); GetCommError(hComm,Stat); end;procedure TComm.DoTransmit; var Stat:TComStat; beginif (hComm<0) or not Assigned(FOnTransmit) then exit; GetCommError(hComm,Stat); FOnTransmit(Self,Stat.cbOutQue); end;procedure TComm.Loaded; begin inherited Loaded; HasBeenLoaded:=True; SetPort(FPort); end;constructor TComm.Create(AOwner:TComponent); begin inherited Create(AOwner); FWindowHandle:=AllocateHWnd(WndProc); HasBeenLoaded:=False; Error:=False; FPort:=PortDefault; FBaudRate:=BaudRateDefault; FParity:=ParityDefault; FDataBits:=DataBitsDefault; FStopBits:=StopBitsDefault; FWriteBufferSize:=WriteBufferSizeDefault; FReadBufferSize:=ReadBufferSizeDefault; FRxFull:=RxFullDefault; FTxLow:=TxLowDefault; FEvents:=EventsDefault; hComm:=-1; end;destructor TComm.Destroy; begin DeallocatehWnd(FWindowHandle); if hComm>=0 then CloseComm(hComm); inherited Destroy; end;procedure TComm.Write(Data:PChar;Len:Word); begin if hComm<0 then exit; if WriteComm(hComm,Data,Len)<0 then Error:=True; GetCommEventMask(hComm,Integer($FFFF)); end;procedure TComm.Read(Data:PChar;Len:Word); begin if hComm<0 then exit; if ReadComm(hComm,Data,Len)<0 then Error:=True; GetCommEventMask(hComm,Integer($FFFF)); end;function TComm.IsError:Boolean; begin IsError:=Error; Error:=False; end;procedure Register; begin RegisterComponents('Additional',[TComm]); end;end. |