Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

First time opening COM port using CreateFile

490 views
Skip to first unread message

pedr...@gmail.com

unread,
Jan 26, 2008, 5:37:21 PM1/26/08
to
Hello all,
When I power up my PC and use my test application, which opens COM1
and reads a string of data (sent by a serial barcode reader), the
first time it just doesn't work.
If I close my application, call HyperTerminal application and open
COM1 (just open it), then close HyperTerminal, open my test
application, it starts working fine.
This looks like HyperTerminal is doing something else then my
application, in order to open the COM port.
I use this line of code:
m_hFile = ::CreateFile(m_csCommPortName, GENERIC_READ | GENERIC_WRITE,
0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

I don't have any error, but the application simply can't receive
anything from the COM port.
Someone has any ideas on where might be the problem?
Thanks in advance,
Pedro

Scott McPhillips [MVP]

unread,
Jan 26, 2008, 7:47:26 PM1/26/08
to
<pedr...@gmail.com> wrote in message
news:ee6d39ee-7268-4720...@q39g2000hsf.googlegroups.com...

> Hello all,
> When I power up my PC and use my test application, which opens COM1
> and reads a string of data (sent by a serial barcode reader), the
> first time it just doesn't work.
> If I close my application, call HyperTerminal application and open
> COM1 (just open it), then close HyperTerminal, open my test
> application, it starts working fine.
> This looks like HyperTerminal is doing something else then my
> application, in order to open the COM port.

There is no such thing as "just open it." HyperTerminal is also setting the
port's baud rate, number of data bits, parity mode, and perhaps flow
control. You have to set all of these things so the port matches the
settings being used by the barcode reader. At a minimum, after you open the
port do this:

DCD dcb;
dcb.DCBlength = sizeof(DCB);
GetCommState(m_hFile, &dcb);
dcb.BaudRate = ...
dcb.ByteSize = ...
dcb.Parity = ...
SetCommState(m_hFile, &dcb);

If these three parameters don't match the external device it can't work. In
simple cases the other DCB settings don't matter. You will probably also
need to call SetCommTimeouts to get ReadFile to return to you in a
reasonable period of time if there is no more input arriving.

--
Scott McPhillips [VC++ MVP]

Owen Ransen

unread,
Jan 27, 2008, 2:29:50 AM1/27/08
to
On Sat, 26 Jan 2008 14:37:21 -0800 (PST), pedr...@gmail.com wrote:

>I use this line of code:
>m_hFile = ::CreateFile(m_csCommPortName, GENERIC_READ | GENERIC_WRITE,
>0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

It is a long times since I used this code, but you might
find something useful in it (especially the TRACE statements
after GetCommState() :

char gszPort [_MAX_PATH+1] = "COM2" ;
HANDLE hComm;
hComm = CreateFile( gszPort,

GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,

0,// FILE_FLAG_OVERLAPPED,
0);

if (hComm == INVALID_HANDLE_VALUE) {
TRACE ("Could not open com2\n") ;
return (TRUE) ;
}


DCB Dcb ;
if (GetCommState (hComm,&Dcb)) {
TRACE ("Comm state got:\n") ;
TRACE ("Rate = %d\n",Dcb.BaudRate) ;
TRACE ("Binary = %d\n",Dcb.fBinary ) ;
} else {
TRACE ("Could not get com state") ;
return (TRUE) ;
}

unsigned long iNumBytesRead ;
char szMsgIn [_MAX_PATH+1] ;
do {
ReadFile (hComm,szMsgIn,1,&iNumBytesRead,NULL) ;
TRACE ("%c",szMsgIn[0]) ;
} while (szMsgIn[0] != '\n') ;


CloseHandle (hComm) ;
...


Easy to use graphics effects:
http://www.ransen.com/

pedr...@gmail.com

unread,
Jan 27, 2008, 5:48:39 PM1/27/08
to
Well in fact I do a little more than that, this is the complete code:

--------------------------------------------------------------------------------------------------------------------------------------------
if (m_hFile == 0)
{
//
// Initialize the overlapped structures
//

// Read event
InitOverlapped(m_overlappedRead);

// Write event
InitOverlapped(m_overlappedWrite);


//
// Open COM port
//

m_hFile = ::CreateFile(m_csCommPortName, GENERIC_READ |
GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

if (m_hFile == INVALID_HANDLE_VALUE)
{
CString csLastError = LogLastError(_T("Error opening COM port!"));

p_errCode.Set(ERRMSG_ERROR_OPENING_COM_PORT, CErrCode::high,
CErrCode::nonRecoverable, csLastError);

return false;
}


//
// Configure COM port with current object attributes
//

BOOL bRet = FALSE;
DCB dcb;

bRet = ::GetCommState(m_hFile, &dcb);
ASSERT(bRet == TRUE);

// Set the new data
dcb.BaudRate = m_wBaudRate;
dcb.ByteSize = m_ucByteSize;
dcb.Parity = m_ucParity;
dcb.StopBits = m_ucStopBits;
dcb.fDtrControl = 0;
dcb.fRtsControl = 0;

// Determine if parity is used
dcb.fParity = (dcb.Parity != NOPARITY);

// Set the new DCB structure
bRet = ::SetCommState(m_hFile, &dcb);
ASSERT(bRet == TRUE);

--------------------------------------------------------------------------------------------------------------------------------------------

I noticed that in one of the replies there were:
dcb.DCBlength = sizeof(DCB);
that I'm not doing... do I need this when I make a GetCommState() ?
Can it be the cause of my problems?

Ulrich Eckhardt

unread,
Jan 28, 2008, 4:54:53 AM1/28/08
to
pedr...@gmail.com wrote:
> m_hFile = ::CreateFile(m_csCommPortName, GENERIC_READ |
> GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
> if (m_hFile == INVALID_HANDLE_VALUE)
> {
> CString csLastError = LogLastError(_T("Error opening COM port!"));
>
> p_errCode.Set(ERRMSG_ERROR_OPENING_COM_PORT, CErrCode::high,
> CErrCode::nonRecoverable, csLastError);
>
> return false;
> }

Just one suggestion here: just throw an exception instea of doing all the
logging here and then only returning 'false' which doesn't give any hint
what actually went wrong.

> bRet = ::GetCommState(m_hFile, &dcb);
> ASSERT(bRet == TRUE);

[...]


> bRet = ::SetCommState(m_hFile, &dcb);
> ASSERT(bRet == TRUE);

Two things here:
1. Have you ever compared the settings after starting the computer with the
settings after starting hyperterm? Hint: type "mode com1" in a commandline
shell.
2. I personally wouldn't say that failure of GetCommState() is a
programmer's error, so I'd say that assertions are wrong here. Rather, just
throw an exception. ;)

> I noticed that in one of the replies there were:
> dcb.DCBlength = sizeof(DCB);
> that I'm not doing... do I need this when I make a GetCommState() ?

Yes, absolutely. This structure has been changed throughout the life of the
win32 API (or has been prepared to allow such changes). In order to remain
compatible, they only added fields and the implementation can detect
the 'version' from the size. This applies to all similar structures, too.


Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

Message has been deleted

pedr...@gmail.com

unread,
Jan 28, 2008, 3:34:35 PM1/28/08
to
Thank you for all your hints and help!
I'm back from work, didn't have the time to work on this today...
I'll check it out tomorrow and I'll let you know if I manage to solve
my problem.
Message has been deleted
Message has been deleted

pedr...@gmail.com

unread,
Jan 28, 2008, 4:18:29 PM1/28/08
to
humm...
I just tryed the "mode com1" with my home computer, one thing got my
attention, the line "Timeout: OFF" changed to "Timeout: ON" and I'm
not changing this configuration in my application so I guess it must
be it...!
I'll try it tomorrow at work.
Many thanks once again for you help!
0 new messages