我正在使用來自「大牌」之一的第三方串行端口組件(是的,我已經要求他們提供支持,但是存在時區差異,我需要要很快解決這個問題)。該組件已存在多年,我沒有理由相信問題在於它(與硬件相同)。用戶界面活動如何破壞我的串口輸入
h/w規範說如果我向seial端口寫入一個特定的字符串,以回車符結束,然後讀取,它將以特殊格式化的8個字符的字符串進行回覆,再次以回車結束。
代碼可以正常運行幾個小時,並根據它讀取的內容更新GUI。
但是,當在GUI上有任何用戶活動時,我從串口讀取垃圾。
我第一次注意到它時,點擊一個按鈕,導致模態窗體打開,然後關閉窗體。
但是,當我簡單地拖動TStringGrid的scollbar時,我也會看到它。
這是代碼。有什麼建議?
更新:組件是線程化的,供應商同意這裏的海報 - 串行端口是異步設備。我更改了代碼以編寫數據請求並處理組件的OnCharReceived()事件處理程序中的每個接受字符。塔恩斯克所有的幫助。
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();
當serialPortInput <>''做'時,有沒有什麼理由使用效率較低的'while Length(serialPortInput)= 0 do'而不是''? –
不,沒有: - /(+1) – Mawg