3

「ビッグネーム」のサードパーティのシリアルポートコンポーネントを使用しています(はい、サポートを依頼しましたが、タイムゾーンの違いがあり、これを非常に迅速に修正する必要があります). このコンポーネントは何年も前から存在しており、問題がコンポーネントにあると信じる理由はありません (ハードウェアも同様です)。

ハードウェア仕様によると、特定の文字列を seial ポートに書き込み、キャリッジ リターンで終了してから読み取ると、具体的にフォーマットされた 8 文字の文字列で応答し、再びキャリッジ リターンで終了します。

コードは、これを正しく実行し、読み取った内容に基づいて GUI を更新することで、何時間も実行できます。

ただし、GUI でユーザー アクティビティが発生すると、シリアル ポートからジャンクを読み取ります。

ボタンをクリックしてモーダルフォームを開き、フォームを閉じたときに最初に気付きました。

ただし、TStringGrid のスクロールバーをドラッグするだけでも表示されます。

これがコードです。何かアドバイス?


更新: コンポーネントはスレッド化されており、サプライヤはここのポスターに同意しています。シリアル ポートは非​​同期デバイスです。コンポーネントの OnCharReceived() イベント ハンドラーで、データの要求を記述し、受信した各文字を処理するようにコードを変更しました。すべての助けのためのTahnsk。


function TForm1.ReadChannelValueFromSerialPort(
                       device_number : String; channel_number : String) : Real;
   const SLEEP_TIME = 50;         // ms
         NUM_READ_ATTEMPTS = 10;

   var serialPortInput : String;
       read_attempt_counter : Integer;
       messageString : String;
begin
   WriteToSerialPort('#' +  device_number + channel_number + #13);

   serialPortInput := '';
   read_attempt_counter := 0;

   while Length(serialPortInput) = 0 do
   begin
      try
         Application.ProcessMessages();
         serialPortInput := serialPortInput + SerialPort.ReadText();

      except
         on E: Exception do
         begin
            messageString := 'Can''t read from serial port' ;
            MessageDlg(messageString, mtError, [mbOK], 0);
            Halt(0);
         end;
      end;

      Inc(read_attempt_counter);

      if (read_attempt_counter = NUM_READ_ATTEMPTS) 
      and (Length(serialPortInput) = 0) then
      begin
         messageString := 'Can''t read from serial port after trying ' +
                     IntToStr(NUM_READ_ATTEMPTS) + ' times in ' +
           FloatToStr((SLEEP_TIME * NUM_READ_ATTEMPTS) / 1000) + ' seconds';
         MessageDlg(messageString, mtError, [mbOK], 0);
         Halt(0);
      end;

      if (Length(serialPortInput) = 0) then
        Sleep(SLEEP_TIME);
   end;

   if Copy(serialPortInput, 1, 1) <> '>' then
   begin
      DebugBreak();
      MessageDlg('Invalid value read from serial port "' + 
                  serialPortInput + '"', mtError, [mbOK], 0);
      Halt(0);
   end;

    // drop the3 leading >
   serialPortInput := Copy(serialPortInput, 2, Length(serialPortInput) - 1);
   serialPortInput := TrimRight(serialPortInput);  // just in case
   Result := StrToFloat(serialPortInput);
end;  // ReadChannelValueFromSerialPort();
4

3 に答える 3

2

通常、シリアル通信には、フロー制御とともに送受信バッファが含まれます。実装が原因で、通常のフローが中断されているようです。

ポートにアクセスするコードをバックグラウンド スレッドに移行し、必要に応じてクライアント GUI への何らかの同期コールバックを用意することをお勧めします。(1 つのオプションは単純な Synchronize() 呼び出しです)

于 2011-09-21T03:21:31.437 に答える
0

数年前に同じ問題が発生したことを覚えています。マウスをクリックすると、PLCとのシリアル通信が中断されました(深刻です!)。

どのように修正したかは正確にはわかりませんが、USBマウス、不適切な接地および/またはシリアルケーブルの電子/磁気シールド、長すぎるシリアルケーブル、ねじれたUSB /シリアルケーブル、またはそのようなもの(はい、R&Dの作業現場では少し面倒でした...)

それで、多分あなたはいくつかのハードウェアを変更したりチェックしたりすることを試みることができますか?

于 2011-09-21T06:06:36.310 に答える