我正在使用来自“大牌”之一的第三方串行端口组件(是的,我已经要求他们提供支持,但是存在时区差异,我需要要很快解决这个问题)。该组件已存在多年,我没有理由相信问题在于它(与硬件相同)。用户界面活动如何破坏我的串口输入
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