一个自动控制机的硅控板检测程序,用多线程和API,没有用控件,少做改动就能用 Unit CommThread;
Interface
Uses Windows, Classes, SysUtils, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtCtrls; Type TThreadParam = Record SusPended: Boolean; BaulSpeed: integer; Port: Byte; Parity: Boolean; StopBit: byte; StartBit: Byte; SB: TStatusBar; LEDs: Array[0..24] Of TShape; End;
Type TReadThread = Class(TThread) Private { Private declarations } hComm: THandle; Port: integer; FErr: Boolean; FPortDescription: String; FShape: Array[0..24] Of TShape; FSB: TStatusBar; cc: TCOMMCONFIG; Data: String; Procedure ReadPort; //读取串行端口数据 Procedure UpdateUI; Protected Procedure Execute; Override; Public Constructor Create(ThdPrm: TThreadParam); End;
Implementation //uses Unit1; // 声明引用Unit1,必须放在implementation区段
Constructor TReadThread.Create(ThdPrm: TThreadParam); Var i: integer; Begin Port := thdprm.Port; FSB := thdprm.SB; For i := 0 To 24 Do Begin FShape[i] := thdPrm.LEDs[i]; End; FreeOnTerminate := True; Inherited Create(ThdPrm.SusPended); End;
Procedure TReadThread.Execute; Var PortToOpen: String; Begin PortToOpen := 'COM' + inttostr(Port); // 选择所要打开的COM hComm := CreateFile(PChar(PortToOpen), GENERIC_READ Or GENERIC_WRITE, 0, Nil, OPEN_EXISTING, 0, 0); // 打开COM If (hComm = INVALID_HANDLE_VALUE) Then Begin //如果COM 未打开 FErr := True; FPortDescription := '打开端口错误!'; End Else Begin FErr := False; FPortDescription := '打开端口成功'; GetCommState(hComm, cc.dcb); // 得知目前COM 的状态 cc.dcb.BaudRate := CBR_9600; // 设置波特率为9600 cc.dcb.ByteSize := 8; //字节为 8 bit cc.dcb.Parity := NOPARITY; // Parity 为 None cc.dcb.StopBits := ONESTOPBIT; // 1 个Stop bit If Not SetCommState(hComm, cc.dcb) Then Begin // 设置COM 的状态 Ferr := True; FPortDescription := FPortDescription + ',设置错误!'; CloseHandle(hComm); //关闭通信端口 End Else Begin FErr := False; FPortDescription := FPortDescription + ',设置成功'; While Not Terminated Do Begin Synchronize(ReadPort); //刚才所定义的读取数据函数 End; Synchronize(UpdateUI); End; End;
End;
Procedure TReadThread.ReadPort; Var i: integer; inbuff: Array[0..29] Of Char; nBytesRead, dwEvent, dwError: LongWORD; cs: TCOMSTAT; Rights, Emptys, Errs: integer; Const RightColor = clBlue; ErrorColor = clRed; EmptyColor = clWhite; Begin Rights := 0; Emptys := 0; Errs := 0; If (hComm = INVALID_HANDLE_VALUE) Then Begin Fsb.Panels[3].Text := FPortDescription; Terminate; //先判断是否已打开通信端口 Exit; End Else Begin Fsb.Panels[3].Text := FPortDescription; ClearCommError(hComm, dwError, @CS); //取得状态 ReadFile(hComm, inbuff, cs.cbInQue, nBytesRead, Nil); // 接收COM 的数据 //串行在读取数据后,会自动将缓冲区中已被读取的数据清除掉 If cs.cbInQue = 0 Then exit; // 数据是否大于我们所准备的Buffer If cs.cbInQue <> sizeof(inbuff) Then Begin PurgeComm(hComm, PURGE_RXCLEAR); // 清除COM 数据 exit; End; Data := Copy(inbuff, 1, cs.cbInQue); //取出数据 For i := 1 To 25 Do Begin If (UpperCase(Data[i]) = 'Y') Then Begin FShape[i].Brush.Color := RightColor; Rights := Rights + 1; End Else If (UpperCase(Data[i]) = 'N') Then Begin FShape[i].Brush.Color := EmptyColor; Emptys := Emptys + 1; End Else If (UpperCase(Data[i]) = 'E') Then Begin FShape[i].Brush.Color := ErrorColor; Errs := Errs + 1; End; End; Fsb.Panels[0].Text := '正确:' + IntTostr(Rights); fsb.Panels[1].Text := '空槽:' + IntTostr(Emptys); fsb.Panels[2].Text := '错误:' + IntTostr(Errs); Fsb.Panels[3].Text := FPortDescription; Fsb.Panels[4].Text := '数据:' + Data; End; End;
Procedure TReadThread.UpdateUI; Begin Fsb.Panels[0].Text := '正确:' + IntTostr(0); fsb.Panels[1].Text := '空槽:' + IntTostr(0); fsb.Panels[2].Text := '错误:' + IntTostr(0); Fsb.Panels[3].Text := ''; Fsb.Panels[4].Text := '数据:' + Data; End;
End.
|
请发表评论