Comport readstr

时间:2014-03-16 11:36:02

标签: delphi tcomport

我正在尝试从串行线RS232上的主机读取一个简单的字符串。 接收 - 传输的参数对于两者都是相同的:

Baudrate: 9600;
Data: 8bit;
Parity: None;
Stop: 1bit;
Flow Control: None;

我试过发送这个字符串:

!A243B324C213D300#

我用'!'和'#'作为标题并完成以确保字符串将被接收。 问题是我可以收到字符串直到第15个字符(3)。

我知道这个,因为如果我使用这段代码:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
begin
 ComPort1.ReadStr(Str, Count);
 memo1.Lines.Add(str);
end;

我会看到


!A243B324C213D3

00#


我试图扩展comport的缓冲区,没有结果。

那么为什么我不能一次性收到完整的字符串?

我在这里找到了这个库,它现在可以正常工作:

http://sourceforge.net/projects/comport/

2 个答案:

答案 0 :(得分:4)

使用TComPort组件来另一个:TComDataPacket。只需将其连接到TComPort,设置StartString和StopString属性,并使用event onPacket获取完整数据。

示例:

...
    ComDataPacket1.Comport := Comport1;
    ComDataPacket1.StartString := '!';
    ComDataPacket1.StopString := '#';
    ComDataPacket1.onPacket := ComDataPacket1Packet;
...

//this is real code from one of my applications where I use it for barcode reader service
procedure TDM.ComDataPacket1Packet(Sender: TObject; const Str: string);
begin
     BarCodeReader.Barcode := Str;  
end;

答案 1 :(得分:3)

在低通信级别的任何通信中,您都不能依赖于接收完整的消息。此外,您不能一次只接收一条消息。

您必须实施某些内容,以确保仅通知完整的消息。

为此,您必须存储传入的数据,直到收到完整的消息(标题和完成标记)。

这是一个带有TMessageBuffer类的小型控制台应用程序,用于处理传入数据和完成消息

program so_22436319;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  SysUtils;

type
  TMessageBuffer = class
  private
    FBuffer : string;
    FMsgPart : Boolean;
    procedure DoHandleMessage( const CompleteMessage : string );
  public
    procedure AddData( const Data : string );
  end;

procedure Test;
var
  LMsgBuffer : TMessageBuffer;
begin
  LMsgBuffer := TMessageBuffer.Create;
  try
    // receive complete message
    LMsgBuffer.AddData( '!A243B324C213D300#' );
    // receive 2 complete message in one go
    LMsgBuffer.AddData( '!A243B324C213D300#!A243B324C213D300#' );
    // receive parts of the message
    LMsgBuffer.AddData( '!A243B324' );
    LMsgBuffer.AddData( 'C213D300#!A243' );
    LMsgBuffer.AddData( 'B324C213D300#!A' );
    LMsgBuffer.AddData( '243B324C2' );
    LMsgBuffer.AddData( '13D300#' );

  finally
    LMsgBuffer.Free;
  end;
end;

  { TMessageBuffer }

procedure TMessageBuffer.AddData( const Data : string );
var
  LIdx : Integer;
  LChar : Char;
begin
  for LIdx := 1 to Length( Data ) do
  begin
    LChar := Data[LIdx];
    if FMsgPart then
      if LChar = '#' then
      begin
        DoHandleMessage( FBuffer );
        FMsgPart := False;
        FBuffer := '';
      end
      else
      begin
        FBuffer := FBuffer + LChar
      end
    else if LChar = '!' then
    begin
      FMsgPart := True;
    end;
  end;
end;

procedure TMessageBuffer.DoHandleMessage( const CompleteMessage : string );
begin
  Writeln( 'MSG: ', CompleteMessage );
end;

begin
  try
    Test;
  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;
  ReadLn;
end.

生成的输出是

MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300

该类删除标题并完成char,因为这是传输协议的一部分,因此不再需要。但如果你愿意,你仍然可以添加它。