串行通信未在模拟端口上阻塞

时间:2016-04-06 20:29:24

标签: c winapi serial-port

当通信通过实际串行端口时,以下代码按预期工作。进程阻塞ReadFile并等待串行缓冲区填充,然后继续处理。

但是,当我连接模拟串行端口的USB设备时,即使没有数据通过缓冲区,ReadFile也不会阻塞。

从USB连接设备每秒钟我得到以下输出......

rVal = 1 ch = -52 bytesRead = 0

因此,在通过usb端口发送字节之前,不会返回错误并且字节读取始终为0。

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 个答案:

答案 0 :(得分:-1)

问题在于我没有得到或设置通讯超时。 WinFI for 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;
}