Задержка в последовательной связи с использованием FTDI и ReadFile - PullRequest
0 голосов
/ 17 сентября 2018

Я заметил странную задержку при общении с устройством FTDI через Virtual Comm Port в C / C ++ (Visual Studio).

Я посылаю команду (11 символов) на устройство, которое возвращает строку(18 символов) и занимает около 5 мс (отправить + получить).Связь осуществляется со скоростью 57600 бод.

После некоторого тестирования я обнаружил, что выполнение этого кода на моем компьютере дает хорошее время (5 мс), в то время как выполнение на других компьютерах занимает от 15 до 20 мс.Любопытно, что этот эффект не появляется при использовании System.IO.Ports через C # для связи с FTDI (я всегда получаю время выполнения 5 мс, независимо от того, какой ПК это выполняет).Время в этом конкретном приложении является критическим, поэтому удаление этих дополнительных мс очень важно.

Задержка буфера порта была вручную установлена ​​на 1 мс (диспетчер устройств).

Я полагаю, это должнобыть связан с тем, как я открываю порт, но я протестировал много решений, и ничего не работает.

Вот код, который я использую для открытия порта:

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
}

ПРИМЕЧАНИЕ!-> это упрощенная версия кода, поэтому возможны ошибки.

Кто-нибудь испытывал подобное раньше?Любая помощь будет высоко оценена.

...