Как ждать события получения COM-порта перед отправкой большего количества данных в цикле - PullRequest
1 голос
/ 29 января 2012

Я работаю над небольшим компонентом для записи и чтения AT-команд с использованием старого телефона Sony Ericsson. Отправка и запись в / из телефона не представляет никаких проблем, однако я хотел бы иметь возможность приостановить свою функцию SendATCmd и подождать, пока компонент COM-порта не уведомит меня о событии уведомления, а затем снова возобновить функцию SendATCmd.

Сценарий: я хочу получить количество SMS-сообщений в телефоне. Обычно я просто скажу телефону: эй, сколько у тебя SMS-сообщений? и телефон ответит в уведомлении. Это все хорошо.

Но я действительно хочу сделать что-то вроде

if SendATCmd('CountSMS')>0 then
  for 0 to SMSCount do
    AddSMSToList;

Код для SendATCmd выглядит следующим образом:

function TSE_Z1010.SendATCmd(Cmd: string): TATResult;
begin
  fCOMPort.PutString(Cmd); //Sending AT command

  //Here is where I would like to pause this function
  //wait for the fCOMPort to notify me when data is available
  //and then resume this function again.

  result:=fTMPATResult;

end;

Я пытался использовать цикл while, паузу и т. Д. И т. Д., Но ничего не сработало, кроме одной вещи, и именно тогда я поставил ShowMessage там, где должна быть пауза. Я не знаю, как ShowMessage работает внутри, но кажется, что он не останавливает программу, как цикл while и pause do.

====================

Исправлено.

Все, что мне нужно было сделать, это добавить формы в предложении использования, а затем я добавил, пока fTMPATResult.Full = false do Application.ProcessMessages; в той части, где я хотел приостановить процедуру.

«fTMPATResult» - это переменная, в которой хранятся входящие данные COM-порта, глобально внутри компонента.

Ответы [ 2 ]

1 голос
/ 30 января 2012

Хотя у AsyncPro есть некоторые решения для этого (ontriggerdata), они основаны на событиях и затрудняют чтение / понимание кода.

вот SendAndWaitForResponse с AsyncPro (как предложил Реми):

TForm1 = class(TForm)
 ...
private
    IOEvent           : THandle; // used for IO events
    IORx              : string;
    Comport           : TapdComport;
...


procedure TForm1.ComportTriggerAvail(CP: TObject; Count: Word);

var i       : integer;

begin
 for i:=1 to Count do
  IORx:=IORx+Comport.GetChar;
 SetEvent(IOEvent);
end;

function TForm1.SerialSAWR(tx : string; TimeOut : integer) : boolean;
begin
 Result := False;
 try
  IORx := ''; // your global var
  ResetEvent(IOEvent);
  Comport.PutString(tx);
  Result := WaitForSingleObject(IOEvent, TimeOut) = WAIT_OBJECT_0;
 except
  on E : Exception do
   // dosomething with exception
 end;
end;

// constructor part
IOEvent := CreateEvent(nil, True, False, nil);
// destructor part
 if IOEvent <> 0 then
  CloseHandle(IOEvent);

Лучшее решение - создать поток с компортом, чтобы ваш графический интерфейс не был заблокирован. У меня есть несколько приложений, работающих с Asyncpro таким образом, и это работает как шарм ...

0 голосов
/ 30 января 2012

В любое время, когда вам нужно позвонить Application.ProcessMessages() вручную, вам нужно переосмыслить свой дизайн кода.Вдвойне, когда он вызывается в цикле.

Я не знаю, как работает Asynch Pro, но в Win32 API есть функция WaitCommEvent(), которая выполняет то, что вы просите.Вы вызываете эту функцию, чтобы запросить у последовательного порта уведомление о желаемом событии (событиях), а затем вы можете использовать WaitForOverlappedResult() или WaitForSingleObject() для ожидания фактического возникновения этих событий, в зависимости от того, работает ли последовательный порт в режиме перекрытиярежим или нет.Обработка сообщений не требуется.Я был бы удивлен, если Asynch Pro так или иначе не раскрывает эту функциональность.

...