2

私はまだTComPortコンポーネントに問題がありますが、今回はコンポーネント自体がその背後にあるロジックではありません。私はデバイスの魔女がシリアルポートを介していくつかのASCII文字列を送信しています。これらの文字列を解析する必要があります。問題はコンピュータが非常に高速に反応するため、charが文字列の一部のみをキャプチャした場合、残りの文字列は後で返されます...そのため、受信時に解析すると不可能になります。

私はタイマーの魔女を書くことで、10秒以上のシリアルアクティビティがなかったかどうかを確認してから、バッファに保存している文字列を処理することを考えていました。しかし、この方法は専門的ではありません。私が聞くことができるアイドルイベントの魔女はありません...私の問題の最善の解決策を待っています。ありがとう。

4

5 に答える 5

4

いくつかのシリアルポートコンポーネントを使用した後、これまで、を使用しCreateFile('\\?\COM1',GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0)てそのハンドルをTHandleStreamインスタンスに渡し、そこから読み取る専用スレッドを開始することで、最良の結果が得られました。スレッドはイベントハンドラーを作成するよりも少し手間がかかることは知っていますが、それでもシリアルポートの使用から発生する同期の問題を処理するための最良の方法です。

于 2012-05-11T15:28:02.613 に答える
3

OnRXCharイベントの一般的なハンドラー:

procedure XXX.RXChar(Sender: TObject; Count: Integer);
begin
  ComPort.ReadStr(s, Count);
  Accumulator := Accumulator + s;
  if not AccumContainsPacketStart then
    Accumulator := ''
  else if AccumContainsPacketEndAfterStart then begin
    ExtractFullStringFromAccum;
    ParseIt;
  end;
end;
于 2012-05-11T14:09:27.023 に答える
2

ノート。 ほとんどのcom-portコンポーネントには、所有者にいつ報告するかについての手がかりがありません。通常、ポートからバイトを収集する責任があるスレッドは、1つ以上のバイトを処理する準備ができていることをOSから通知されます。この情報は、単にあなたのレベルにポップアップされます。したがって、メッセージが転送されることを期待すると、OSが提供するものを取得できます。

すべての着信文字をグローバルバッファにバッファリングする必要があります。メッセージ文字列の最後の文字を取得したら、メッセージを処理します。

これは、メッセージの開始が特殊文字で識別され、メッセージの終了が別の文字で識別される例です。

メッセージが別の方法で作成されている場合は、コードを適応させる方法を理解できると確信しています。

var
  finalBuf: AnsiString;

{- Checking message }
Function ParseAndCheckMessage(const parseS: AnsiString) : Integer;
begin
  Result := 0; // Assume ok
  {- Make tests to confirm a valid message }
  ...
end;


procedure TMainForm.ComPortRxChar(Sender: TObject; Count: Integer);
var
  i,err: Integer;
  strBuf: AnsiString;
begin
  ComPort.ReadStr(strBuf, Count);
  for i := 1 to Length(strBuf) do
    case strBuf[i] of
      '$' : 
        finalBuf := '$';  // Start of package
      #10 :
        begin
          if (finalBuf <> '') and (finalBuf[1] = '$') then  // Simple validate check 
            begin
              SetLength( finalBuf, Length(finalBuf) - 1); // Strips CR
              err := ParseAndCheckMessage(finalBuf);
              if (err = 0) then 
                {- Handle validated string }
              else
                {- Handle error } 
            end;
          finalBuf := '';
        end; 
    else
      finalBuf := finalBuf + strBuf[i];  
    end;
end;
于 2012-05-11T14:09:53.310 に答える
1

プロトコルに開始/終了マーカーがある場合は、TComDataPacketを使用して、使用可能な場合は完全なパケットを提供できます。

于 2012-05-11T20:06:09.240 に答える
-2

特定の文字量については、ReadStrの数ミリ秒前に遅延を使用して、データが完全に送信されるようにすることができます。4文字量の例:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Str: String;
  tegangan : real;
begin
  sleep(100); //delay for 100ms
  ComPort1.ReadStr(Str, 4);

..。

于 2014-08-22T06:57:14.203 に答える