我在做一个串口通讯的程序,发现读串口的时候特慢,有些时候居然卡在读串口函数那里,程序不往下走了,请教一下到底是怎么回事:function ReadCommFunction(ReadBuf: Pointer; Length: Cardinal): integer;
var
  iLength: Cardinal;
begin
  if (hCommHandle = INVALID_HANDLE_VALUE) then begin
    Result := -1;
    Exit;
  end;  if not ReadFile(hCommHandle, Buffer, Length, iLength, @OverOper) then begin
    if CheckOverlappedResult() < 0 then begin
      Result := -2;
      Exit;
    end;
  end;  if (Length <> iLength) then begin
     Result := -3;
     Exit;
  end;  Move(Buffer, ReadBuf^, iLength);
  Result := 0;
end;这是读串口函数,我发现是卡在ReadFile上面,请问一下这是怎么回事?

解决方案 »

  1.   

    改成线程模式吧,这样读取要是COM口上长时间无数据到达,可定会卡在ReadFile函数里的,这是Windows消息机制问题!
      

  2.   

    mscomm
    在ONCOMM事件里处理就可以了
      

  3.   

    ReadFile(hCommHandle, Buffer, Length, iLength, @OverOper) 你这个为串口异步读取
    注意第3个参数iLength的取值,这个值是接收到多少个数据的时候才返回,一般来说最好这个值等于串口中已接收的字节数, 该字节数可以用clearcomerror函数得到.
    另外申请串口的时候有一个SetCommTimeOut函数设置, 可设置接收到每两个字符间隔多少时间以外就返回.尽量设小.你要直接用API操作串口,最好设置一个缓冲多次ReadFile读取串口数据,然后得到完整的一帧后再做处理.因为直接操作则一次ReadFile通常不能拿完一帧(字符间隔设小),而SetCommTimeOut中字符间隔参数设置过大则不容易退出ReadFile.
      

  4.   

    procedure TForm1.tmReceiveTimer(Sender: TObject);
    var
      Temp : String;
      inbuff : array[0..2047] of Char;
      nBytesRead, dwError : DWORD;
      cs : TCOMSTAT;
    begin
      ClearCommError(hComm, dwError, @cs);
      //若未接收到数据或者接收的数据大于缓冲区大小责推出
      if cs.cbInQue = 0 then Exit;
      if cs.cbInQue > sizeof(inbuff) then
        begin
          PurgeComm(hComm, PURGE_RXCLEAR);
          Exit;
        end;  ReadFile(hComm, inbuff, cs.cbInQue, nBytesRead, nil);
      Temp := Copy(inbuff, 1, cs.cbInQue);
      mReceive.Text := mReceive.Text + Temp;
      //将memo组件的显示位置移到最下端
      mReceive.SetFocus;
      mReceive.SelStart := Length(mReceive.Text);
      mReceive.SelLength := 0;end;
    ClearCommError(hComm, dwError, @cs);
    读的时候先调用ClearCommError获取输入缓冲区字符数,没收到数据就不要读了。或者写个线程专门读写数据
      

  5.   

    我的程序要求抄数据是一个月或二个月才一次,而且是根据listview里面显示的用户信息一个个轮循下发:
    1、先开串口
    2、下发报文
    3、Sleep(2000);
    4、读数据,判是否是需要的数据,不是就再下发请求报文(这个是规约规定发三次)
    5、不管正确与否都在界面的listview显示相关数据和通讯情况
    6、轮循完关闭串口我现在不会在ReadFile那里卡住了,但是发现偶而有几次会没收到报文,我想很可能是我的程序有问题,我也考虑过用线程,但是线程感觉跟我的流程好象合不在一起,当然这是我对串口通讯不熟悉也有关系,所以我还是想看看有什么好的办法,可以让我能正确的每次都收到报文.
      

  6.   

    根据我手头上的数据,如果你打开关闭串口不用多线程来处理,会有一定的延时.
    打开串口用时30ms,关闭串口500ms.这个在执行的时候会卡那么一下才会返回.
    另外你调试的时候用串口助手监控过没,先确定是没有数据上传还是上传了不接收.
    从下发完成到接收完数据是需要一定时间的,视乎你设备的执行方式.
    如果下发接收到就马上准备上传的话,下发完成到有数据接收是2ms左右,下发完成到数据接收完成一般在10ms内.整个过程+处理大概在15ms(119200波特率50个字符).
    所以我建议你用多次读取串口的方式完成一条数据的读取.如果上传数据没问题,请检测你的接收缓冲区是否每次都能将接收到的数据存入.