c++ ReadFile始终返回false,GetLastError报告ERROR_IO_PENDING,Waitforsingleobject通过

zzzyeukh  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(116)

我想做的是从一个COM端口获取 Dataframe ,每个 Dataframe 是258字节,并且以每秒8.5字节的速度不断进入。
我需要接收 Dataframe ,然后我将对它们进行一些其他处理,但现在我试图将它们打印到控制台。每个 Dataframe 以'/'开头,以'?'结尾。
下面是我写的代码(是的,我是一个新手):

#include <iostream>
#include <time.h>
#include <string>

#include "windows.h"
#pragma comment (lib, "OneCore.lib")

int main()
{
    int portnum = 0;

    ULONG ptNums[300];
    ULONG some = 300;
    ULONG ptsFound[20];
    LPCSTR fName = "COM4";

    ULONG status = GetCommPorts(ptNums, 100, ptsFound);
    if (status == ERROR_SUCCESS) {
        std::cout << "ports found:" << ptsFound[0] << "\n";
        for (int i = 0; i < ptsFound[0]; i++) {
            portnum = ptNums[i];
            std::cout << "COM" << portnum << "\n";
        }
    }

    HANDLE port = CreateFileA(fName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
    if (port == INVALID_HANDLE_VALUE) {
        std::cout << "unable to open port\n";

    }

    DCB dcb;
    dcb = { 0 };
    //this is the default, use 8N1
    dcb.DCBlength = sizeof(DCB);
    dcb.fBinary = TRUE;
    dcb.BaudRate = 250000;
    dcb.fParity = FALSE;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;

    DWORD eventMask;

    SetCommState(port, &dcb);
    SetCommMask(port,EV_TXEMPTY|EV_RXCHAR);

    bool exitloop = false;
    char arduBuf[258];

    OVERLAPPED ov;
    ov.Offset = 0;
    ov.OffsetHigh = 0;
    ov.hEvent = CreateEvent(0, TRUE, 0, 0);
    SetupComm(port, 300, 300);

    while (!exitloop) {
        
        GetCommMask(port, &eventMask);
        BOOL dataRet = WaitCommEvent(port, &eventMask, &ov);
        DWORD dwait = WaitForSingleObject(ov.hEvent, INFINITE);
        
        if (eventMask & EV_TXEMPTY) {
            std::cout << "all data was sent\n";
            exitloop = true;
        }

        if (dwait == WAIT_OBJECT_0) {
            GetCommMask(port, &eventMask);
            std::cout << "some random stuff was received\n";

            BOOL status = ReadFile(port, arduBuf, sizeof(arduBuf), NULL, &ov);
            std::cout << "status:" << status << "\nerror is:" << GetLastError() << "\n";
            PurgeComm(port, PURGE_RXCLEAR);
            if (status) {
                std::cout << arduBuf << "\n";
            }
            ResetEvent(ov.hEvent);
            //exitloop = true;
        }

        if (dwait == WAIT_TIMEOUT) {
            std::cout << "timeout\n";
        }
    }
}

字符串
代码编译并运行,WaitForSingleObject()返回WAIT_OBJECT_0,但状态始终为0,GetLastError()返回ERROR_IO_PENDING。如果我打印出数据缓冲区,那么我可以看到我的数据,但它在一些混乱的行上,并且非常不一致:
x1c 0d1x的数据
我认为这是因为虽然EV_RXCHAR得到了满足,但EV_TXEMPTY永远不会得到满足。如果我将掩码设置为EV_TXEMPTY,那么代码将在WaitForSingleObject()处挂起。我认为这是因为在数据被读取之前,已经有新的数据填充了输入缓冲区。
我的问题:

  • 这里明显有问题,有人能指出吗?
  • 我不确定把阅读的过程放到while循环中是否是一个好主意,我知道应该把它放到一个线程中,一旦读失败或成功就终止,但是while循环真的会导致问题吗?
  • 我在WaitForSingleObject()行上得到一个警告,ov.hEvent可能是0。为什么会这样,这也是一个问题吗?
  • 我什么时候需要重置事件?

正如你可以告诉,我是新的COM端口I/O。我已经花了一天多的时间在这方面,并决定是时候问别人知道他们在做什么。

ar7v8xwq

ar7v8xwq1#

正如@tevemadar所说,ERROR_IO_PENDING不是一个失败;它表示读操作异步地等待完成。

  • 如果重叠的操作不能立即完成,则函数返回null,GetLastError函数返回ERROR_IO_PENDING,表示操作正在后台执行。当这种情况发生时,系统在WaitCommEvent返回之前将OVERLAPPED结构的hEvent成员设置为无信号状态,然后,当发生指定的事件或错误时,它将其设置为信号状态。

使用GetOverlappedResult函数来确定WaitCommEvent操作的结果可以获得一些更新。

相关问题