我是Delphi编程的新手,我需要一些帮助。我在分割我的串行数据时遇到问题。这是我的代码:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
DataByte : string;
x, i: integer;
save_data : TStringList;
begin
save_data := TStringList.create;
for x := 0 to Count-1 do begin
ComPort1.ReadStr(DataByte,1);
if DataByte = 'n' then
begin
memo1.Text := '';
end
else
begin
memo1.Text := memo1.Text + DataByte;
Split(' ', DataByte, save_data);
end;
end;
save_gyroX := save_data[0];
save_gyroY := save_data[1];
save_gyroZ := save_data[2];
save_accelX := save_data[3];
save_accelY := save_data[4];
save_accelZ := save_data[5];
SerialProcess();
save_data.Free;
end;
我的Split(' ', DataByte, save_data);
无效。我不明白,因为我只是将String
数据从串口中取出。这是我的Split()
程序:
procedure TForm1.Split(const Delimiter: Char; Input: string; const Strings: TStrings) ;
begin
Assert(Assigned(Strings));
Strings.Clear;
Strings.Delimiter := Delimiter;
Strings.DelimitedText := Input;
end;
我不知道为什么我的程序给了EStringListError
错误。
答案 0 :(得分:2)
您正在调用ReadStr()
来读取单个字节,并在每个字节上调用Split()
('n'
除外)。所以TStringList
一次只能容纳1个字符串。就像MBo所说,你需要修复你的循环以避免这种情况,例如:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
DataByte : string;
x: integer;
save_data : TStringList;
begin
ComPort1.ReadStr(DataByte, Count);
for x := 1 to Length(DataByte) do
begin
if DataByte[x] = 'n' then
begin
Memo1.Text := '';
end
else
begin
Memo1.Text := Memo1.Text + DataByte[x];
end;
end;
save_data := TStringList.create;
try
Split(' ', DataByte, save_data);
save_gyroX := save_data[0];
save_gyroY := save_data[1];
save_gyroZ := save_data[2];
save_accelX := save_data[3];
save_accelY := save_data[4];
save_accelZ := save_data[5];
SerialProcess();
finally
save_data.Free;
end;
end;
话虽如此,您没有考虑到任何给定OnRxChar
事件调用的字节数是任意。它是在那个确切时刻读取的原始字节。您假设一个包含至少6个分隔子串的完整字符串,这根本不能保证。您需要在收到原始数据时对其进行缓冲,然后根据需要从缓冲区中解析并删除已完成的字符串。
尝试更像这样的事情:
var
DataBuffer: string;
// consider using the OnRxBuf event instead...
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
DataByte : string;
x: integer;
save_data : TStringList;
begin
ComPort1.ReadStr(DataByte, Count);
DataBuffer := DataBuffer + DataByte;
x := Pos('n', DataBuffer);
if x = 0 then Exit;
save_data := TStringList.Create;
try
repeat
DataByte := Copy(DataBuffer, 1, x-1);
Delete(DataBuffer, 1, x);
Memo1.Text := DataByte;
Split(' ', DataByte, save_data);
if save_data.Count >= 6 then
begin
save_gyroX := save_data[0];
save_gyroY := save_data[1];
save_gyroZ := save_data[2];
save_accelX := save_data[3];
save_accelY := save_data[4];
save_accelZ := save_data[5];
SerialProcess();
end;
x := Pos('n', DataBuffer);
until x = 0;
finally
save_data.Free;
end;
end;
答案 1 :(得分:1)
如果Comport是Dejan Crnila CPort类,那么这一行
ComPort1.ReadStr(DataByte,1);
每次都替换Databyte内容,此字符串的长度始终为1个字节。
只需通过一次调用
读取缓冲区中的所有字节ComPort1.ReadStr(DataByte, Count);
并使用字符串