Delphi中的串口同步

时间:2012-05-11 11:48:23

标签: delphi serial-port

我仍然遇到TComPort组件的问题,但这次不是组件本身就是它背后的逻辑。我有一个设备巫婆通过串口发送一些ascii字符串我需要删除那些字符串问题是计算机反应非常快所以在事件char它只捕获字符串的一部分其余的字符串后来回来...所以在收到它时解析就不可能了。

我正在考虑编写一个计时器,以验证是否没有串口活动10个secons或更多,然后将我保存的字符串写入缓冲区。但这种方法是不专业的,不存在我可以听的空闲事件......等待我的问题的最佳解决方案。感谢。

5 个答案:

答案 0 :(得分:3)

OnRXChar事件的典型处理程序:

procedure XXX.RXChar(Sender: TObject; Count: Integer);
begin
  ComPort.ReadStr(s, Count);
  Accumulator := Accumulator + s;
  if not AccumContainsPacketStart then
    Accumulator := ''
  else if AccumContainsPacketEndAfterStart then begin
    ExtractFullStringFromAccum;
    ParseIt;
  end;
end;

答案 1 :(得分:3)

使用了许多串口组件后,到目前为止,我已经获得了最好的结果,使用CreateFile('\\?\COM1',GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0),将该句柄传递给THandleStream实例,并启动一个专用线程来读取它。我知道线程比编写事件处理程序需要更多的工作,但它仍然是处理使用串行端口引起的任何同步问题的最佳方法。

答案 2 :(得分:2)

注意。 大多数com-port组件都没有线索何时向所有者报告。通常,操作系统通知负责从端口收集字节的线程准备好处理一个或多个字节。然后,这些信息会弹出到您的级别。因此,当您希望传输消息时,您将获得操作系统为您提供的信息。

您必须缓冲全局缓冲区中的所有传入字符。当您在消息字符串中获得最后一个字符时,请处理该消息。

下面是一个示例,其中使用特殊字符标识消息开头,并使用另一个字符标识消息的结尾。

如果您的消息是以其他方式构建的,我相信您可以弄清楚如何调整代码。

var
  finalBuf: AnsiString;

{- Checking message }
Function ParseAndCheckMessage(const parseS: AnsiString) : Integer;
begin
  Result := 0; // Assume ok
  {- Make tests to confirm a valid message }
  ...
end;


procedure TMainForm.ComPortRxChar(Sender: TObject; Count: Integer);
var
  i,err: Integer;
  strBuf: AnsiString;
begin
  ComPort.ReadStr(strBuf, Count);
  for i := 1 to Length(strBuf) do
    case strBuf[i] of
      '$' : 
        finalBuf := '$';  // Start of package
      #10 :
        begin
          if (finalBuf <> '') and (finalBuf[1] = '$') then  // Simple validate check 
            begin
              SetLength( finalBuf, Length(finalBuf) - 1); // Strips CR
              err := ParseAndCheckMessage(finalBuf);
              if (err = 0) then 
                {- Handle validated string }
              else
                {- Handle error } 
            end;
          finalBuf := '';
        end; 
    else
      finalBuf := finalBuf + strBuf[i];  
    end;
end;

答案 3 :(得分:1)

如果你的协议有开始/结束标记,你可以使用TComDataPacket为它们提供完整的数据包。

答案 4 :(得分:-2)

对于一定数量的字符,我们可以在ReadStr之前使用延迟几毫秒来确保数据完全发送。 4个字符数量的示例:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Str: String;
  tegangan : real;
begin
  sleep(100); //delay for 100ms
  ComPort1.ReadStr(Str, 4);

...