WriteFile on Com port indicates Tx complete, but no data transmitted

0

I am using VS 2013 Professional in an MFC project

I have been using my software to receive data from the com port for some time, but recently needed to add transmission capability The Init code is:

BOOL PASCAL FAR SetupConnect(pCONNECTION pCon, pCOMCONFIG pCfg) { DCB dcb;

pSERBUF pSB = pCon->BufStruct;
//  pSERBUF *ppSB = (pSERBUF*)pCon->BufStruct;
//  pSB = *ppSB;

dcb.DCBlength = sizeof(DCB);


CheckComs(); // Gets available COM ports

pCon->Port = pNames[0].PortNames[3] - 0x30;

if (pCon->BufStruct == NULL) // This is a personal Communications structure
{                            // Init
    pCon->hSB = GlobalAlloc(GHND, sizeof(SERBUF));
    if (pCon->hSB == NULL)
    {
        //          return INVALID_HANDLE_VALUE;
        return 0;
    }

    pSB = (pSERBUF)GlobalLock(pCon->hSB);

    pSB->idComDev = INVALID_HANDLE_VALUE;

    pCon->BufStruct = pSB;
}
else return (0);

if (pSB->idComDev == INVALID_HANDLE_VALUE)
{
    pSB->idComDev = CreateFile(pNames[0].PortNames, GENERIC_READ | GENERIC_WRITE,
        0,      //exclusive access
        NULL,   // no security
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        NULL);
}

// Current configuration
GetCommState(pSB->idComDev, &dcb);

// Setup baudrate, parity, etc.

dcb.BaudRate = pCfg->dwBaudRate;
dcb.ByteSize = pCfg->bDataBits;
dcb.Parity = pCfg->bParity;
dcb.StopBits = pCfg->bStopBits;

// Setup Flow Control
dcb.fOutxDsrFlow = pCfg->handshake_DTR;
dcb.fDtrControl = DTR_CONTROL_ENABLE;       // DTR high while port open

dcb.fOutxCtsFlow = pCfg->handshake_RTS;
dcb.fRtsControl = RTS_CONTROL_DISABLE;      // Toggle RTS with EscapeCommFunction


// XON/XOFF Not Used
dcb.fInX = FALSE;
dcb.fOutX = FALSE;

dcb.fBinary = TRUE;
dcb.fParity = TRUE;

//return TRUE if everything looks cool
return (SetCommState(pSB->idComDev, &dcb));

}

And:

CSerCom::CSerCom() { pCon = &Con; pCfg = &Cfg; m_SerHwnd = this; pCfg->dwBaudRate = 115200; pCfg->bDataBits = 8; pCfg->bParity = NOPARITY; pCfg->bStopBits = TWOSTOPBITS; // here

SetupConnect(pCon, pCfg);
pSERBUF pSB = pCon->BufStruct; // pSB is set in SetUpConnect

if (pSB->idComDev == INVALID_HANDLE_VALUE)
{
    // device open failure
    // hardware not there or someone else controls it!
    GlobalUnlock(pCon->hSB);
    GlobalFree(pCon->hSB);
    pCon->BufStruct = NULL;

    //      TODO stop this from going any further
    HandleFailure();
}
else // Only continue if Port is available
{

    // Clear Buffer
    SetupComm(pSB->idComDev, 4096, 4096);
    PurgeComm(pSB->idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    // create the overlapped events
    memset(&(pSB->osRead), 0, sizeof(OVERLAPPED));
    memset(&(pSB->osWrite), 0, sizeof(OVERLAPPED));

    pSB->osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    pSB->osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if ((pSB->osRead.hEvent == NULL) || (pSB->osWrite.hEvent == NULL))
    {
        ReleaseNetResources(pCon);
        CloseHandle(pSB->idComDev);
        pSB->idComDev = INVALID_HANDLE_VALUE;
        HandleFailure();

        //      return (pSB->idComDev);
    }

    // allocate & lock the mem
    // (used to contain data points to & from the MODBUS
    //  as well as the receive buffer for incoming serial data) 

    pSB->hRcv = GlobalAlloc(GHND, MAX_RX_LEN);
    if (pSB->hRcv == NULL)
    {
        ReleaseNetResources(pCon);
        CloseHandle(pSB->idComDev);
        pSB->idComDev = INVALID_HANDLE_VALUE;
        HandleFailure();

        //      return (pSB->idComDev);
    }

    pSB->pRcv = (char  *)GlobalLock(pSB->hRcv);


    pSB->hTx = (char *)GlobalAlloc(GHND, MAX_TX_LEN);
    if (pSB->hTx == NULL)
    {
        ReleaseNetResources(pCon);
        CloseHandle(pSB->idComDev);
        pSB->idComDev = INVALID_HANDLE_VALUE;
        HandleFailure();
        //      return (pSB->idComDev);
    }

    pSB->pTx = (char  *)GlobalLock(pSB->hTx);

    // remember the setup params
    pSB->TimeOut = 3; //CalculateTimeOut(pCfg->dwBaudRate);
    //  pSB->TimerId = TimerId;
    // initialize the status counters
    //  pSB->ValidCt = 0;
    //  pSB->InvalidCt = 0;
    pSB->RxInIdx = 0;

    //          pSB->RTS_Delay[0] = pCfg->RTS_Delay[0];
    //          pSB->RTS_Delay[1] = pCfg->RTS_Delay[1];
    pSB->RTS_Delay[0] = 100;
    pSB->RTS_Delay[1] = 100;

    // setup the Comm Timeouts
    CommTimeOuts.ReadIntervalTimeout = 0xffffffff;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    CommTimeOuts.ReadTotalTimeoutConstant = 1000;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    CommTimeOuts.WriteTotalTimeoutConstant = 1000;
    SetCommTimeouts(pSB->idComDev, &CommTimeOuts);


    // if everything looks good to here
    // create the Receive Thread & return the CONNECT handle
    pSB->hIOThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
        0,
        (LPTHREAD_START_ROUTINE)SerProc,
        (LPVOID)pCon,
        0,
        &dwThreadID);

    if (pSB->hIOThread == NULL)
    {
        ReleaseNetResources(pCon);
        CloseHandle(pSB->idComDev);
        pSB->idComDev = INVALID_HANDLE_VALUE;
        HandleFailure();
        //      return (pSB->idComDev);
    }

    hIOT = pSB->hIOThread;
}

}

So with that set up, I enter a thread loop in which I have the following

        // wait indefinitely for somthing to happen
    WaitCommEvent(pSB->idComDev, &dwEvtMask, NULL);

    // Catch Rx event
    if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
    {
        Edit1_txt.Format(_T("Rx'd"));
        E1->SetWindowText(Edit1_txt);
        CMFCView->UpdateWindow();
        // only try to read number of bytes in queue 
        ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);

        dwLength = ComStat.cbInQue;

        // Read data bytes into connection Rcv Buffer at current RxInIdx
        if (dwLength > 0)
        {
            fReadStat = ReadFile(pSB->idComDev,
                &(pSB->pRcv[pSB->RxInIdx]),
                dwLength,
                &bytesread,
                &(pSB->osRead));

            if (!fReadStat)
            {
                if (GetLastError() == ERROR_IO_PENDING)
                {
                    // We have to wait for read to complete. 
                    while (!GetOverlappedResult(pSB->idComDev,
                        &(pSB->osRead), &bytesread, FALSE))
                    {
                        dwErrorFlags = GetLastError();
                        if (dwErrorFlags != ERROR_IO_INCOMPLETE)
                            // an error occurred, try to recover
                            ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);

                    }

                }
                else
                {
                    // some other error occurred
                    dwLength = 0;
                    ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
                }

            }   // End of Read Error
        }       // End of Read Char

        if (ComStat.cbInQue < 500)
        {
            // update the receive index
            pSB->RxInIdx += dwLength;
            wSleepime = GetTickCount();         // hkk  7/16/99     for console app

            ParseAPI(pSB);

        }
        else
            ComStat.cbInQue = 0;
    }

    // At some point in the program pSB->TxOutIdx is set to some positive value
    if (pSB->TxOutIdx > 0)
    {
        dwLength = pSB->TxOutIdx;
        fWriteStat = WriteFile(pSB->idComDev,
            &(pSB->pTx[pSB->TxOutIdx]),
            dwLength,
            &byteswritten,
            &(pSB->osWrite));

        if (!fWriteStat)
        {
            if (GetLastError() == ERROR_IO_PENDING)
            {
                while (!GetOverlappedResult(pSB->idComDev,
                    &(pSB->osWrite), &byteswritten, FALSE))
                {
                    dwErrorFlags = GetLastError();
                    if (dwErrorFlags != ERROR_IO_INCOMPLETE)
                        // an error occurred, try to recover
                        ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
                }
            }

            pSB->TxOutIdx -= byteswritten;
        }
    }
}

This detects the Tx buffer full, (pSB->TxOutIdx > 0) and transmits the data

The transmit fails with an IO pending error, but after execution of GetOverlappedResult, bytes written show the length desired.

However, no data comes out the port. I have checked, and the port found and used is correct.

Wassup?

windows
windows-10
visual-studio-2013
asked on Super User Aug 31, 2019 by user155906

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0