Re: Serial Communication Problem

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: George (George_at_discussions.microsoft.com)
Date: 11/30/04


Date: Mon, 29 Nov 2004 18:13:03 -0800

This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
        DCB dcb;
        HANDLE nComID;
        COMSTAT ComStat;
        BOOL bBuildComm;
        BOOL bSetCommStateRtn;
        char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

        nComID = CreateFile("COM1",
                                GENERIC_READ | GENERIC_WRITE, 0,
                                NULL, OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

//////////////////////// BuildComm
/////////////////////////////////////////////////

        dcb.DCBlength = sizeof(DCB);
        GetCommState(nComID, &dcb);
        strcpy(szPortSet, "COM1:9600,e,7,2");

        bBuildComm = BuildCommDCB(szPortSet,&dcb);

/////////////////////// SetCommState
/////////////////////////////////////////////

        ZeroMemory(&dcb, sizeof(DCB));
           dcb.DCBlength = sizeof(DCB);
           dcb.wReserved = 0;

        dcb.BaudRate = CBR_9600;
        dcb.fParity = TRUE;
        dcb.Parity = 2;
        dcb.ByteSize = 7;
        dcb.StopBits = 2;

        dcb.fOutxCtsFlow = FALSE;
        dcb.fOutxDsrFlow = FALSE;
        dcb.fDtrControl = DTR_CONTROL_ENABLE;
        dcb.fRtsControl = RTS_CONTROL_ENABLE;
        dcb.fDsrSensitivity = FALSE;
        //XON/XOFF
        dcb.fOutX = TRUE;
        dcb.fInX = TRUE;
        dcb.fTXContinueOnXoff = TRUE;
        dcb.XonLim = 2048;
        dcb.XoffLim = 2048;
        dcb.XonChar = 0x11;
        dcb.XoffChar = 0x13;

        dcb.fBinary = TRUE;
        dcb.fNull = FALSE;
        dcb.fAbortOnError = TRUE;
        dcb.fErrorChar = FALSE;
        dcb.ErrorChar = 0x00;

        bSetCommStateRtn = SetCommState(nComID, &dcb);

/////////////////////////////////////////////////////////////////////////////////////////////

        if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
                if (GetLastError() != CE_MODE) {
                        DWORD dwErrors;
                        if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
                                return GetLastError();
                         }
                }
        }

        COMMTIMEOUTS comm_timeout;
        comm_timeout.ReadIntervalTimeout = MAXDWORD;
        comm_timeout.ReadTotalTimeoutMultiplier = 0;
        comm_timeout.ReadTotalTimeoutConstant = 0;
        comm_timeout.WriteTotalTimeoutMultiplier = 0;
        comm_timeout.WriteTotalTimeoutConstant = 0;
        if (!SetCommTimeouts(nComID, &comm_timeout)) {
                return -1;
        }

        if (ThreadHdl == NULL) {
                ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
                                        this, CREATE_SUSPENDED, &ThreadID);
                if (ThreadHdl == NULL) {
                        return -1;
                }
                ResumeThread(ThreadHdl);
        }

        return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
        DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
        DWORD dwError;
        COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
        BOOL bRet;
        int nReadCnt; // bytes received(return value of ReadComPort())

        bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

        while (TRUE) {
                        bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
                        if (!fContinue) {
                                break;
                        }
                        ClearCommError(nComID, &dwError, &ComStat);
                        if (!bRet) {
                                PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
                                continue;
                        }
                }

                if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
                        //error-handling
                        continue;
                }

                if (ComStat.cbInQue > 0) { // check existence of receive data
                        ReadComPort(nComID, byBuffer, 1024);
                        //data-handling
                }
        }

        return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
        DWORD dwError;
        COMSTAT comstat;

        BOOL bContinue = TRUE;
        DWORD dwBytesRead = 0;
        BOOL rc = 0;

        read_os.Offset = 0;

        rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
        if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
                if (WaitForSingleObject(read_os.hEvent, 1000)) {
                        dwBytesRead = 0;
                } else {
                        rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
                        if (rc) {
                                read_os.Offset = dwBytesRead;
                        }
                }
        } else {
                read_os.Offset = dwBytesRead;
        }

        if (rc) {
                return read_os.Offset;
        } else {
                // error handling
                PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
                ClearCommError(nComID, &dwError, &comstat);
                return -1;
        }
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
        DWORD dwError;
        COMSTAT comstat;
        DWORD dwBytesWritten = 0;
        BOOL rc = 0;

        write_os.Offset = 0;
                                                                                                                                
        rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
        if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
                if (WaitForSingleObject(write_os.hEvent, 1000)) {
                        dwBytesWritten = 0 ;
                } else {
                        rc = GetOverlappedResult( nComID,
                                                                                 &write_os,
                                                                                 &dwBytesWritten, FALSE);
                        if (rc) {
                                write_os.Offset = dwBytesWritten;
                        }
                }
        } else {
                write_os.Offset = dwBytesWritten;
        }

        if (rc) {
                return write_os.Offset;
        } else {
                // error handling
                PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
                ClearCommError(nComID, &dwError, &comstat);
                return -1;
        }
}

"Slobodan Brcin (eMVP)" wrote:

> Hi George,
>
> No matter what SetumComm settings that you use (default) serial driver should work.
> You have a logic error in your code regarding when you expect to get some data.
>
> Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few lines
> that you should try to explain to your-self, but doing that "aloud" ca usually help)
>
> Regards,
> Slobodan
>
> "George" <George@discussions.microsoft.com> wrote in message news:ED0FF924-CDD1-4952-80A4-9600242875A8@microsoft.com...
> > I tested with a simple application in a simple condition.
> > Connect 2 PCs with serial cable and run above application on both PC.
> >
> > Everything went well all around.
> > The data packet sent from 1 PC could be correctly received by another PC.
> > If some character data is reached to the system receive buffer,
> > WaitCommEvent is terminated and ReadFile correctly read buffer data.
> > According to this result, I think the receive data logic is not wrong.
> > Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
> > my appllication or device (or XP Embedded component configuration).
> >
> > By the way, I found the API SetupComm. Is this API necessary for our
> > application?
> >
> > "KM" wrote:
> >
> > > George,
> > >
> > > Somehow I seem to overlook your reply in this thread.
> > >
> > > > HasOverlappedIoCompleted returns FALSE.
> > >
> > > Yup. This is what we expected, right?
> > > It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.
> > >
> > > > By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
> > > > FALSE. Why?
> > >
> > > How about checking with GetLastError?
> > >
> > > > Any 2nd parameter of SetCommMask() results in the same.
> > >
> > > Please look at this MSDN sample code to see how it should work in a simple case:
> > > http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp
> > >
> > > Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro first
> and
> > > then move to XPe.
> > > As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.
> > >
> > > Regards,
> > > KM
> > >
> > > > "KM" wrote:
> > > >
> > > > > Just to add to that..
> > > > >
> > > > > George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding I/O
> > > > > operation.
> > > > >
> > > > > --
> > > > > Regards,
> > > > > KM, BSquare Corp.
> > > > >
> > > > >
> > > > > > Hi George,
> > > > > >
> > > > > > One basic question do you know how overlapped operation are working?
> > > > > >
> > > > > > You should choose between one of two following syntaxes.
> > > > > > > ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
> > > > > > > ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.
> > > > > >
> > > > > > Using both values with overlapped access does not make sense since all operations will return immediately and set
> BytesRead to
> > > 0
> > > > > or
> > > > > > some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
> you
> > > use.
> > > > > But
> > > > > > this length info is usually 0 (treat is as undefined).
> > > > > >
> > > > > > Length info is filled only during the IO API call not later.
> > > > > > So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use API
> > > > > functions
> > > > > > like GetOverlappedResult.
> > > > > >
> > > > > > Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different read
> and
> > > > > write
> > > > > > operations on different handles and still execute some other code while drivers and hardware gather your data.
> > > > > >
> > > > > > Regards,
> > > > > > Slobodan
> > > > > >
> > > > > >
> > > > > > "George" <George@discussions.microsoft.com> wrote in message news:6D476082-1612-4DF9-8B16-7558DEDE77C1@microsoft.com...
> > > > > > > Depend on queue status? What's that?
> > > > > > >
> > > > > > > Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
> > > > > > > difference.
> > > > > > > GetOverlappedResult() returns successfully but "BytesRead" is always 0.
> > > > > > >
> > > > > > >
> > > > > > > "Slobodan Brcin (eMVP)" wrote:
> > > > > > >
> > > > > > > > Hi George,
> > > > > > > >
> > > > > > > > > I have not tested another OS than Windows XP Embedded.
> > > > > > > > > Does OS matter about this phenomenon?
> > > > > > > >
> > > > > > > > Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK related
> > > would
> > > > > be
> > > > > > > > better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe then
> this
> > > is
> > > > > NG
> > > > > > to
> > > > > > > > ask for help.
> > > > > > > >
> > > > > > > > > OK I'll try to make test program without sub-thread and set timeout properly.
> > > > > > > > >
> > > > > > > > > R/W file operation is simple as below. This operation is done after (10)'s
> > > > > > > > > check.
> > > > > > > > > ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
> > > > > > > > > WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);
> > > > > > > >
> > > > > > > > With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be most
> > > likely
> > > > > 0
> > > > > > > > (depending on queue status).
> > > > > > > >
> > > > > > > > > Wait for completion of overlapped operaion.
> > > > > > > > > GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);
> > > > > > > >
> > > > > > > > Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after both
> > > read
> > > > > and
> > > > > > > > write operations. Ase last parameter as TRUE for test cases.
> > > > > > > >
> > > > > > > > > Check if "BytesWritten" is over zero, and application specific process.
> > > > > > > > >
> > > > > > > > > I also tried without using WaitCommEvent but only ReadFile within eternal
> > > > > > > > > while loop, but the result was same. No data could be read.
> > > > > > > > >
> > > > > > > > > What is wrong?
> > > > > > > >
> > > > > > > > Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).
> > > > > > > >
> > > > > > > > > BIOS level setting?
> > > > > > > > NO. Has nothing to do with this.
> > > > > > > > > OS setting?
> > > > > > > > NO, since you configure DCB, timeouts etc.
> > > > > > > >
> > > > > > > > > Shortage of pre-configuration in my application?
> > > > > > > > NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)
> > > > > > > >
> > > > > > > > Regards,
> > > > > > > > Slobodan
> > > > > > > >
> > > > > > > >
> > > > > > > > > "Slobodan Brcin (eMVP)" wrote:
> > > > > > > > >
> > > > > > > > > > Hi George,
> > > > > > > > > >
> > > > > > > > > > Does this work on XP Pro?
> > > > > > > > > >
> > > > > > > > > > Why do you create new thread for simple test? Simplify your test case.
> > > > > > > > > > Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
> > > requested by
> > > > > > read
> > > > > > > > > > operation).
> > > > > > > > > > Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
> for
> > > them
> > > > > > > > especially
> > > > > > > > > > since you use overlapped access).
> > > > > > > > > > Where are read and write file in your example?
> > > > > > > > > >
> > > > > > > > > > Regards,
> > > > > > > > > > Slobodan
> > > > > > > > > >
> > > > > > > > > > "George" <George@discussions.microsoft.com> wrote in message
> > > news:B19BE148-3CEC-482A-A7D3-8D858DA475FC@microsoft.com...
> > > > > > > > > > > Hi.
> > > > > > > > > > > Please give me some advise.
> > > > > > > > > > > I want to communicate with a device via COM port and coded typical
> > > > > > > > > > > communication program using Windows SDK.
> > > > > > > > > > >
> > > > > > > > > > > The program sequence is thus...
> > > > > > > > > > > (1) CreateFile with overlap mode.
> > > > > > > > > > > ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
> > > > > > > > > > > OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
> > > > > > > > > > >
> > > > > > > > > > > (2) BuildCommDCB
> > > > > > > > > > > BuildCommDCB("COM1",&dcb);
> > > > > > > > > > >
> > > > > > > > > > > (3) SetCommState with some parameter set by the value the device requires
> > > > > > > > > > > and others by default.
> > > > > > > > > > > SetCommState(ComID, &dcb);
> > > > > > > > > > >
> > > > > > > > > > > (4) SetCommTimeouts with no timeout.
> > > > > > > > > > > SetCommTimeouts(ComID, &comm_timeout);
> > > > > > > > > > >
> > > > > > > > > > > (5) SetCommMask
> > > > > > > > > > > SetCommMask(ComID, EV_RXCHAR);
> > > > > > > > > > >
> > > > > > > > > > > (6) CreateThread.
> > > > > > > > > > >
> > > > > > > > > > > (7) In the thread created above, WaitCommEvent for a data sent from the
> > > > > > > > > > > device.
> > > > > > > > > > > WaitCommEvent(ComID, &EventMask, &event);
> > > > > > > > > > >
> > > > > > > > > > > (8) Wait until the overlapped operation complete.
> > > > > > > > > > > GetOverlappedResult(ComID, &event, &Transfer, TRUE);
> > > > > > > > > > >
> > > > > > > > > > > (9) Get error code and clear.
> > > > > > > > > > > ClearCommError(ComID, &Error, &ComStat);
> > > > > > > > > > >
> > > > > > > > > > > (10) Check the receive queue if some data is received.
> > > > > > > > > > >
> > > > > > > > > > > The problem is that function WaitCommEvent never return!
> > > > > > > > > > > Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
> > > > > > > > > > > but the loop never ended.
> > > > > > > > > > >
> > > > > > > > > > > I confirmed that the command from application to the device is correctly sent.
> > > > > > > > > > > And also confirmed by line monitor connected between the device and COM port
> > > > > > > > > > > that the device returns correct response for the command sent by my
> > > > > > > > > > > application.
> > > > > > > > > > > But why my application can't receive any data?
> > > > > > > > > > > Almost all the settings are set by general value.
> > > > > > > > > > >
> > > > > > > > > > > OS is Windows XP Embedded with almost full functionality configuration.
> > > > > > > > > > >
> > > > > > > > > > > Please help me. Thanks.
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > >
> > > > > >
> > > > >
> > > > >
> > > > >
> > >
> > >
> > >
>
>
>



Relevant Pages

  • Re: return from main
    ... alias) have been participating in comp.lang.c since February ... terminates the ... compatible with int, the ... The wordings are really confusing. ...
    (comp.lang.c)
  • Re: FastMove with XP SP2-DES enabled
    ... Version 2.3 can be found in the attachments ... The Program just terminates during ... while debugging i wasn't even able to check if SrcProc ...
    (borland.public.delphi.language.basm)
  • Re: reply the answer
    ... The closest thing I can find is C99 ... If the} that terminates a function is reached, ... int sily ... gcc will give a warning if poked hard enough, but with only the options to ensure full compliance to a C standard and no extra warnings it will produce no diagnostic. ...
    (comp.lang.c)
  • Re: return from main
    ... initial call to the main function is equivalent to calling the exit ... compatible with int, the ... terminates the main function returns a value of 0." ...
    (comp.lang.c)
  • Re: Main loop helper functions
    ... gamehack wrote: ... > which terminates the program. ... > int quit_application ... int success = EXIT_SUCCESS; ...
    (comp.lang.c)