繁体   English   中英

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

[英]Serial Communications not blocking on an emulated port

当通信通过真正的串行端口时,以下代码按预期工作。 该进程在 ReadFile 上阻塞,并在处理继续之前等待串行缓冲区被填充。

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

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

rVal=1 ch=-52 字节读取=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);
 ...

问题是我没有得到或设置通信超时。 WinAPI 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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM