Чтение из последовательного порта ошибочно без ввода пользователя - PullRequest
2 голосов
/ 16 марта 2011

Использование Delphi 7 Я читаю с последовательного порта.

Перед чтением всегда предшествует запись, при которой ч / б начинает измерять с датчика и записывает что-то, что я могу прочитать (и всегда есть что прочитать).

У меня естьдве возможности: вручную ввести команду и щелкнуть кнопку, чтобы записать ее в последовательный порт (чтение модели или ч / б версию и т. д.), или щелкнуть кнопку для циклического считывания результатов измерений, пока не будет нажата кнопка остановки.Они оба используют одни и те же внутренние функции, поэтому код выглядит примерно так:

WriteSerial('?model');
SerialData := ReadSerial();  // returns string
WriteSerial('?fw');
SerialData := ReadSerial();

и

while stopButtonNotPressed do
begin
  WriteSerial('?data');
  SerialData := ReadSerial();
  Memo1.Lines.Add(SerialData );
end;

Первый вариант (ввод команды вручную и нажатие кнопки) всегдауспешно, независимо от того, как быстро или медленно я ввожу команды (удерживайте кнопку для повтора), куда идет второй

pass
fail
pass
pass
fail
pass
pass
fail
... add infinitum

добавление вызовов в режим сна ничего не дает, но при попытке отладки я обнаружил, что если ядобавьте модальное диалоговое окно MsgDialog, 'Please close this dialog...', mtInfo, [mrOK]); в цикл, после чего он больше не завершится с ошибкой.

Теперь он не выглядит как хронометраж (иначе, конечно, добавление Sleep(2000); к циклусделать это и не делать, так почему нажатие кнопки на главной форме или в модальном диалоге приводит к успеху?

Кстати, ч / б руководство пользователя ничего не говорит о CTS / RTS и единственномПример кода предоставить также не дает.

Примечание: если я несколько раз вручную введу ?data, это никогда не завершится неудачей ...

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 16 марта 2011

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

Как вы говорите, Sleep(2000) должно обеспечить множество "перерывов", но есть две другие потенциальные проблемы, о которых вам нужно позаботиться:

  • Последовательная связь не обязательна: Буфер (2000) может быть слишком длинным!
  • Используемая вами последовательная библиотека может использовать сообщения Windows для обработки входящих байтов. Sleep() запрещает рассылку сообщений, поэтому сообщения больше не передаются в ваше приложение

Попробуйте "спать", используя что-то вроде этого:

procedure BusyWait(ms: Cardinal);
var StopAt: TDateTime;
begin
  StopAt := Now + EncodeTime(0, 0, ms div 1000, ms mod 1000);
  while StopAt > Now do
  begin
   Application.ProcessMessages;
   Sleep(50); // per Michał Niklas's suggestion, to keep the CPU from reaching 100%
  end;
end;

Эта процедура будет ждать, но она будет поддерживать работу сервера сообщений, позволяя вашей последовательной библиотеке получать сообщения. Если это проблема ...

1 голос
/ 16 марта 2011

Возможно добавление Application.ProcessMessages() до того, как Sleep() поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...