Delphi-xe7 arduino tpapro ApdComPort 读取
Delphi-xe7 arduino tpapro ApdComPort read
我想通过 USB(串行)从我的 Arduino 读取一个字符串。
我制作了这个脚本,但它有问题:
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
msg:string;
I:word;
C:ansichar;
begin
msg := '';
for I := 1 to count do
begin
C := apdComPort1.GetChar;
if C = #7 = false then
begin
if C in [#32..#126] then
begin
msg := msg + C;
end;
end;
end;
listbox1.Items.Add(msg);
msg := '';
end;
问题是 "count" 不正确。
例如,当我发送 "Backspace" 时,这是输出:
Bac
kspace
但是在arduino串口监视器上它工作正常。
有谁知道为什么 "count" 不正确以及如何解决它?
您假设 完整 数据与事件之间存在一对一的关系。没有这样的保证。可能需要多个事件才能接收到 complete 数据。该事件只是报告 一些 数据可用在那一刻。在您的示例中,您可能收到了 3 个字符的事件,然后收到了剩余 6 个字符的第二个事件。您调用了 Add()
两次,一次针对数据的每个部分,而不是一次针对 complete 数据。
因此,您必须分析接收到的数据,根据需要在事件之间缓存它,然后仅当您有 完整 数据时才调用 Add()
展示。例如:
var
msg: string;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
I: Word;
C: AnsiChar;
begin
for I := 1 to Count do
begin
C := apdComPort1.GetChar;
if C <> #7 then
begin
if C in [#32..#126] then
begin
msg := msg + C;
end;
end else
begin
ListBox1.Items.Add(msg);
msg := '';
end;
end;
end;
正如 Remy 所说,在串行通信中接收数据时,您可能会为同一字符串触发许多事件。事实上每个字节是一个事件,但驱动程序通常缓冲数据。
要知道消息的结尾,您应该在此消息的末尾添加一些字符序列。如果您使用 Serial.println()
而不是 Serial.print()
从 Arduino 发送字符串,那么它将在文本后添加一个新的行标记。这样你只需要将字符添加到 ListBox1.Items.Text
属性 而不是使用 Add
函数。您需要允许字符 #10 和 #13 才能完成这项工作。
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
C: AnsiChar;
begin
while Count > 0 do
begin
Dec(Count);
C := apdComPort1.GetChar;
if C in [#32..#126, #10, #13] then
begin
ListBox1.Items.Text := ListBox1.Items.Text + C;
end;
end;
end;
此外,如果您这样做,则无需发送响铃字符 (#7)。
我想通过 USB(串行)从我的 Arduino 读取一个字符串。 我制作了这个脚本,但它有问题:
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
msg:string;
I:word;
C:ansichar;
begin
msg := '';
for I := 1 to count do
begin
C := apdComPort1.GetChar;
if C = #7 = false then
begin
if C in [#32..#126] then
begin
msg := msg + C;
end;
end;
end;
listbox1.Items.Add(msg);
msg := '';
end;
问题是 "count" 不正确。 例如,当我发送 "Backspace" 时,这是输出:
Bac
kspace
但是在arduino串口监视器上它工作正常。 有谁知道为什么 "count" 不正确以及如何解决它?
您假设 完整 数据与事件之间存在一对一的关系。没有这样的保证。可能需要多个事件才能接收到 complete 数据。该事件只是报告 一些 数据可用在那一刻。在您的示例中,您可能收到了 3 个字符的事件,然后收到了剩余 6 个字符的第二个事件。您调用了 Add()
两次,一次针对数据的每个部分,而不是一次针对 complete 数据。
因此,您必须分析接收到的数据,根据需要在事件之间缓存它,然后仅当您有 完整 数据时才调用 Add()
展示。例如:
var
msg: string;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
I: Word;
C: AnsiChar;
begin
for I := 1 to Count do
begin
C := apdComPort1.GetChar;
if C <> #7 then
begin
if C in [#32..#126] then
begin
msg := msg + C;
end;
end else
begin
ListBox1.Items.Add(msg);
msg := '';
end;
end;
end;
正如 Remy 所说,在串行通信中接收数据时,您可能会为同一字符串触发许多事件。事实上每个字节是一个事件,但驱动程序通常缓冲数据。
要知道消息的结尾,您应该在此消息的末尾添加一些字符序列。如果您使用 Serial.println()
而不是 Serial.print()
从 Arduino 发送字符串,那么它将在文本后添加一个新的行标记。这样你只需要将字符添加到 ListBox1.Items.Text
属性 而不是使用 Add
函数。您需要允许字符 #10 和 #13 才能完成这项工作。
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
C: AnsiChar;
begin
while Count > 0 do
begin
Dec(Count);
C := apdComPort1.GetChar;
if C in [#32..#126, #10, #13] then
begin
ListBox1.Items.Text := ListBox1.Items.Text + C;
end;
end;
end;
此外,如果您这样做,则无需发送响铃字符 (#7)。