首页 > 解决方案 > 读取文件操作完成但用多条消息/串行通信填充数据缓冲区

问题描述

我正在开发一个在串行端口上读取数据的应用程序。可以在短时间内通过这个串口发送各种消息,读取传入数据的线程必须在 ReadFile 操作完成时识别它读取的消息类型。我正在使用重叠的结构,我希望一条一条地阅读消息。

我的问题是 ReadFile 操作经常用多条消息填充缓冲区,我找不到阻止这种情况发生的 com 超时值。我怀疑当背靠背收到两条消息时读取操作没有完成,从读取线程中可以看出这是一条消息,因为当第一条消息完成时串行端口上仍有数据。

我正在使用非重叠结构观察相同的现象。

我使用的是串口,配置如下:

    DCB configPort = { 0 };
    COMMTIMEOUTS timeouts;

    this->hDevice = CreateFileA(
            this->portReady,
            GENERIC_READ | GENERIC_WRITE,
            NULL,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL
    );

    if (this->hDevice == INVALID_HANDLE_VALUE) {
        std::cout << "INVALID HANDLE" << std::endl;
        return 0;
    }

    OvReception.Offset = 0;
    OvReception.OffsetHigh = 0;
    OvReception.hEvent = ::CreateEvent(NULL, FALSE, FALSE, _T("")); 

    configPort.DCBlength = sizeof(DCB);
    configPort.BaudRate = CBR_38400;
    configPort.StopBits = ONESTOPBIT;
    configPort.Parity = EVENPARITY;
    configPort.ByteSize = 8;
    configPort.fRtsControl = RTS_CONTROL_DISABLE;

    configPort.fAbortOnError = 0;
    configPort.XonLim = 800;
    configPort.XoffLim = 2000;

    timeouts.ReadIntervalTimeout = 1;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;

    if (!SetCommState(this->hDevice, &configPort)) {
        CloseHandle(this->hDevice);
        return 0;
    }

    if (!SetCommTimeouts(this->hDevice, &timeouts)) {
        CloseHandle(this->hDevice);
        return 0;
    }

我使用以下方法读取传入数据:


    bool readState = false;
    char incomingMessage[512] = {0};
    DWORD bytesRead = 0;
    memset(incomingMessage, 0, sizeof(incomingMessage));
    while (this->threadRunning) {

        readState = ReadFile(
            this->comSerie.hDevice,
            incomingMessage,
            sizeof(incomingMessage),
            NULL,
            &this->comSerie.OvReception);

        if (::GetLastError() == ERROR_IO_PENDING)
        {
            ::GetOverlappedResult(this->comSerie.hDevice, &this->comSerie.OvReception, &bytesRead, TRUE);
        }
        //NO ERRORS OBSERVED
        std::cout << "ERROR" << std::endl;
        std::cout << GetLastError() << std::endl;

        std::cout << "Message received" << std::endl;
        std::cout << incomingMessage<< std::endl;
        switch(ReceivedMessageType(incomingMessage)){
         //............ DO SOMETHING
        }
        //Clean buffer
        memset(incomingMessage, 0, sizeof(incomingMessage));
    }

我在 GetOverlappedResult 中将 bwait 参数配置为 TRUE,以便在写操作完成之前它不会返回。我没有观察到 GetLastError() 返回的任何错误。

我也试过使用 WaitForSingleObject 函数,问题是一样的。

我错过了什么吗?

谢谢您的帮助

标签: c++serial-portreadfile

解决方案


推荐阅读