1

シリアル回線 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#


コンポートのバッファを拡張しようとしましたが、結果はありませんでした。

では、なぜ一発で完全な文字列を受信できないのでしょうか?

ここでこのライブラリを見つけましたが、今までは問題なく動作しています:

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

4

2 に答える 2

4

TComPort コンポーネントには、TComDataPacket という別のコンポーネントが付属しています。これを TComPort に接続し、StartString および StopString プロパティを設定し、イベント 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;
于 2014-03-16T15:42:56.430 に答える
3

そのような低レベルのコミュニケーションでは、どのようなコミュニケーションにおいても完全なメッセージを受け取ることに頼ることはできません。また、一度に 1 つのメッセージしか受信できないことに依存することもできません。

完全なメッセージでのみ通知することを保証する何かを実装する必要があります。

そのためには、完全なメッセージ (ヘッダーと終了フラグ) を受信するまで受信データを保存する必要があります。

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

このクラスは、ヘッダーと終了文字を削除します。これは、トランスポート プロトコルの一部であり、不要になったためです。ただし、必要に応じて追加できます。

于 2014-03-16T13:49:56.837 に答える