Как пользовательский интерфейс повреждает мой последовательный порт

Я использую сторонний компонент последовательного порта от одного из "громких имен" (да, я попросил их о поддержке, но есть разница во времени и мне нужно исправить это очень быстро). Компонент существует уже много лет, и у меня нет оснований полагать, что проблема кроется в нем (то же самое относится к программному обеспечению).

Спецификация h / w говорит, что если я напишу определенную строку в последовательный порт, завершенную возвратом каретки, а затем прочтю, он ответит 8-символьной строкой, отформатированной в специальном формате, снова завершенной возвратом каретки.

Код может работать часами, делая это правильно и обновляя графический интерфейс в зависимости от того, что он читает.

Тем не менее, когда есть какая-либо активность пользователя в графическом интерфейсе, я читаю мусор с последовательного порта.

Я впервые заметил это при нажатии кнопки, которая вызывала открытие модальной формы, а затем закрытие формы.

Тем не менее, я также вижу это, просто перетаскивая полосу прокрутки TStringGrid.

Вот код Любой совет?


Обновление: компонент имеет резьбу, и поставщики согласны с его постерами - последовательный порт является асинхронным устройством. Я изменил код, чтобы написать запрос данных и обработать каждый полученный символ в обработчике события 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();

3 ответа

Решение

Трудно сказать, не зная, какой компонент вы на самом деле используете, или что он делает внутри. Но пользовательская активность проходит через основную очередь сообщений, и ваш код вручную перекачивает очередь для новых сообщений, что, вероятно, связано с вашей проблемой. Вы разрешаете обрабатывать действия пользователя между вашими записями и чтениями. Вы пытались переместить логику последовательного порта в отдельный рабочий поток?

Последовательная связь обычно включает в себя буферы отправки / получения наряду с управлением потоком. Нормальный поток, по-видимому, прерывается из-за вашей реализации.

Я предлагаю вам перенести код доступа к порту в фоновый поток и при необходимости использовать синхронизированный обратный вызов для клиентского графического интерфейса. (одним из вариантов является простой вызов Synchronize())

Он вспоминает, что у меня была такая же проблема несколько лет назад: щелчок мышью прервал последовательную связь с ПЛК (серьезно!).

Не знаю точно, как мы это исправили, но я думаю, что это было связано с сочетанием USB-мыши, неправильного заземления и / или электронного / магнитного экранирования последовательного кабеля, слишком длинного последовательного кабеля, скрученного USB/ последовательного кабеля или что-то вроде этого (да, это было немного грязно на рабочем месте R&D...)

Так что, может быть, вы можете попробовать изменить и / или проверить некоторые аппаратные средства?

Другие вопросы по тегам