我用了delphi的spcomm控件进行串口循环发送和接收,可问题就在于:我再次按窗体的按钮时,按钮的反应非常慢,请问如何解决这个问题...
按钮是Button,bitbtn
急,等待各位大虾的问题...

解决方案 »

  1.   

    spcomm(V2.5)的代码里,有导致死循环部分。就是读写串口时,比如写n个字节,第一次异步操作完成,会检查写入的字节数,如果写入的字节数少于n字节,会继续写剩余的字节,直到写入的数据总和等于n字节。问题在于,若串口发生错误,永远不可能写入n字节,怎么办?其二,spcomm的读还是写线程,优先级设得比较高(tpHigher),会导致界面响应迟缓。现在的SPCOMM如何,我不知道,我说的是2.5版本的。
      

  2.   

    反映慢是消息阻塞的原因,试试换个控件试下,cport3.1
      

  3.   

    procedure Outputgoon();
    var
      StrData:string;
    begin
         StrData:='a';
         StrtoASCII_and_Send(StrData);
         sleep(500);
             StrData:='b';
             StrtoASCII_and_Send(StrData);
             sleep(500);
         StrData:='c';
         StrtoASCII_and_Send(StrData);
         sleep(500);
    end;procedure StrtoASCII_and_Send(var x:string);
    begin
       StrtoASCII(x);
       senddata(x);
    end;procedure StrtoASCII(var x:string);
    var
      i,Len:byte;
    begin
      Len:=length(x)+2;
      setlength(sbuf,Len);
      for i:=0 to len-3 do
        begin
          sbuf[i]:=ord(x[i+1]);
        end;
      sbuf[i]:=$0D;
      i:=i+1;
      sbuf[i]:=$0A;
    end;procedure senddata(var x:string);
    var
    i:integer;
    commflg:boolean;
    begin
      viewstring:='';
      commflg:=true;
      for i:=0 to length(x)+1 do
        begin
          if not Form1.comm1.writecommdata(@sbuf[i],1) then
            begin
               commflg:=false;
               break;
            end;
          viewstring:=viewstring+ inttohex(sbuf[i],2)+' ';
        end;
      viewstring:='发送'+ viewstring;  Form1.memo1.lines.add(viewstring);  Form1.memo1.lines.add('');  if not commflg then messagedlg('发送失败 !' ,mterror,[mbyes],0);end;
      

  4.   

    procedure Outputgoon(); 
    var 
      StrData:string; 
    begin 
        StrData:='a'; 
        StrtoASCII_and_Send(StrData); 
        sleep(500); 
            StrData:='b'; 
            StrtoASCII_and_Send(StrData); 
            sleep(500); 
        StrData:='c'; 
        StrtoASCII_and_Send(StrData); 
        sleep(500);
    end; StrData:='a';StrData:='b';StrData:='c';发送给下位机后,下位机会发回上位机数据;
    procedure Outputgoon();这个函数在我收到下位机数据后,再次发送;我循环就是用这个函数
     
      

  5.   

    主程序那么大量地Sleep,难怪反应慢!
      

  6.   

    to sy_100000
    我想发送一次停500ms,所以要用到这么多sleep
      

  7.   

    嘿嘿,兄弟,把这一堆移到一个独立的线程就好了
    还有不要用什么控件,直接用api就好了
      

  8.   


    Sleep不好在主线程里用的!
      

  9.   

    to qizhi_t
    这一堆指我上面所有代码吗?这些代码是spcomm的写线程,不就是一个线程了吗?
    关于改用api,我会试下..
      

  10.   

    to qizhi_t
    谢谢你的回复,有点不明白,我的发送已经是写线程了,你指的自己写线程是指什么,能不能给点指导性代码
      

  11.   

    一:不能用sleep,DELPHI里的sleep是让整个应用程序暂停(停止)运行,自己写个延时函数;
    二:循环的话最好不要用字符串类型,很耗CPU资源的,建议放在LIST流里,然后一次显示出来
      

  12.   

    to weipiy
    一,程序改为自己写的延时函数后,按键无法响应问题解决.但是,但循环通信时,出现窗体无法关闭.
    二,你所说的不要用字符串是什么意思,我没用字符串发送.
    谢谢回复
      

  13.   

    Outputgoon(); 
    该函数放到单独的线程中去发送,按钮中事件只要thread.resume即可。
    你在主界面线程中sleep肯定要慢的
      

  14.   

    谢谢大家
    我把Outputgoon();放在单独线程中去了,现在按键有反应,但就是窗口在循环通信时不能关闭?这是为什么
      

  15.   

    循环等待时采用类似这种方式延时
              while not MeterNextFlag do   //等待本帧通讯结束
                Application.ProcessMessages;
              sleep(200);
      

  16.   

    to kampan
    用你的循环等待,窗口在循环通信时不能关闭的问题还不能解决
      

  17.   

    再次感谢大家的回贴
    现在还有一个问题,就是当串口(用spcomm控件)循环通信时,关闭窗体的时候不能立即反应,得等5~10秒才能关闭.有人说把循环通信部分用线程循环,我试了一下还是一样.请问具体应该解决这个问题,最好给出详细代码,或者代码框架也行,多谢了...再次期待你的回复:)
      

  18.   

    上面写少了几个字,如下:再次感谢大家的回贴 
    现在还有一个问题,就是当串口(用spcomm控件)循环通信时,关闭窗体的时候不能立即反应,得等5~10秒才能关闭.有人说把循环通信部分用线程循环,我试了一下还是不行. 请问具体应该怎样解决这个问题,最好给出详细代码,或者代码框架也行,多谢了... 
    再次期待你的回复:)
      

  19.   

    一:不能用sleep,DELPHI里的sleep是让整个应用程序暂停(停止)运行,自己写个延时函数;
    可以用TIMER控件来代替SLEEP。
      

  20.   


        FTComm:=TComm.Create(nil);
        FTComm.CommName  := '\\.\'+sComName;  //解决超过十的串口问题
        FTComm.BaudRate  := 4800;
        FTComm.Inx_XonXoffFlow  := False;
        FTComm.Outx_XonXoffFlow := False;
        FTComm.ReadIntervalTimeout := 220;
        FTComm.StartComm;    tmr_Send := TTimer.Create(nil);
        tmr_Send.Enabled := False;
        tmr_Send.OnTimer := OnTimerS;
        tmr_SendNext := TTimer.Create(nil);
        tmr_SendNext.Enabled := False;
        tmr_SendNext.Interval := 550;
        tmr_SendNext.OnTimer := IncSingSend;我这里用了好几个TTimer来解决定时发送的问题。
      

  21.   

        procedure SingSend;virtual; abstract;      //对单一送查询指令
        procedure ComSendMSG();virtual; abstract;  //通过串口发送指令给探测器
        procedure IncSingSend(Sender: TObject);virtual; abstract;  //通过串口发送指令给探测器
        procedure ComRevMSG(Sender: TObject; Buffer: Pointer;
                  BufferLength: Word);virtual;abstract;
      public
                           
        FTClientDataSet: TClientDataSet;           //用于在内在中存储各个探测器的值和状态    FTComm: TComm;                             //spcomm 串口类成
        property FiSleep: Integer read iSleep write SetiSleep;
        property FsComplete:string read sComplete write SetCompT;
        property sBatchNO:string read FBatchNO write SetBatchNo;
        property TypeName:string read FTypeName write SetTypeName;
         constructor Create(sComName:String);virtual;
        destructor Destroy; virtual;
        procedure Start(aInters:Integer);virtual;
        procedure Stop;
        procedure Suspend;
        procedure ReStart; virtual;基类中的部分代码,可以参考下
      

  22.   

    代码写在 HandleReadData里面,通过消息传递出来吧。