Re: RS232 RxBufferSize WinCE

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: aba (aba_ru_at_mail.ru)
Date: 02/05/04


Date: 5 Feb 2004 01:20:39 -0800


"Steve Maillet \(eMVP\)" <nospam1@EntelechyConsulting.com> wrote in message news:<uZ9l7pm6DHA.1948@TK2MSFTNGP12.phx.gbl>...
> Ignore the size info - it's an error. Just call read file with as big a
> buffer as you want. The driver will use your buffer directly.

Thanks.
But I cann't understand why just after opening the port there is an
error CE_RXOVER, that I can not clear?! What am I doing wrong? Here's
my code (Initialization, and 2 functions for the reading thread, that
wrapped in CISerial class):

[code]
DWORD CISerial::PortInitialize(LPCTSTR lpPort, DWORD dwBaudRate, HWND
hWndOnMsg)
{

        COMMPROP commProp;
        CString str;

        COMSTAT Stat;
        DWORD dwErrors;
        // Attempt to open the serial port (COM1)

        PortClose();
        m_bPortOpened = FALSE;
        m_hSerialPort = CreateFile (_T("COM1:"), // Pointer to the name of
the port
                                                                  GENERIC_READ | GENERIC_WRITE, // Access (read-write) mode
                                                                  0, // Share mode
                                                                  NULL, // Pointer to the security attribute
                                                                  OPEN_EXISTING,// How to open the serial port
                                                                  0, // Port attributes
                                                                  NULL); // Handle to port with attribute
                                                                                                // to copy
        if (m_hSerialPort == INVALID_HANDLE_VALUE){
#ifdef DEBUG_MSGS_ON
                        MessageBox(_T("Unable to open serial port"), _T("Error"), MB_OK);
#endif
                        return GetLastError();
        }
        
        // Set the size of the input and output buffer
        if (!SetupComm(m_hSerialPort, 1024, 0)) {
#ifdef DEBUG_MSGS_ON
                MessageBox (_T("Unable to set the buffer-size parameters"),
_T("Error"), MB_OK);
#endif
                return GetLastError()?GetLastError():-1;
        }

    // Terminates all outstanding read and write operations and clear
the buffers
    VERIFY(PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR));

        // Initialize the DCBlength member.
        DCB PortDCB;
        FillMemory(&PortDCB, sizeof(PortDCB), 0);
        PortDCB.DCBlength = sizeof (DCB);

        // Get the default port setting information.
        GetCommState (m_hSerialPort, &PortDCB);

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

        // Configure the port according to the specifications of the DCB
        // structure.
        if (!SetCommState (m_hSerialPort, &PortDCB))
        {
          // Could not create the read thread.
#ifdef DEBUG_MSGS_ON
                MessageBox(_T("Unable to configure the serial port"), _T("Error"),
MB_OK);
#endif
                return GetLastError();
        }

        // Retrieve the time-out parameters for all read and write operations
        // on the port.
        COMMTIMEOUTS CommTimeouts;
        GetCommTimeouts (m_hSerialPort, &CommTimeouts);

        // Change the COMMTIMEOUTS structure settings.
        CommTimeouts.ReadIntervalTimeout = MAXDWORD;
        CommTimeouts.ReadTotalTimeoutMultiplier = 0;
        CommTimeouts.ReadTotalTimeoutConstant = 0; //5
        CommTimeouts.WriteTotalTimeoutMultiplier = 0;
        CommTimeouts.WriteTotalTimeoutConstant = 10;

        // Set the time-out parameters for all read and write operations
        // on the port.
        if (!SetCommTimeouts (m_hSerialPort, &CommTimeouts))
        {
          // Could not create the read thread.
#ifdef DEBUG_MSGS_ON
                MessageBox (_T("Unable to set the time-out parameters"),
_T("Error"), MB_OK);
#endif
                return GetLastError();
        }

        if (!ClearCommBreak(m_hSerialPort)) {
#ifdef DEBUG_MSGS_ON
                MessageBox (_T("Unable to restore character transmission
(unBREAK)"), _T("Error"), MB_OK);
#endif
                return GetLastError();
        }

/* if (!SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR |
EV_RING)) {
#ifdef DEBUG_MSGS_ON
                MessageBox (_T("Unable to specify a set of events to be monitored
for a communications device"), _T("Error"), MB_OK);
#endif
                return GetLastError();
        }
*/
        if (!EscapeCommFunction(m_hSerialPort, SETDTR)){
#ifdef DEBUG_MSGS_ON
                        MessageBox (_T("Unable to set DTR line"), _T("Error"), MB_OK);
#endif
                        return GetLastError();
        }
        if (!EscapeCommFunction(m_hSerialPort, CLRRTS)){
#ifdef DEBUG_MSGS_ON
                        MessageBox (_T("Unable to clear RTS line"), _T("Error"), MB_OK);
#endif
                        return GetLastError();
        }

// ::Sleep(10);

#ifdef DEBUG_MSGS_ON
        if (GetCommProperties(m_hSerialPort, &commProp)) {
                str.Format(_T("Comm properties: %X(dwMaxTxQueue), %X(dwMaxRxQueue),
%X(dwMaxBaud), %X(dwProvSubType), %X(dwProvCapabilities),
%X(dwSettableParams), %X(dwSettableBaud), %X(wSettableData),
%X(wSettableStopParity), %X(dwCurrentTxQueue), %X(dwCurrentRxQueue)"),
commProp.dwMaxTxQueue, commProp.dwMaxRxQueue, commProp.dwMaxBaud,
commProp.dwProvSubType, commProp.dwProvCapabilities,
commProp.dwSettableParams, commProp.dwSettableBaud,
commProp.wSettableData, commProp.wSettableStopParity,
commProp.dwCurrentTxQueue, commProp.dwCurrentRxQueue);
                MessageBox (str, _T("SerialPort"), MB_OK);
        }
#endif
        
        dwErrors = 0;
        if (ClearCommError (m_hSerialPort, &dwErrors, &Stat)) {
#ifdef DEBUG_MSGS_ON
                str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d),
CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d),
CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d),
fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d),
fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK,
dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE,
dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY,
dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold,
Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue,
Stat.cbOutQue);
                MessageBox (str, _T("SerialPort"), MB_OK);
#endif
        }

                //GetCommState (m_hSerialPort, &PortDCB);
                //str.Format(_T("Actual BaudRate is %d"), PortDCB.BaudRate);
                //MessageBox (str, _T("OpeningPort"), MB_OK);
                m_BaudRate = dwBaudRate;
                m_lpPortName = lpPort;

        m_bPortOpened = TRUE;

        //Starting working thread for reading & processing inData
        THREADPARMS* ptp = new THREADPARMS;
        ptp->pClass = this;
        ptp->hWndOnMsg = hWndOnMsg;

        //pReadThread = AfxBeginThread(PortReadThreadProcT, ptp,
THREAD_PRIORITY_HIGHEST); //LPVOID(this));

        pReadThread = ::CreateThread(NULL, 0, PortReadThreadProcT, ptp, 0,
NULL); //LPVOID(this));
        if (pReadThread == NULL) {
#ifdef DEBUG_MSGS_ON
                        MessageBox (_T("Unable to run ReadThread"), _T("Error"), MB_OK);
#endif
                        return GetLastError();
        }

        VERIFY(SetThreadPriority(pReadThread, THREAD_PRIORITY_HIGHEST));

        return 0;
}

DWORD WINAPI CISerial::PortReadThreadProcT(LPVOID pParam)
{
        // Route the method to the actual object
        THREADPARMS* ptp = (THREADPARMS*) pParam;
        CISerial* pThis = reinterpret_cast<CISerial*>(ptp->pClass);
    HWND hWnd = ptp->hWndOnMsg;
    delete ptp;
        
        return pThis->PortReadThreadProc(hWnd);
}

UINT CISerial::PortReadThreadProc(HWND hWnd)
{
        DWORD inDataCount =
sizeof(m_InDataPacketCur)/sizeof(m_InDataPacketCur[0]);
        DWORD dwBytesTransferred, dwTotalBytesTransferred = 0;
        BOOL bErr;
        DWORD dwCommModemStatus;
        int dCheckErrCount = NUM_CHECKSUM_TRY;
        COMSTAT Stat;
        DWORD dwErrors;
        BYTE readBuf[RxBufferSize];
// int pReadBuf = 0; //pointer to current position in readBuf

        CString str;
        
        ::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_WAITING,
(WPARAM) 0, 0);
        VERIFY(PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR));
        VERIFY(SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR |
EV_RING | EV_BREAK | EV_ERR));

        dwErrors = 0;
        if (ClearCommError (m_hSerialPort, &dwErrors, &Stat)) {
#ifdef DEBUG_MSGS_ON
                str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d),
CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d),
CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d),
fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d),
fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK,
dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE,
dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY,
dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold,
Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue,
Stat.cbOutQue);
                MessageBox (str, _T("SerialPort"), MB_OK);
#endif
        }

        while (m_hSerialPort != INVALID_HANDLE_VALUE) {//
                // Wait for an event to occur for the port.
                WaitCommEvent (m_hSerialPort, &dwCommModemStatus, NULL);
                // Re-specify the set of events to be monitored for the port.
                SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING |
EV_BREAK | EV_ERR);

                //check the event for errors
                if (dwCommModemStatus & EV_ERR)
                {
                        dwErrors = 0;
                        if (ClearCommError(m_hSerialPort, &dwErrors, &Stat)) {
#ifdef DEBUG_MSGS_ON
                                str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d),
CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d),
CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d),
fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d),
fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK,
dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE,
dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY,
dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold,
Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue,
Stat.cbOutQue);
                                MessageBox (str, _T("SerialPort"), MB_OK);
#endif
                        }
                } //if (dwCommModemStatus & EV_ERR)

                //check for RXCHAR
                if (dwCommModemStatus & EV_RXCHAR)
                {

                        // Loop for waiting for the data.
                        do
                        {
                                bErr = ReadFile(m_hSerialPort, &readBuf[0],
(inDataCount>dwTotalBytesTransferred)?(inDataCount-dwTotalBytesTransferred):0,
&dwBytesTransferred, NULL);
                                if (!bErr) {
                                                return GetLastError();
                                }

                                if (dwBytesTransferred > 0){
                                        m_mutexSerPortRxBufferBusy.Lock();
                                        //copying inData from readBuf to m_InDataPacketCur
                                        memcpy(&m_InDataPacketCur[dwTotalBytesTransferred], &readBuf[0],
dwBytesTransferred);
                                        m_mutexSerPortRxBufferBusy.Unlock();
                                                
                                        dwTotalBytesTransferred += dwBytesTransferred;

                                        if (dwTotalBytesTransferred < inDataCount)
                                                ::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_WAITING,
(WPARAM) 0, 0);
                                                //return 2 ;
                                        else {
// if (dwTotalBytesTransferred >= inDataCount) {
                                                if (!CISerial::ProcessInData()) {
                                                        //Error in checksum => try to receive extra data
                                                        ::PostMessage (hWnd,
WM_USER_SERIAL_PORT_READING_THREAD_SUMCHECK_ERR, (WPARAM)
(NUM_CHECKSUM_TRY-dCheckErrCount), 0);
                                                        if (dCheckErrCount--) {
                                                                m_mutexSerPortRxBufferBusy.Lock();
                                                                memmove(&m_InDataPacketCur[0], &m_InDataPacketCur[1],
inDataCount-1);
                                                                m_mutexSerPortRxBufferBusy.Unlock();
                                                                dwTotalBytesTransferred--;
                                                        }
                                                        else {
                                                                dwTotalBytesTransferred = 0;
                                                                ::PostMessage (hWnd,
WM_USER_SERIAL_PORT_READING_THREAD_CANCELED, (WPARAM) 0, 0);
                                                                return 1;
                                                        }
                                                }
                                                else {
                                                        dwTotalBytesTransferred = 0;
                                                        dCheckErrCount = NUM_CHECKSUM_TRY;
                                                        ::PostMessage (hWnd,
WM_USER_SERIAL_PORT_READING_THREAD_FINISHED, (WPARAM) 0, 0);
                                                }
                                        } //if (dwTotalBytesTransferred >= inDataCount)
                                } //if (dwBytesTransferred > 0)

                        } while ((dwBytesTransferred > 0));//&&(dwTotalBytesTransferred <
inDataCount));
                }

                
                if (WaitForSingleObject(m_eventSerPortReadKill, 0) ==
WAIT_OBJECT_0){
                        break;
                }

        } //while (m_hSerialPort != INVALID_HANDLE_VALUE)

        return 0;
}

[/code]



Relevant Pages