设备上的串行通信期间出现异常行为

时间:2019-06-02 07:46:19

标签: c++ winapi serial-port serial-communication

”我正在编写程序,该程序在com端口串行通信上同步写入数据,并且在writefile之后放置睡眠时读取操作也是同步的,但是它可以正常工作,但是如果删除睡眠,那么我会得到一些错误数据,其中0x20空间不是所有数据都是错误但有些字节”

我已经添加了我已经使用过的写入文件和读取文件,并且还创建了文件,请告知我哪里错了

int CCommLink::WriteComm (HANDLE hComm, void* pBuf, int iLen, DWORD dwTimeToWait, UINT nBaud)
{

    OVERLAPPED ol;
    memset (&ol, 0, sizeof(OVERLAPPED));
    ol.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

    COMSTAT ComStat;
    DWORD dwErrorFlags, dwBytesWrite;

    // ---------------------------------------------------------------------
    // clear the buffer
    // ---------------------------------------------------------------------
    ClearCommError (hComm, &dwErrorFlags, &ComStat);
    dwBytesWrite = (DWORD)ComStat.cbOutQue;

    if (dwBytesWrite)
    {
        DWORD dwTickCount = GetTickCount();
        do
        {
            ClearCommError (hComm, &dwErrorFlags, &ComStat);
            dwBytesWrite = (DWORD)ComStat.cbOutQue;
        } while ( dwBytesWrite && GetTickCount() - dwTickCount < 
 dwTimeToWait);
    }



    // ----------------------------------------------------------------
    // write the data to the serial port
    // ---------------------------------------------------------------------
    if (!WriteFile (hComm, pBuf, iLen, &dwBytesWrite, NULL))
    {
        if (GetLastError() == ERROR_IO_PENDING)
        {
//          GetOverlappedResult(hComm, &ol, &dwBytesWrite, TRUE);
            WaitForSingleObject (ol.hEvent, iLen * 40000 / nBaud);
            dwBytesWrite = iLen;
        }
        else
        {
//          CString cs = GetLastErrorStr();
            return 0;
        }
    }


    return dwBytesWrite;    
}




******************* read file function************************


int CCommLink::ReadComm (HANDLE hComm, void* pBuf, DWORD dwTimeToWait, UINT nBaud, DWORD dwBytesToRead)
{

//  dwTimeToWait=100;
    OVERLAPPED ol;
    memset (&ol, 0, sizeof(OVERLAPPED));
    ol.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

    COMSTAT ComStat;
    DWORD dwErrorFlags, dwBytesRead;

    ClearCommError (hComm, &dwErrorFlags, &ComStat);
    dwBytesRead = (DWORD)ComStat.cbInQue;


    if (!dwBytesRead)
    {
        if (!dwTimeToWait)
            return 0;

        DWORD dwTickCount = GetTickCount();
        do
        {
            ClearCommError (hComm, &dwErrorFlags, &ComStat);
            dwBytesRead = (DWORD)ComStat.cbInQue;
        } while (!dwBytesRead && GetTickCount() - dwTickCount < dwTimeToWait);
    }

    if (!dwBytesRead)
        return -1;

    if (dwBytesRead > dwBytesToRead)
        dwBytesRead = dwBytesToRead;
    (void)memset((void *)pBuf, ' ', (size_t)256);


    if (!ReadFile (hComm, pBuf, 1, &dwBytesRead,  NULL))
    {

        LogResult(_T("********************************************ERROR WHILE READING ***********************************************"));
        if (GetLastError() == ERROR_IO_PENDING)
        {
            DWORD w = (32*10000) / nBaud;
            if (!w)
                w = 16;
            WaitForSingleObject (ol.hEvent, w);
            dwBytesRead = 1;
        }
        else
            dwBytesRead = 0;
    }

    CString str=  LogStr((unsigned char*)pBuf ,1);
    LogResult(str);

      //   pBuf=(void*)UxRx; 
    if (!dwBytesRead)
    {
//      CString cs = GetLastErrorStr();
        return -2;
    } 

    return (int)dwBytesRead;
}





HANDLE CCommLink::SetComm (int iPort, UINT nBaud, int Parity, int StopBits)
{

    // ---------------------------------------------------------------------
    // open a port handle
    // ---------------------------------------------------------------------
    CString cPort;
    if (iPort < 10)
        cPort.Format(_T("COM%d"), iPort);
    else
        cPort.Format(_T("\\\\.\\COM%d"), iPort);

    HANDLE hPort = CreateFile(
        cPort,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
         0,// FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        NULL);

    if (INVALID_HANDLE_VALUE == hPort)
        return INVALID_HANDLE_VALUE;

    // ---------------------------------------------------------------------
    // set communication buffer size
    // ---------------------------------------------------------------------
    if (!SetupComm(hPort, eSize_LinkBuffer*2, eSize_LinkBuffer*2))          // h,in,out
    {
        CloseHandle (hPort);
        return INVALID_HANDLE_VALUE;
    }

    // ---------------------------------------------------------------------
    // set timeout contants
    // ---------------------------------------------------------------------
    COMMTIMEOUTS CommTimeOuts;

    CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    CommTimeOuts.ReadTotalTimeoutConstant = 0;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 80000/nBaud ? 80000/nBaud : 1;
    CommTimeOuts.WriteTotalTimeoutConstant = CommTimeOuts.WriteTotalTimeoutMultiplier * 8;

    if( !SetCommTimeouts(hPort, &CommTimeOuts) )
    {
        CloseHandle (hPort);
        return INVALID_HANDLE_VALUE;
    }

    // ---------------------------------------------------------------------
    // set port configurations
    // ---------------------------------------------------------------------
    DCB dcb;                                // Initialize the DCBlength member. 
    dcb.DCBlength = sizeof (DCB);           // Get the default port setting information.
    GetCommState (hPort, &dcb);

    // Change the DCB structure settings.
    dcb.BaudRate = nBaud;                   // Current baud 
    dcb.fBinary = TRUE;                     // Binary mode: no EOF check 
    dcb.fParity = TRUE;                     // Parity checking: Disable
    dcb.fOutxCtsFlow = FALSE;               // No CTS output flow control 
    dcb.fOutxDsrFlow = FALSE;               // No DSR output flow control 
    dcb.fDtrControl = DTR_CONTROL_ENABLE;   // DTR flow control type 
    dcb.fDsrSensitivity = FALSE;            // DSR sensitivity 
    dcb.fTXContinueOnXoff = TRUE;           // XOFF continues Tx 
    dcb.fOutX = FALSE;                      // No XON/XOFF out flow control 
    dcb.fInX = FALSE;                       // No XON/XOFF in flow control 
    dcb.fErrorChar = TRUE;                  // Disable error replacement 
    dcb.fNull = FALSE;                      // Disable null stripping 
    dcb.fRtsControl = RTS_CONTROL_ENABLE;   // RTS flow control 
    dcb.fAbortOnError = FALSE;              // Do not abort reads/writes on: error
    dcb.ByteSize = 8;                       // Number of bits/BYTE, 4-8 
    dcb.Parity = Parity;                    // 0-4=no,odd,even,mark,space
    dcb.StopBits = StopBits;                // 0,1,2 = 1, 1.5, 2 
    dcb.ErrorChar = ' ';                    // reaplacement of the TCHAR with parity error 

    if (!SetCommState (hPort, &dcb)) 
    {
        CloseHandle (hPort);
        return INVALID_HANDLE_VALUE;
    }

    return hPort;
}

1 个答案:

答案 0 :(得分:0)

您的ReadFile()可能返回TRUE(成功),而pBuf中没有数据。要解决此问题,您可以将ReadIntervalTimeout设置为例如10(毫秒)而不是MAXDWORD,因为:

  

MAXDWORD的值,与两个   ReadTotalTimeoutConstant和ReadTotalTimeoutMultiplier成员,   指定读取操作将立即返回   已收到的字节,即使没有字节   收到

(下面与您的问题没有直接关系,但有一些代码提示)。

由于设置了同步操作而不是异步操作,因此存在一些冗余代码行:

OVERLAPPED ol;
memset (&ol, 0, sizeof(OVERLAPPED));
ol.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

WaitForSingleObject();

为了使重叠的操作生效。您需要为CrateFile()设置FILE_FLAG_OVERLAPPED标志,并为WriteFile()ReadFile()配置OVERLAPPED结构;

//...

    HANDLE hPort = CreateFile(
        L"COM8",
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL);

//...

    WriteFile(hComm, pBuf, iLen, NULL, &ol);

//...

    ReadFile(hComm, pBuf, 1, NULL, &ol);