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