代码之家  ›  专栏  ›  技术社区  ›  Carles

使用FTDI和ReadFile进行串行通信时的延迟

  •  0
  • Carles  · 技术社区  · 8 年前

    我注意到在C/C++(Visual Studio)中通过虚拟通信端口与FTDI设备通信时出现了奇怪的延迟。

    我向设备发送一个命令(11个字符),返回一个字符串(18个字符),大约需要5毫秒才能完成(发送+接收)。通信以57600波特完成。

    经过一些测试,我发现在我的电脑上执行这段代码的时间很长(5毫秒),而在其他电脑上执行这段代码需要15到20毫秒。奇怪的是,在使用系统时,这种效果并没有出现。伊奥。通过C#端口与FTDI进行通信(无论是哪台电脑执行,我的执行时间总是为5ms)。 在这个特定的应用程序中,时间是至关重要的,因此删除这些额外的ms非常重要。

    端口缓冲区的延迟已手动设置为1ms(设备管理器)。

    我认为这应该与我打开端口的方式有关,但我已经测试了许多解决方案,但都不起作用。

    以下是我用来打开端口的代码:

    hCom = CreateFile(DevPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if ( hCom==INVALID_HANDLE_VALUE) {
        CloseHandle(hCom);
        hCom = NULL;
        return false;
    } else {
        if (!SetupComm(hCom,2048,2048)) {
            CloseHandle(hCom);
            hCom = NULL;
            return false;
        }
    
        try {
    
            dcb.DCBlength = sizeof(DCB);
            GetCommState(hCom, &dcb);
    
            //No Flow control
            dcb.BaudRate = CBR_57600;
            dcb.ByteSize = 8;         // Setting ByteSize = 8
            dcb.StopBits = ONESTOPBIT;// Setting StopBits = 1
            dcb.Parity   = NOPARITY;  // Setting Parity = None
            dcb.fBinary = TRUE;
            dcb.fParity = FALSE;
            dcb.fOutxCtsFlow = FALSE;
            dcb.fOutxDsrFlow = FALSE;
            dcb.fDtrControl = DTR_CONTROL_DISABLE;
            dcb.fDsrSensitivity = FALSE;
            dcb.fRtsControl = RTS_CONTROL_DISABLE;
            dcb.fTXContinueOnXoff = FALSE;
            dcb.fOutX = FALSE;
            dcb.fInX = FALSE;
    
            if(!SetCommState(hCom, &dcb)) {
                CloseHandle(hCom);
                hCom  = NULL;
                return false;
            }
        } catch (std::string strCatchErr) {
            CloseHandle(hCom);
            hCom = NULL;
            return false;
        }
    
        CommTimeouts.ReadIntervalTimeout = MAXDWORD;
        CommTimeouts.ReadTotalTimeoutConstant = 0;
        CommTimeouts.ReadTotalTimeoutMultiplier = 0;
        CommTimeouts.WriteTotalTimeoutConstant = 40;
        CommTimeouts.WriteTotalTimeoutMultiplier = 0;
    
        if(!SetCommTimeouts(hCom, &CommTimeouts)) {
            CloseHandle(hCom);
            hCom = NULL;
            return false;
        }
    
        //purge port buffers
        PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
    
        return true;
    

    读取和写入端口的过程使用普通的ReadFile和WriteFile指令完成:

    DWORD BytesRead = 0;
    DWORD TotalBytesRead = 0;
    DWORD BytesToRead = 20;
    DWORD bytesWritten = 0;
    BOOL bSuccess;
    char rxbuffer[1024];
    char * InBuffer;
    int fRun = 1;
    
    //Send data
    PurgeComm(hCom, PURGE_RXCLEAR | PURGE_RXABORT);
    WriteFile(hCom, "TESTCMD001\n", (DWORD)11, &bytesWritten, NULL);
    
    //receive data
    InBuffer = &rxbuffer[0];
    
    while(fRun) {
        BytesRead = 0;
        bSuccess = ReadFile(hCom, InBuffer, BytesToRead, &BytesRead, NULL);
        if ( bSuccess==TRUE ) {
            if (BytesRead>0) {
                TotalBytesRead += BytesRead;
                rxbuffer[TotalBytesRead] = '\0';
                InBuffer = &rxbuffer[TotalBytesRead];
                if ( strchr(rxbuffer, '\n')!=NULL ) fRun = 0;
            } //IF_BytesRead>0
        } //IF_ReadFile
    }
    

    注意->这是代码的简化版本,因此可能会有错误。

    以前有人经历过这样的事情吗? 任何帮助都将不胜感激。

    0 回复  |  直到 8 年前