用SPComm单元中的TCOmm类通过串口发送数据,点一下发送一条时接收方可以正确接收,如果点的速度过快则接收方出错.用了一个定时器1秒发一条也是正常的,但不能更快了.请问这是什么原因,如何避免这个错误.

解决方案 »

  1.   

    我在开发手机管理程序时也说遇到过类似的问题,最后我只用WIN API解决了这个问题:下面给出单元文件,有关与手机通讯的源代码请在http://tansuo.51.net上下载unit ComPort;interface
    uses Windows,SysUtils;type
      ECommsError = class( Exception );var
      iComNum      : integer = 2; // 
      iOldComOpen  : integer = 0;
      iComBaud     : integer = 115200; // 
      iOldComBaud  : integer = 0;
      hCom         : THandle=INVALID_HANDLE_VALUE;
      ComTimeouts  : TCommTimeouts;
      txLen, rxLen : Dword;
      FlgOvrlp     : boolean = True;
      COMwr : OVERLAPPED;
      COMrd : OVERLAPPED;
      COMst : COMSTAT;
      DCB          : TDCB;
    { DCB结构 :
    0      DWORD fBinary: 1;          // binary mode, no EOF check
    1      DWORD fParity: 1;          // enable parity checking
    2      DWORD fOutxCtsFlow:1;      // CTS output flow control
    3      DWORD fOutxDsrFlow:1;      // DSR output flow control
    4..5   DWORD fDtrControl:2;       // DTR flow control type
    6      DWORD fDsrSensitivity:1;   // DSR sensitivity
    7      DWORD fTXContinueOnXoff:1; // XOFF continues Tx
    8      DWORD fOutX: 1;        // XON/XOFF out flow control
    9      DWORD fInX: 1;         // XON/XOFF in flow control
    10     DWORD fErrorChar: 1;   // enable error replacement
    11     DWORD fNull: 1;        // enable null stripping
    12..13 DWORD fRtsControl:2;   // RTS flow control
    14     DWORD fAbortOnError:1; // abort reads/writes on error
    15..31 DWORD fDummy2:17;      // reserved}function OpenCom(Mode:boolean) : boolean;
    procedure CloseCom;
    function GetComDCB : boolean;
    function SetComDCB : boolean;
    function GetComTimeouts : boolean;
    function SetComTimeouts : boolean;
    function SetComRxTimeouts(NewIntervalTimeout,NewTimeoutMultiplier,NewTimeoutConstant:dword) : boolean;
    function ReadCom(Buf:Pointer; BufLen:Dword) : boolean;
    function WriteCom(Buf:Pointer; BufLen:Dword) : boolean;
    function EscapeComFunction(dwFunc:Dword) : boolean;
    function GetComModemStatus : DWORD;
    function GetComStat : boolean;
    function PurgeCom(mode:Dword): boolean; // 清空读写缓冲区中的数据
    function WriteComStr(S: String): boolean;
    function ChangeComSpeed(Baud:integer) : boolean;implementationfunction OpenCom(Mode:boolean) : boolean;
    var
      dw : dword;
    begin
      result:=FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        CloseCom;  if FlgOvrlp then  // 同步、异步通讯模式
        dw:=FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED
      else
        dw:= 0;  // 同步  hCom:=CreateFile(PChar('\\.\COM'+IntToStr(iComNum)),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,dw,0);
      if hCom = INVALID_HANDLE_VALUE then
        raise ECommsError.Create( '串口打开失败.' )
      else
      begin
        if GetFileType( hCom ) <> FILE_TYPE_CHAR then
        begin
          CloseHandle( hCom );
          raise ECommsError.Create( '文件句柄不是通信句柄. ' )
        end;    if not SetupComm( hCom, 8192, 8192 ) then  // Rd , Wr
        begin
          CloseHandle( hCom );
          raise ECommsError.Create( '串口缓冲设置失败.' )
        end;    if GetComDCB then
        begin
          if Mode then
            DCB.Flags := (DCB.Flags and $ffff8000) or $0001
          else
            DCB.Flags := (DCB.Flags and $ffff8000) or $0011;   //$1011;      DCB.ByteSize := 8;
          DCB.Parity := 0;
          DCB.StopBits := 0;
          DCB.BaudRate := iComBaud;
          if SetComDCB then
          begin
            ComTimeouts.ReadIntervalTimeout:=20; //0
            ComTimeouts.ReadTotalTimeoutMultiplier:=1; //0
            ComTimeouts.ReadTotalTimeoutConstant:=2000; //200
            ComTimeouts.WriteTotalTimeoutMultiplier:=1;//MAXDWORD;
            ComTimeouts.WriteTotalTimeoutConstant:=2000;//MAXDWORD;
            if SetComTimeouts then
            begin
              iOldComOpen:=iComNum;
              iOldComBaud:=iComBaud;
              if Mode then
              begin
                sleep(75);
                EscapeComFunction(SETRTS); // 发送RTS信号
                sleep(25);
                EscapeComFunction(SETDTR); // 发送DTR信号
              end
              else
              begin
                sleep(75);
                EscapeComFunction(SETRTS); // 发送RTS信号
              end;
              result := TRUE;
            end;
          end;
        end;
      end;
    end;procedure CloseCom;
    var
      x: THandle;
    begin
      if hCom<>INVALID_HANDLE_VALUE then
      begin
        x:=hCom;
        hCom:=INVALID_HANDLE_VALUE;
        CloseHandle(x);
      end;
      iOldComOpen:=0;
    end;function GetComDCB : boolean;
    begin
      result := FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        result := GetCommState(hCom,DCB);
    end;
      

  2.   

    function SetComDCB : boolean;
    begin
      result:=FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        result := SetCommState(hCom,DCB);
    end;function ChangeComSpeed(Baud:integer) : boolean;
    var
      save_baud : integer;
    begin
      result:=FALSE;
      save_baud:=dcb.BaudRate;
      if hCom<>INVALID_HANDLE_VALUE then
      begin
        if GetComDCB then
        begin
          if dcb.BaudRate<>Dword(Baud) then
          begin
            dcb.BaudRate:=Baud;
            result := SetCommState(hCom,DCB);
            EscapeComFunction(SETRTS);
            EscapeComFunction(SETDTR);
            if not result then
            begin
              dcb.BaudRate:=save_baud;
              SetCommState(hCom,DCB);
              EscapeComFunction(SETRTS);
              EscapeComFunction(SETDTR);
            end;
          end;
        end;
      end;
    end;function GetComTimeouts : boolean;
    begin
      result:=FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        result := GetCommTimeouts(hCom,ComTimeouts);
    end;function SetComTimeouts : boolean;
    begin
      result:=FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        if SetCommTimeouts(hCom,ComTimeouts) then result:=TRUE;
    end;function SetComRxTimeouts(NewIntervalTimeout,NewTimeoutMultiplier,NewTimeoutConstant:dword) : boolean;
    begin
      result:=FALSE;
      if (ComTimeouts.ReadIntervalTimeout<>NewIntervalTimeout)
          or (ComTimeouts.ReadTotalTimeoutMultiplier<>NewTimeoutMultiplier)
          or (ComTimeouts.ReadTotalTimeoutConstant<>NewTimeoutConstant)
      then
      begin
        ComTimeouts.ReadIntervalTimeout:=NewIntervalTimeout;
        ComTimeouts.ReadTotalTimeoutMultiplier:=NewTimeoutMultiplier;
        ComTimeouts.ReadTotalTimeoutConstant:=NewTimeoutConstant;
        if hCom<>INVALID_HANDLE_VALUE then
          if SetCommTimeouts(hCom,ComTimeouts) then
            result:=TRUE;
      end
      else
        result:=TRUE;
    end;function  GetComStat : boolean;
    var
      dErr : DWORD;
    begin
      result:=FALSE;
      dErr := 0;
      if hCom<>INVALID_HANDLE_VALUE then
      begin
        GetCommState( hCom, dcb );
        if ClearCommError(hCom,dErr,@COMst) then
        begin
          // size Rx buff := COMst.cbInQue;
          Result := True;
        end;
      end;
    end;function ReadCom(Buf:Pointer; BufLen :Dword) : boolean;
    var
     dErr: Dword;
    begin
     result := False;
     if (hCom<>INVALID_HANDLE_VALUE)and(Buf<>Nil)and(BufLen<>0) then begin
      rxlen:=0;
      if FlgOvrlp then begin
       COMrd.hEvent:=CreateEvent(Nil,TRUE,FALSE,Nil);
       if not ReadFile(hCom,Buf^,BufLen,rxLen,@COMrd) then begin
        if not GetOverlappedResult(hCom,COMrd,rxLen,True) then begin
        end;
       end;
    //   ResetEvent(COMrd.hEvent);
       CloseHandle(COMrd.hEvent);
      end
      else begin
       if not ReadFile(hCom,Buf^,BufLen,rxLen,Nil) then begin
    //     ClearCommError(hCom,dErr,Nil);
    //     exit;
       end;
      end;
      if rxLen = BufLen then result := True
      else ClearCommError(hCom,dErr,Nil);
     end;
    end;function WriteCom(Buf:Pointer; BufLen:Dword) : boolean;
    Var
     dErr: Dword;
    begin
     result:=FALSE;
     if (hCom<>INVALID_HANDLE_VALUE)and(Buf<>Nil)and(BufLen<>0) then begin
      txLen:=0;
      if FlgOvrlp then begin
       COMwr.hEvent:=CreateEvent(Nil,TRUE,FALSE,Nil);
       if not WriteFile(hCom,Buf^,BufLen,txLen,@COMwr) then begin
        if not GetOverlappedResult(hCom,COMwr,txLen,True) then begin
        end;
    //     ClearCommError(hCom,dErr,Nil);
       end;
    //   ResetEvent(COMwr.hEvent);
       CloseHandle(COMwr.hEvent);
      end
      else begin
       if not WriteFile(hCom,Buf^,BufLen,txLen,Nil) then begin
    //     ClearCommError(hCom,dErr,Nil);
    //     exit;
       end;
      end;
      if txLen = BufLen then result:=TRUE
      else ClearCommError(hCom,dErr,Nil);
      //PurgeComm(hCom, PURGE_TXABORT + PURGE_TXCLEAR);
     end;
    end;function WriteComStr(S: String): boolean;
    begin
      Result:=WriteCom(@S[1],Length(S));
    end;function PurgeCom(mode:Dword): boolean; //function
    begin
     result := PurgeComm(hCom,mode); // 清空读写缓冲区中的数据
    end;function EscapeComFunction(dwFunc:Dword):boolean;
    begin
      result:=FALSE;
      if hCom<>INVALID_HANDLE_VALUE then
        result := EscapeCommFunction(hCom,dwFunc);
    end;
    //////////////////////////////////////////////////////////
    //  FUNCTION: GetComModemStatus
    //
    //  PURPOSE: Read the state of modem input pin right now
    //
    //  PARAMETERS:
    //     none
    //
    //  RETURN VALUE:
    //
    //     A DWORD variable containing one or more of following codes:
    //
    //     Value       Meaning
    //     ----------  -----------------------------------------------------------
    //     MS_CTS_ON   The CTS (clear-to-send) signal is on.
    //     MS_DSR_ON   The DSR (data-set-ready) signal is on.
    //     MS_RING_ON  The ring indicator signal is on.
    //     MS_RLSD_ON  The RLSD (receive-line-signal-detect) signal is on.
    //
    //     If this comm have bad handle or not yet opened, the return value is 0
    //
    //  COMMENTS:
    //
    //    This member function calls GetCommModemStatus and return its value.
    //    Before calling this member function, you must have a successful
    //    'StartOpen' call.
    //
    //
    function GetComModemStatus : DWORD;
    var
       dwModemState : DWORD;
    begin
      if hCom<>INVALID_HANDLE_VALUE then
         if not GetCommModemStatus( hCom, dwModemState ) then
            Result := 0
         else
            Result := dwModemState
    end;end.
      

  3.   

    因为是第三代语言.第一代是 机器码
    第二代是 汇编
    第三代是 C
    第四代是 Delphi胡诌,让什么老教授晕一下.
      

  4.   

    可能是还没有发送完成,你看看那个TCOmm有没有什么属性,或事件表示当前发送任务已经完成的。
      

  5.   

    先结贴了,给COM发送要求3秒一条就可以了,所以现在的程序不会有问题的.