-2

我无法从设备获取串行端口数据。下面是预期结果的图像:

期望结果:

在此处输入图像描述

不想要的结果:

在此处输入图像描述

我使用 Ttimer,所以我可以自动获取数据并将其放入备忘录中。

我需要在备忘录中逐行放置数据。

这是源代码:

procedure TForm3.Timer1Timer(Sender: TObject);
var
k: Integer;
InBuffer: array[1..500] of char;

begin

for k:=1 to 500  do
InBuffer[k]:=' '; 
Trim(InBuffer);

if cport.Connected = true then
begin
ComLed1.Kind := lkGreenLight;
cport.ReadStr(str,k);
Trim(str);
S:=str;

if str = '' then
begin

end
else
begin
memo1.lines.Add(str);
end;
end
else
begin
ComLed1.Kind := lkredLight; 
txt_com_status1.Caption := 'Connected';
end;
end;

我的问题是什么问题?什么是解决方案。

4

1 回答 1

3

TMemo.Lines.Add()添加一行。您添加的文本将在其末尾插入一个换行符。很明显,您正在接收分段的硬件数据,并且您将每个分段单独添加为备忘录中的自己的行。

要执行您正在尝试的操作,您需要:

  1. 从硬件读取片段并缓存它们,直到检测到完整消息的结尾,然后Add()仅将完整的消息发送到备忘录。您如何执行此操作取决于硬件用于向您发送数据的特定协议。它是否将数据包装在STX/ETX标记中?它是否分隔消息?我们不知道,您还没有提供任何相关信息。而且您的代码正在尝试(未成功)删除大量可能根本不应该丢弃的数据。

  2. 根本不要使用Add()。您可以改用该SelText属性来避免插入任何您不想要的换行符。

    memo1.SelStart := memo1.GetTextLen;
    memo1.SelLength := 0;
    memo1.SelText := str;
    

话虽如此,您的计时器代码正在做一些奇怪的事情。InBuffer用空格填充,然后(不成功)修剪,然后完全忽略。您将未初始化的k值传递给ReadStr(). str您读取的值在添加到备忘录之前未成功修剪。您分配strS然后忽略S.

试试这个:

procedure TForm3.Timer1Timer(Sender: TObject);
var
  str: AnsiString;
begin
  if cport.Connected then
  begin
    ComLed1.Kind := lkGreenLight;
    txt_com_status1.Caption := 'Connected';
    cport.ReadStr(str, 256);
    str := Trim(str);    
    if str <> '' then
    begin
      memo1.SelStart := memo1.GetTextLen;
      memo1.SelLength := 0;
      memo1.SelText := str;
    end;
  end
  else
  begin
    ComLed1.Kind := lkredLight; 
    txt_com_status1.Caption := 'Disconnected';
  end;
end;

或者(假设您使用TComPort的是有一个OnRxChar事件):

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  if cport.Connected then
  begin
    ComLed1.Kind := lkGreenLight;
    txt_com_status1.Caption := 'Connected';
  end
  else
  begin
    ComLed1.Kind := lkredLight; 
    txt_com_status1.Caption := 'Disconnected';
  end;
end;

procedure TForm3.cportRxChar(Sender: TObject; Count: Integer);
var
  str: AnsiString;
begin
  cport.ReadStr(str, Count);
  str := Trim(str);    
  if str <> '' then
  begin
    memo1.SelStart := memo1.GetTextLen;
    memo1.SelLength := 0;
    memo1.SelText := str;
  end;
end;

根据评论中提供的新信息进行编辑,尝试如下操作:

private
  buffer: AnsiString;
  portConnected: boolean;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  if cport.Connected then
  begin
    if not portConnected then
    begin
      portConnected := true;
      buffer := '';
      ComLed1.Kind := lkGreenLight;
      txt_com_status1.Caption := 'Connected';
    end;
  end
  else
  begin
    if portConnected then
    begin
      portConnected := false;
      ComLed1.Kind := lkredLight; 
      txt_com_status1.Caption := 'Disconnected';
    end;
  end;
end;

procedure TForm3.cportRxChar(Sender: TObject; Count: Integer);
var
  str: AnsiString;
  i: integer;
begin
  cport.ReadStr(str, Count);
  buffer := buffer + str;
  repeat
    i := Pos(#10, buffer);
    if i = 0 then Exit;
    str := Copy(buffer, 1, i-1);
    Delete(buffer, 1, i);
    memo1.Lines.Add(str);
  until buffer = '';
end;
于 2016-09-05T18:47:17.970 回答