• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 364
  • Last Modified:

Getting COM input in realtime

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
phervers
Asked:
phervers
2 Solutions
 
pherversAuthor Commented:
i didn't mention that i'm using dev-c++ for development.
0
 
grg99Commented:
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
 
pherversAuthor Commented:
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
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
jkrCommented:
>>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
 
mokuleCommented:
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
 
pherversAuthor Commented:
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
 
jkrCommented:
>>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
 
pherversAuthor Commented:
oh and one more thing is there any way to emulate data being sent by hardware, maybe connecting to stdin ???
0
 
jkrCommented:
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

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now