Solved

Getting COM input in realtime

Posted on 2004-10-27
328 Views
Last Modified: 2012-08-13
Hi experts.

First thing i want to say is that English is not my natural language, but i hope You will understand what i mean.

I'm writing a piece of software that will be used to control a hardware device connected through COM port.
Computer can send commands and device send information but it can't be predicted when the informaton will be sent.

From what i've read i should use winAPI CreateFile function, but how do i know when new information is sent ???

I have to say that i haven't used winAPI before so a code sample to connect to COM port would be welcome.
0
Question by:phervers
    9 Comments
     
    LVL 1

    Author Comment

    by:phervers
    i didn't mention that i'm using dev-c++ for development.
    0
     
    LVL 22

    Expert Comment

    by:grg99
    COM port I/O is always a bit of a hassle.   Try google "msdn serial port I/o".  I found this good bit of info direct from msoft:

    http://tinyurl.com/8un6

    0
     
    LVL 1

    Author Comment

    by:phervers
    well maybe i should also mention that commands and info from hardware are simply series of ascii characters for example you send command "<fw>"  you get  info like "<w25>", commands might be more complicated but it's only series of ansii chars
    0
     
    LVL 86

    Accepted Solution

    by:
    >>how do i know when new information is sent ???

    'WaitCommEvent()' would be the API of choice, since it notifies your process whenever new data arrived at the port. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwbgen/html/msdn_serial.asp ("Serial Communications in Win32") and http://msdn.microsoft.com/library/en-us/devio/base/communications_events.asp ("Communications Events"). There's also a sample available at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/monitoring_communications_events.asp ("Monitoring Communications Events"):

    #include <windows.h>
    #include <assert.h>
    #include <stdio.h>

    void main( )
    {
        HANDLE hCom;
        OVERLAPPED o;
        BOOL fSuccess;
        DWORD dwEvtMask;

        hCom = CreateFile( "COM1",
            GENERIC_READ | GENERIC_WRITE,
            0,    // exclusive access
            NULL, // default security attributes
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL
            );

        if (hCom == INVALID_HANDLE_VALUE)
        {
            // Handle the error.
            printf("CreateFile failed with error %d.\n", GetLastError());
            return;
        }

        // Set the event mask.

        fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR);

        if (!fSuccess)
        {
            // Handle the error.
            printf("SetCommMask failed with error %d.\n", GetLastError());
            return;
        }

        // Create an event object for use by WaitCommEvent.

        o.hEvent = CreateEvent(
            NULL,   // default security attributes
            FALSE,  // auto reset event
            FALSE,  // not signaled
            NULL    // no name
                );
       

        // Intialize the rest of the OVERLAPPED structure to zero.
        o.Internal = 0;
        o.InternalHigh = 0;
        o.Offset = 0;
        o.OffsetHigh = 0;

        assert(o.hEvent);

        if (WaitCommEvent(hCom, &dwEvtMask, &o))
        {
            if (dwEvtMask & EV_DSR)
            {
                 // To do.
            }

            if (dwEvtMask & EV_CTS)
            {
                // To do.
            }
        }
        else
        {
            DWORD dwRet = GetLastError();
            if( ERROR_IO_PENDING == dwRet)
            {
                printf("I/O is pending...\n");

                // To do.
            }
            else
                printf("WaitCommEvent failed with error %d.\n", GetLastError());
        }
    }

    The main difference to yur scenario is that you'd wat for EV_RXCHAR.
    0
     
    LVL 17

    Assisted Solution

    by:mokule
    Hi,
    Important !
    After CreateFile You should set transmission parameters

        DCB dcbPort;
        COMMTIMEOUTS  tout;

        if( GetCommState(hCom, &dcbPort))
          {
          dcbPort.BaudRate = CBR_9600;
          dcbPort.ByteSize = 8;
          dcbPort.Parity =NOPARITY;
          dcbPort.StopBits = ONESTOPBIT;
          if(SetCommState(hCom, &dcbPort))
            {
    // optional sending and receiving bufor length
            SetupComm(hCom,2400,2400);      
    // setting timeouts may be helpfull
            GetCommTimeouts(hCom,&tout);
            SetCommTimeouts(hCom,&tout);
            }
          else
            {
    // error
            }

    ////////////////////////////////
    Another option to waiting for comm event may be polling received bytes using

    DWORD err;
    COMSTAT st;

    ClearCommError(hCom,&err,&st);

    in st.cbInQue You've got number of received bytes
    0
     
    LVL 1

    Author Comment

    by:phervers
    thanks to both of you i have another question: is that ok to put this event handling routine into loop like this:

    do
    {
        if (WaitCommEvent(hCom, &dwEvtMask, &o))
        {
            if (dwEvtMask & EV_RXCHAR)
            {
                // To do.
            }
        }
        else
        {
            running = false;
        }  
    }
    while(running);

    ofcourse this is simplified i'll want to add some more conditions on when to exit loop.

    I'm asking cause i haven't got the device yet and i need to write most of code before i get it so no testing available in difficult early stages :(
    0
     
    LVL 86

    Expert Comment

    by:jkr
    >>is that ok to put this event handling routine into loop

    Sure. Since 'WaitCommEvent()' will pause until an event occurs, the CPU won't be hogged up.
    0
     
    LVL 1

    Author Comment

    by:phervers
    oh and one more thing is there any way to emulate data being sent by hardware, maybe connecting to stdin ???
    0
     
    LVL 86

    Expert Comment

    by:jkr
    No, you'll need some device attached to the serial port. For that, you could e.g. connect two PCs using a null modem cable.
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Course: Foundations of Front-End Development

    Jump-start a lucrative career in front-end web development, with zero previous coding experience required. This course covers the basic programming concepts and languages required for creating engaging websites from scratch.

    Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
    Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
    The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
    The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

    933 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now