【问题标题】:Serial Port Synchronization in DelphiDelphi中的串口同步
【发布时间】:2014-08-22 15:09:30
【问题描述】:

我仍然对 TComPort 组件有问题,但这次不是组件本身,而是它背后的逻辑。我有一个设备女巫通过串行端口发送一些 ascii 字符串我需要 prase 这些字符串问题是计算机反应非常快,所以在事件 char 它只捕获字符串的一部分,其余的字符串稍后回来......所以当它被接收时解析它是不可能的。

我正在考虑编写一个计时器来验证是否在 10 秒或更长时间内没有串行活动,然后将我保存到缓冲区中的字符串 prase。但是这种方法是不专业的,不是有一个空闲的事件女巫我可以听...等待我的问题的最佳解决方案。谢谢。

【问题讨论】:

  • 这是一个已知问题。在更多环境中使用它。数据事件触发确实比后面的数据快。除了在阅读前稍等片刻之外,我不确定还有什么其他的。
  • 这很正常,您应该简单地将字符存储在缓冲区中,然后重置计时器。然后使用计时器来触发实际活动 - 计时器可能非常紧张。您希望以“状态机”结束并拥有事件触发器。
  • 假设您使用 Djean Crnila 等人的 TComport(有几个组件称为“TComport”)。此问题可能与数据事件触发有关,但也可能您的串行设备的波特率设置为与您的 comport 控件的速率不同的速率。如果您的设备每隔几毫秒发送一次数据包,如果数据包的长度合理,您应该能够轻松捕获和解析整个数据包。设备是否发送数据包结束控制字符? - 使它更容易。如果您提供有关设备、收到的数据包等的更多信息。有人可能会提供帮助。
  • 编写一个数据包组件并不难。事件中的所有数据都进入缓冲区,数据包分析缓冲区,根据您的需要,您可以有一个 startcondition、endcondition 等等......

标签: delphi serial-port


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    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;
    

    【讨论】:

    • 字符串中包含#0这样的字符,所以readstr方法的使用肯定不在问题范围内
    • pascal 字符串不重要(直到操作系统函数输出)
    • @opc0de,在 pascal 中,#0 字符与任何其他字符一样。如果您更喜欢使用字节,请将 AnsiChars/AnsiStrings 交换为 Bytes/TBytes。这是自 D2009 和 unicode 以来的首选方式。
    • Reading binary data from serial port using Dejan TComport Delphi component 为例,但正如 MBo 所说,TComPort.Read( var buffer; Count:Integer)TComPort.ReadStr( var Str:AnsiStr; count:Integer) 之间没有根本区别。
    【解决方案3】:

    注意。 大多数 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;
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 当我在 Delphi 7 中使用 TComDataPacket 时收到访问冲突,但不是一直使用,而是在数据包更大时
      • 好的,我看到沃伦在你的另一个问题中反对它。不过,我们只是在 Delphi XE2 中成功使用了它。
      • 似乎定义了一个大小为 1024 字节的固定缓冲区。尝试在构造函数中增加它,看看这是否有助于更大的数据包。
      【解决方案5】:

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

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

      ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多