在循环中发送更多数据之前,如何等待COM端口接收事件 [英] How to wait for COM port receive event before sending more data in a loop

查看:173
本文介绍了在循环中发送更多数据之前,如何等待COM端口接收事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用旧的索尼爱立信手机编写和阅读AT命令的小组件。
发送和写入电话是没有问题的,但是我希望能够暂停我的SendATCmd功能,并等待COM端口组件通知我通知事件,然后恢复SendATCmd功能再次。



情景:我想在手机中获取短信的数量。
通常我只是告诉电话:嘿,你有多少短信?
,手机将在通知事件中回复。
这很好。



但是我真正想做的就是像

 如果SendATCmd('CountSMS')> 0然后
为0到SMSCount do
AddSMSToList;

SendATCmd的代码如下所示:

  function TSE_Z1010.SendATCmd(Cmd:string):TATResult; 
begin
fCOMPort.PutString(Cmd); //发送AT命令

//这里是我要暂停此函数的地方
//等待fCOMPort在数据可用时通知我
//然后再次恢复此功能。

result:= fTMPATResult;

end;

我尝试过使用while循环,暂停等等,但没有任何功能,除了一个事情是这样的,当我把一个ShowMessage放在哪里应该是暂停。
我不知道ShowMessage如何在内部工作,但似乎它不会像while循环和暂停那样停止程序。



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



修正它。



我所要做的就是在uses子句中添加Forms,然后在fTMPATResult.Full = false时添加Application.ProcessMessages;在我想要暂停过程的部分。



fTMPATResult是传入COM端口数据在组件中全局存储的变量。

解决方案

AsyncPro确实有一些解决方案(ontriggerdata),它们是基于事件的,使代码难以阅读/理解。

这里是AsyncPro的SendAndWaitForResponse(如Remy建议):

  TForm1 = class TForm)
...
private
IOEvent:THandle; //用于IO事件
IORx:string;
Comport:TapdComport;
...


程序TForm1.ComportTriggerAvail(CP:TObject; Count:Word);

var i:integer;

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

函数TForm1.SerialSAWR(tx:string; TimeOut:integer):boolean;
begin
结果:= False;
try
IORx:=''; // your global var
ResetEvent(IOEvent);
Comport.PutString(tx);
结果:= WaitForSingleObject(IOEvent,TimeOut)= WAIT_OBJECT_0;
除了
在E:异常do
// dosomething与异常
结束;
结束

//构造函数部分
IOEvent:= CreateEvent(nil,True,False,nil);
//析构函数部分
如果IOEvent<> 0然后
CloseHandle(IOEvent);

最佳解决方案是使用comport创建一个线程,以便您的GUI不会被阻止。
我有几个应用程序在生产中使用Asyncpro这种方式,它的作用就像一个魅力...


I'm working on a small component for writing and reading AT Commands using an old Sony Ericsson phone. Sending and writing to/from the phone is no problem at all, however I would like to be able to pause my SendATCmd function and wait for the COM Port component to notify me with a Notification Event, and then resume the SendATCmd function again.

Scenario: I want to get the count of SMS messages in the phone. Normally I'd just tell the phone: Hey, how many SMS messages do you have? and the phone would reply in the notification event. Thats all good.

But what I really want to do is something like

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

The code for SendATCmd looks like this:

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;

I've tried using a while-loop, pause, etc etc, but nothing's worked except for one thing, and that's when I put a ShowMessage where the pause should be. I don't know how ShowMessage works internally but it seems that it doesn't halt the program like while-loop and pause do.

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

Fixed it.

All I had to do was to add Forms in the uses clause, and then I added while fTMPATResult.Full=false do Application.ProcessMessages; in the part where I wanted to pause the procedure.

"fTMPATResult" is the variable where the incoming COM Port data is stored, globally within the component.

解决方案

While AsyncPro does have some solutions for this (ontriggerdata), they are event based and make code difficult to read/understand.

here is SendAndWaitForResponse with AsyncPro (like Remy suggested):

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);

Best solution is to create a thread with the comport so your GUI won't be blocked. I have several applications in production with Asyncpro this way and it works like a charm...

这篇关于在循环中发送更多数据之前,如何等待COM端口接收事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆