如何增加分配给变量的串行数据的数量?

Mat*_*eng 5 delphi serial-port delphi-7

我已经下载并安装了comport库.我有一个模拟器通过串口RS232发送数据到Selphi程序.这是以下代码段.

procedure TMainForm.ComPortRxChar(Sender: TObject; Count: Integer);
begin
  ComPort.ReadStr(CPort.Str, Count);
  Memo.Text := Memo.Text + CPort.Str;
end; 
Run Code Online (Sandbox Code Playgroud)

至于CPort库部分,我补充说:

var
  Str: String;

here is the problem.
Run Code Online (Sandbox Code Playgroud)

正在经历的数据示例大致相同

$HEHDT,288.45,T*1D
$HEHDT,288.46,T*18
$HEHDT,288.47,T*1A
Run Code Online (Sandbox Code Playgroud)

等等.每行每秒发送一次.因此,使用上面的代码,备忘录将显示所有这些数据.

但是,如果我将代码更改为:

procedure TMainForm.ComPortRxChar(Sender: TObject; Count: Integer);
begin
  ComPort.ReadStr(CPort.Str, Count);
  Memo.Text := Memo.Text + CPort.Str + 'haha';
end;
Run Code Online (Sandbox Code Playgroud)

这是备忘录上的内容:

$HEHDT,2haha88.45,T*haha1Dhaha
$HEHDT,2haha88.46,T*haha18haha
$HEHDT,2haha88.47,T*haha1Ahaha
Run Code Online (Sandbox Code Playgroud)

8个ASCII字符后出现"haha".这意味着在CPort.pas库中,在异步/同步部分下,只有8ASCII字符max被赋给变量Str?

如何更改代码,使整个数据字符串(无论大小)分配给变量Str而不是8字节.

更新**我意识到这部分CPort库包含以下代码.任何人都可以启发我如何编辑代码?或者它是否是我采购的正确块.谢谢!

// split buffer in packets
procedure TComDataPacket.HandleBuffer;

procedure DiscardPacketToPos(Pos: Integer);
var
Str: string;
begin
FInPacket := True;
if Pos > 1 then
begin
  Str := Copy(Buffer, 1, Pos - 1); // some discarded data
  Buffer := Copy(Buffer, Pos, Length(Buffer) - Pos + 1);
  DoDiscard(Str);
end;
end;

procedure FormPacket(CutSize: Integer);
var
Str: string;
begin
Str := Copy(Buffer, 1, CutSize);
Buffer := Copy(Buffer, CutSize + 1, Length(Buffer) - CutSize);
CheckIncludeStrings(Str);
DoPacket(Str);
end;

procedure StartPacket;
var
Found: Integer;
begin
// check for custom start condition
Found := -1;
DoCustomStart(Buffer, Found);
if Found > 0 then
  DiscardPacketToPos(Found);
if Found = -1 then
begin
  if Length(FStartString) > 0 then // start string valid
  begin
    Found := Pos(Upper(FStartString), Upper(Buffer));
    if Found > 0 then
      DiscardPacketToPos(Found);
  end
  else
    FInPacket := True;
end;
end;

procedure EndPacket;
var
Found, CutSize, Len: Integer;
begin
// check for custom stop condition
Found := -1;
DoCustomStop(Buffer, Found);
if Found > 0 then
begin
  // custom stop condition detected
  CutSize := Found;
  FInPacket := False;
end
else
  if Found = -1 then
  begin
    Len := Length(Buffer);
    if (FSize > 0) and (Len >= FSize) then
    begin
      // size stop condition detected
      FInPacket := False;
      CutSize := FSize;
    end
    else
    begin
      Len := Length(FStartString);
      Found := Pos(Upper(FStopString),
        Upper(Copy(Buffer, Len + 1, Length(Buffer) - Len)));
      if Found > 0 then
      begin
        // stop string stop condition detected
        CutSize := Found + Length(FStopString) + Len - 1;
        FInPacket := False;
      end;
    end;
  end;
if not FInPacket then
  FormPacket(CutSize); // create packet
end;
Run Code Online (Sandbox Code Playgroud)

LU *_* RD 2

具有完整错误检查的简约解决方案是:

\n\n

更新 :

\n\n

(假设接收到的字符串以CRLF组合结尾,并且数据包长度不是恒定的。这是一个NMEA 0183数据包)

\n\n
var\n  finalBuf: AnsiString;\n\n// Example packet: $HEHDT,10.17,T*28 + CRLF\n// This is a NMEA 0183 protocol (Marine and GPS standard)\n// Subset for reading the heading.\n// HDT Heading \xe2\x80\x93 True\n//       1   2 3\n//       |   | |\n//$--HDT,x.x,T*hh\n//1) Heading Degrees, true\n//2) T = True\n//3) Checksum\n// HE stands for: Heading \xe2\x80\x93 North Seeking Gyro\n\n{- Checking packet and checksum, calculating heading }\nFunction ParseAndCheckNMEA_HDT(const parseS: AnsiString;\n  var heading: Double): Integer;\n// Example packet: $HEHDT,10.17,T*28 + CRLF\nvar\n  i, p, err: Integer;\n  xorSum: Byte;\n  xorStr: AnsiString;\n  headingStr: AnsiString;\nbegin\n  Result := 0; // Assume ok\n  if (Pos('$HEHDT', parseS) = 1) then // Start header ok ?\n  begin\n    p := Pos('*', parseS);\n    if (p <> 0) and (Length(parseS) >= p + 2) then\n    // Assumes a checksum in packet\n    begin\n      xorSum := Ord(parseS[2]);\n      for i := 3 to p - 1 do // Calculate checksum\n        xorSum := xorSum xor Ord(parseS[i]);\n      xorStr := IntToHex(xorSum, 2);\n      if (UpperCase(xorStr) = Copy(parseS, p + 1, 2)) then // Checksum ok ?\n      begin\n        // Validate heading\n        headingStr := Copy(parseS, 8, p - 10);\n        Val(headingStr, heading, err);\n        if (err <> 0) then\n          Result := 4; // Not a valid float\n      end\n      else\n        Result := 3; // Wrong checksum\n    end\n    else\n      Result := 2; // No checksum\n  end\n  else\n    Result := 1; // Wrong header\nend;\n\n\nprocedure TMainForm.ComPortRxChar(Sender: TObject; Count: Integer);\nvar\n  i,err: Integer;\n  strBuf: AnsiString;\n  heading: Double;\nbegin\n  ComPort.ReadStr(CPort.Str, Count);\n  strBuf := CPort.str;\n  for i := 1 to Length(strBuf) do\n    case strBuf[i] of\n      '$' : \n        finalBuf := '$';  // Start of package\n      #10 :\n        begin\n          if (finalBuf <> '') and (finalBuf[1] = '$') then  // Simple validate check \n            begin\n              SetLength( finalBuf, Length(finalBuf) - 1); // Strips CR\n              err := ParseAndCheckNMEA_HDT(finalBuf, heading);\n              if (err = 0) then \n                Memo.Lines.Add(finalBuf); // Add validated string\n              //else\n              //  Memo.Lines.Add('Error:' + IntToStr(err)); \n            end;\n          finalBuf := '';\n        end; \n    else\n      finalBuf := finalBuf + strBuf[i];  \n    end;\nend;\n
Run Code Online (Sandbox Code Playgroud)\n\n

知道起始字符和数据包结束符后,使用起来应该相当安全。\n标记数据包结束的 #13 和 #10 (CR LF) 字符将被剥离,并检查数据包的有效校验和以及生成的标题计算值。\n然后将经过验证的字符串添加到备忘录中。

\n\n

更新2

\n\n

要回答直接问题,为什么您的接收方法可以在数据字符串中间添加“haha”字符串:

\n\n

通信例程按照自己的节奏传送数据、一个或多个字符。您无法控制何时获取数据或有多少个字符。使用我的答案中的方案,数据会被缓冲,直到交付完整的包为止。有了 TComPort 的数据包支持,就可以做到同样的事情。

\n\n

从您的评论来看,似乎有几种 NMEA 0183 传感器类型连接到串行端口。(给出其他长度的包,但全部以 $ 字符开头)。

\n\n

将 ParseAndCheckNMEA_HDT 替换为以下函数以验证这种情况下的字符串:

\n\n
Function ParseAndCheckNMEA(const parseS: AnsiString): Integer;\n// Example packet: $HEHDT,10.17,T*28 + CRLF\nvar\n  i, p: Integer;\n  xorSum: Byte;\n  xorStr: AnsiString;\nbegin\n  Result := 0; // Assume ok\n  if (Pos('$', parseS) = 1) then // Start header ok ?\n  begin\n    p := Pos('*', parseS);\n    if (p <> 0) and (Length(parseS) >= p + 2) then\n    // Assumes a checksum in packet\n    begin\n      xorSum := Ord(parseS[2]);\n      for i := 3 to p - 1 do // Calculate checksum\n        xorSum := xorSum xor Ord(parseS[i]);\n      xorStr := IntToHex(xorSum, 2);\n      if (UpperCase(xorStr) <> Copy(parseS, p + 1, 2)) then // Checksum ok ?\n        Result := 3; // Wrong checksum\n    end\n    else\n      Result := 2; // No checksum\n  end\n  else\n    Result := 1; // Wrong header\nend;\n
Run Code Online (Sandbox Code Playgroud)\n