在 delphi 中拆分串行数据
Split up serial data in delphi
我是 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
错误。
如果 Comport 是 Dejan Crnila CPort class,那么这一行
ComPort1.ReadStr(DataByte,1);
每次都替换Databyte的内容,这个字符串总是1个字节的长度。
只需一次调用即可从缓冲区中读取所有字节
ComPort1.ReadStr(DataByte, Count);
并使用字符串
您正在调用 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;
我是 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
错误。
如果 Comport 是 Dejan Crnila CPort class,那么这一行
ComPort1.ReadStr(DataByte,1);
每次都替换Databyte的内容,这个字符串总是1个字节的长度。
只需一次调用即可从缓冲区中读取所有字节
ComPort1.ReadStr(DataByte, Count);
并使用字符串
您正在调用 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;