Последовательная связь не блокирует эмулируемый порт

Приведенный ниже код работает так, как ожидается, когда связь проходит через настоящий последовательный порт. Процесс блокирует ReadFile и ожидает, что последовательный буфер будет заполнен до начала обработки.

Однако, когда я подключаю USB-устройство, которое эмулирует последовательный порт, ReadFile не будет блокироваться даже тогда, когда данные не будут проходить через буфер.

Каждую секунду с устройства, подключенного к USB, я получаю следующий вывод...

rVal = 1 ch = -52 bytesRead = 0

Таким образом, никакая ошибка не возвращается, и чтение байтов всегда равно 0, пока я не отправлю байты через порт usb.

DWORD rVal;
HANDLE handle;
BOOL isGood;
char Ch; //Temporary character used for reading
DWORD bytesRead;

handle = CreateFile(L "\\\\.\\COM4",          //port name
    GENERIC_READ | GENERIC_WRITE,                 //Read/Write
    0,                                            // No Sharing
    NULL,                                         // No Security
    OPEN_EXISTING,                                // Open existing port only
    0,                                            // Non Overlapped I/O
    NULL);                                        // Null for Comm Devices

 if (handle == INVALID_HANDLE_VALUE)
 {
     return INVALID_HANDLE_VALUE;
 }

 isGood = SetCommMask(handle, EV_RXCHAR);
 if (isGood == false)
 {
     return USV_ERR_READER_COM;
 }

 rVal = ReadFile(handle,           //Handle of the Serial port
      &ch,       //Temporary character
      sizeof(ch),//Size of TempChar
      &bytesRead,    //Number of bytes read
      NULL);
 ...
-1
06 апр. '16 в 23:29
источник поделиться
1 ответ

Проблема заключалась в том, что я не получал или не устанавливал таймауты в сети. WinAPI для ReadFile заявляет, что это должно быть установлено и что поведение было непредсказуемым, если оно не было установлено. Теперь приведенный ниже код последовательно работает на нескольких последовательных устройствах.

Для человека, который понизил это, промокните голову.

// W32SerialLibrary.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<windows.h>
#include<stdio.h>

#define SEL     4   // marks the end of the message. it should only appear after a NAK/ACK and never by itself.
#define ACK     6   // the last character before the end of the message
#define NAK     21  // the last character before the end of the message
#define GS      29  // indicates the start of a message.

#define MAX_BUFFER 512

void convertCharToWchar(const char *fromCharBuffer, wchar_t *toWcharBuffer, size_t toWcharBufferSize)
{
    int i;

    for (i = 0; fromCharBuffer[i] != '\0' && i < toWcharBufferSize; i++)
    {
        toWcharBuffer[i] = fromCharBuffer[i];
    }

    toWcharBuffer[i] = '\0';
}

int readMRZ(const char *portPath, char *mrzBuffer, const size_t mrzBuffer_size)
{
    HANDLE hComm;
    DCB dcbSerialParams;
    BOOL isGood;
    COMMTIMEOUTS commTimeOuts;
    char mrzChar; //Temporary character used for reading
    DWORD bytesRead;
    int mrzIndex;
    DWORD maskUsed;
    char errorChar = '_';
    wchar_t wportPath[MAX_PATH];

    convertCharToWchar(portPath, wportPath, sizeof(wportPath));

    hComm = CreateFile(wportPath,                //port name
        GENERIC_READ | GENERIC_WRITE,                 //Read/Write
        0,                                            // No Sharing
        NULL,                                         // No Security
        OPEN_EXISTING,                                // Open existing port only
        0,                                            // Non Overlapped I/O
        NULL);                                        // Null for Comm Devices

    if (hComm == INVALID_HANDLE_VALUE)
    {
        printf("Error in opening serial port\n");
        return -1;
    }

    // setup connection

    dcbSerialParams = { 0 }; // Initializing DCB structure
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

    isGood = GetCommState(hComm, &dcbSerialParams);

    dcbSerialParams.BaudRate = CBR_9600;  // Setting BaudRate = 9600
    dcbSerialParams.ByteSize = 8;         // Setting ByteSize = 8
    dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1
    dcbSerialParams.Parity = NOPARITY;  // Setting Parity = None

                                        // setup listener

    isGood = SetCommState(hComm, &dcbSerialParams);
    if (isGood == false)
    {
        printf("Error %d\n", GetLastError());
        return -1;
    }

    GetCommTimeouts(hComm, &commTimeOuts);

    isGood = SetCommMask(hComm, EV_RXCHAR);
    if (isGood == false)
    {
        printf("Error %d\n", GetLastError());
        return -1;
    }

    mrzIndex = 0;

    commTimeOuts.ReadTotalTimeoutConstant = 0;
    commTimeOuts.ReadTotalTimeoutMultiplier = 0;
    commTimeOuts.WriteTotalTimeoutConstant = 0;
    commTimeOuts.WriteTotalTimeoutMultiplier = 0;
    commTimeOuts.ReadIntervalTimeout = 500;

    SetCommTimeouts(hComm, &commTimeOuts);
    maskUsed = 0;
    WaitCommEvent(hComm, &maskUsed, NULL);
    commTimeOuts.ReadIntervalTimeout = 0;

    do
    {
        isGood = ReadFile(hComm,        //Handle of the Serial port
            &mrzChar,                   //Temporary character
            sizeof(mrzChar),            //Size of TempChar
            &bytesRead,                 //Number of bytes read
            NULL);

//      printf("isGood %d ch=%c dec=%d oct=%#o hex=%#08X maskUsed=%x bytesRead=%d\n", isGood, mrzChar, mrzChar, mrzChar, mrzChar, maskUsed, bytesRead);

        if (mrzChar == GS)
        {
            mrzIndex = 0;
            continue;
        }

        if (mrzChar == ACK)
        {
            mrzBuffer[mrzIndex] = '\0';
            break;
        }

        // fill buffer
        if ((mrzChar >= 48 && mrzChar <= 90) || mrzChar == '<' || mrzChar == errorChar || mrzChar == '\r')
        {
            if (mrzIndex == MAX_BUFFER)
            {
                exit(-1);
            }

            if (mrzChar == '\r')
            {
                mrzBuffer[mrzIndex++] = '\n';
            }

            mrzBuffer[mrzIndex++] = mrzChar;
        }
    }

    while (bytesRead > 0);

    CloseHandle(hComm);//Closing the Serial Port

    return 0;
}

int main()
{
    char mrzBuffer[512];
    int rVal;

    rVal = readMRZ("\\\\.\\COM1", mrzBuffer, sizeof(mrzBuffer));

    printf("\nrVal=%d mrzBuffer length=%d\n", rVal, strlen(mrzBuffer));
    printf("mrzBuffer=\n\"%s\"\n", mrzBuffer);

    return rVal;
}
-1
12 апр. '16 в 22:03
источник

Посмотрите другие вопросы по меткам или Задайте вопрос