FoggyLog

Sun May 30th 2004 12:00:14: Reading and Writing to Serial Port in C++

Here is how to read and write to a PC's serial port in MS Visual C++. This code was written with help from the source code of Serialterm, which is also a great help when debugging PIC hardware.

// SensorWebPC.cpp
// Pass the port name in the command line - e.g. sensorwebpc comm2

#include "stdafx.h"
#include <windows.h>

void PrintError( LPCSTR str)
{
LPVOID lpMessageBuffer;
int error = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &lpMessageBuffer,
0,
NULL
);
printf("%s: (%d) %s\n\n",str,error,lpMessageBuffer);
LocalFree( lpMessageBuffer );
}

int main(int argc, char* argv[])
{
// open port for I/O
HANDLE h = CreateFile(argv[1],
GENERIC_READ|GENERIC_WRITE,
0,NULL,
OPEN_EXISTING,0,NULL);

if(h == INVALID_HANDLE_VALUE) {
PrintError("E012_Failed to open port");
} else {
// set timeouts
COMMTIMEOUTS cto = { 1, 100, 1000, 0, 0 };
DCB dcb;
if(!SetCommTimeouts(h,&cto))
PrintError("E013_SetCommTimeouts failed");

// set DCB
memset(&dcb,0,sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = 19200;
dcb.fBinary = 1;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
// dcb.fOutxCtsFlow = 1;
// dcb.fRtsControl = DTR_CONTROL_HANDSHAKE;

dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;

if(!SetCommState(h,&dcb))
PrintError("E014_SetCommState failed");

char buf[7];
DWORD read = 0;
DWORD write=1; // Number of bytes to write to serial port
buf[0] = 72; // Decmial value to write to serial port
WriteFile(h,buf,write,&write,NULL); // write is updated with the number of bytes written

ReadFile(h,buf,sizeof(buf),&read,NULL); // read is updated with the number of bytes read
DWORD i;
for (i=0; i<read; i++)
printf("%i ", (unsigned char)buf[i]);

CloseHandle(h);
}

return 0;
}

I've played with the timeouts to suit my needs, however details of what the parts of the "COMMTIMEOUTS" structure mean can be found here

 

I had already looked at the serialterm code but I was having trouble understanding it. This piece of code has been helpful understanding serial communication. Thanks

Comment by Sergio Roche at 4:37 on Sun 12 November 2006

I am writing a program to send data and receive data from a serial port on a dos machine for a simulator for Rhino XR3 simulator. The pascal code I was given looks like this...

const

P: integer = $3f8; {com1}

can you tell me how to change that line to C++ code so that I can query the simulator for an error code (integer) and receive that info? The query will be sent in ASCII (like a ? or 'an' etc.)

Thanks.

Comment by JR at 20:43 on Sat 31 March 2007

could u tell me what the equavalent c++ code for the above visual c++ code. i mean what is the code of serial port programing in c++

Comment by Ephrem Desta at 17:56 on Sun 29 April 2007

JR / Ephrem Desta - Sorry - I can't answer either of your questions.

Gary

Comment by Gary at 20:43 on Mon 30 April 2007

I get error: In CreateFile: 32 when trying to open com3 using c++ code(my own) which previously worked. Nothing in code has changed. Using heperterminal i can open the modem and issue commands and detect dtmf tones. However, in hyperterminal I can oly open the modem as it's vendor name, not from the com port that it is attatched to. What is causing this problem. In code I can only use com1,2 or 3, not the modem name itself. Please help.

Comment by help at 0:46 on Thu 28 June 2007

How can I read from serial port and write into a .txt file? (in Borland C..)

Comment by R.T. at 11:20 on Tue 6 November 2007

Where can I find the "stdafx.h" file????

Thanx a lot!

Comment by Mauricio Arias at 12:12 on Tue 13 November 2007

hi,

iam trying to establishing peer-peer network communication in vc++.iam also trying to reading and writing data from & to the serialport in vc++.but iam getting error E012_Failed to open port:<3> The system cannot find the path specified by using the above code.pls tell me how to overcome it as early as possible.pls.........

Comment by pranitha at 12:19 on Tue 8 January 2008

E012_Failed to open port <3> D

dont know why

pls help

Comment by Me at 9:23 on Thu 31 January 2008

Cannot open COM port "831473" Please help!

Also the file stdafx.h cannot be found. Please help!

Can you help me?

Thanks in advance!

Comment by egon at 15:30 on Mon 10 March 2008

Thanks a million for the code very helpful.

However i do get this error.

error C2664: 'CreateFileW' : cannot convert parameter 1 from 'char *' to 'LPCWSTR'

Any ideas? Thanks

Comment by simon at 10:31 on Mon 31 March 2008

To egon:

i got the same problem as you, but i solved by chosing a Precompiled header i application settings when i create a new project. I'm using visual studio 2005 as compiler and for me that solved the problem. If you want some knowledge about stdafx.h read http://en.wikipedia.org/wiki/Precompiled_header .

However i get the same error as simon "error C2664: 'CreateFileW' : cannot convert parameter 1 from 'char *' to 'LPCWSTR'"... anyone knows why?

Comment by David at 9:24 on Fri 4 April 2008

simon and egon:

to get rid of "char* to LPCWSTR" conversion errors, simply add

#undef UNICODE

on top of your code.

Comment by robin at 1:41 on Sun 6 April 2008

I got the same problem with simon & david.

I just simply add #undef UNICODE as robin mentioned.

But nothing is change. the problem still there.

Btw, where is actually this "UNICODE" defined?

Comment by Harris at 2:34 on Mon 26 May 2008

I found where is UNICODE exactly defined and added #undef UNICODE on top of WinBase header file. The problem dissapeared but another problem popout.

error C2664: 'FormatMessageA' : cannot convert parameter 5 from 'LPTSTR' to 'LPSTR'

Why?

Comment by Harris at 3:06 on Mon 26 May 2008

Thanks!! Was having one hell of a time opening up a

USB com-port until I found your code. It was a life

saver and ran first time with NO problems.

L Piovano

Comment by L Piovano at 0:37 on Sat 14 June 2008

Works great thanks! To get past the 'LPTSTR' conversion just use:

int _tmain(int argc, _TCHAR* argv[]) // Visual Studio 2005

instead of

int main(int argc, char* argv[])

Regards

Comment by Roderick Mooi at 8:51 on Thu 17 July 2008

I have a problem, this code and serialterm can't open virtual serial ports. ¿how can we do this?

Comment by Armando at 5:08 on Sun 3 August 2008

Hello, Im trying to use this code, but i have some doubts. Is this code for SERIAL port? or for USB port?, because im trying to send data from one PC to another by the SERIAL port with DB9 connectors.

Thank You!

Comment by Alfredo at 20:13 on Wed 12 November 2008

Hi Alfredo,

It's for a DB9 serial port...

Gary

Comment by Gary at 20:19 on Wed 12 November 2008

Thank you for replying, please can you help me?, Im trying to use this code to send data from a PC to another but it doesn´t work, in the command line im writing: sensorwebpc com1, and then nothing happens, I understand that this code is for sending and for reading, so im executing this code in both computers, but do i have to execute it in a special way or something? because nothing happens, not even errors appear on the screen, it only display a blank line and then appear again C:\, please help me.

Thank you!

Comment by Alfredo at 1:40 on Thu 13 November 2008

Thx.

This was helpful.

Comment by Chobicus at 15:05 on Tue 2 December 2008

Hi anyone know where do i type the command line for Visual studio 2005?

Is this in Configuration properties in Linker...command line then type in additional options ..sensorwebpc comm2? thanks guys

Comment by joe at 18:35 on Sun 7 December 2008

I have used _outp in one of my programs for serial comm. the program compiled and linked in VC++ 6 with no errors but did not run. Any ideas?

Comment by rajesh at 8:05 on Sun 11 January 2009

thanks a lot.

your source code is of great help - I am trying to address an USB device

Comment by Hans-Juergen at 15:25 on Fri 23 January 2009

Can you tell me how to change the Com port number? I want to choose Com3

Thank you

Comment by Adi at 10:36 on Wed 27 May 2009

The com number is passed in on the command line... e.g. "sensorweb com3".

Gary

Comment by Gary at 10:39 on Wed 27 May 2009

Thanks Gary - good simple help on the basics of serial comms. Sorry you have to put up with the clueless 3rd world people asking you to tell them how to do their job. Talk about resourceless - no wonder these people live in countries that look like dumps.

Comment by pete at 4:44 on Sun 31 May 2009

Oh one other thing: your exam paper PDFs took me back in time with that university mathsy typography - what was it called....ahh that's write it was done in LaTex. The stats people in Economics used it years ago when I was there, came back to uni to do medicine and the public health stats people were STILL using it! Funny how a font and a layout can take you back again - I think they loved the mechanistic way you 'programmed' complex formulae in with all the maths character sets.

Comment by pete in Australia at 5:28 on Sun 31 May 2009

Hi Everyone, do you know how to enable this C++ code to make sure that the serial port is read?

I get this error: E012_Failed to open port <3> T

How do u make sure you open the port? I've already connect it to my device which can be run by hyper terminal.

Would appreciate any of your help

Comment by Ethon at 3:41 on Fri 13 November 2009

Ethon: I got the same error,E012_Failed to open port

My problem was that I was using COM port number greater than or equal to 10 e.g. COM31

In this case you should write the com port as "////.//COM31" instead of "COM31".

check the msdn for CreateFile.

Comment by anusha at 15:23 on Wed 24 March 2010

i am trying to adress a modem using the code but the AT command i write using the Writefile function is not being executed. what might be the problem or how can u be sure the device actually receives the command.urgent please. thanks

Comment by stanley at 9:06 on Tue 30 March 2010

Nice clean and understandable code. Thanks for sharing. I replaced '#include "stdafx.h"' with '#include <stdio.h>' and was able to compile it in dev-c++.

Comment by Daniel at 18:17 on Tue 4 May 2010

Hi,

I work for Newcastle University as a programmer on a 'charity' project called SiDE. This example was very useful. The web is short of 'simple' examples without layers of code straying from the context of what it is!

Any chance you can detail the argv for other people. You mention "comm3" but I suspect this won't open a valid file handle.

"com2" for example might.

nice example though. :)

Comment by Gavin Wood at 14:37 on Sat 19 June 2010

Works fine in Visual Studio 2008!

I started a new 'Win32 Console Application' project, which automatically takes care of the stdafx.h precompiled header and copy pasted your code over the automatically generated code in my cpp file.

Then, as Roderick Mooi suggested I changed the int main... into int _tmain(int argc, _TCHAR* argv[])

then I used 'COM4' as the argument.

(hint: you can set the argument as a project property, see Configuration Properties - Debugging - Command Arguments, in Visual Studio, this way you can see it work while you step through it in debug mode)

(hint2: you can search for a valid argument using the device manager in Windows: Control Panel - System - Device Manager - Ports (COM & LPT). Check for any ports listed in there.

Anyway, great example, thanks!

Comment by Bart at 21:40 on Fri 9 July 2010

One of the few things i've tried that's actually managed to compile. However I either just get E12 port failed to open or I get multiple memory errors when I try to pass COM1 to the argument. (I think I may be doing this wrong)

How do I make it work?!

Comment by Aidan at 10:28 on Fri 23 July 2010

Hi

I used a similar code as lcc-MEX-Matlab 2007 32bit which worked always fine.

With Visual C++-MEX Matlab 2010 64 bit now I always get E012_Failed to open port: (2) The system cannot find the file specified.

Why could that be?

Hope somebody can answer this, kernel.

Comment by kernel at 8:52 on Fri 17 September 2010

Thanks, Dude - that saved me a pile of time.

I owe you a beer.

Matt

Comment by Matthew Gaunt at 19:25 on Mon 25 October 2010

I have used your program.In high baud rate such as 115200 with no handshaking ,serial buffer looses some data.

I have set its event to EV_TXEMPTY and EV_RXCHAR .but the problem has remained yet.

Comment by zahra babaei at 8:54 on Sat 12 March 2011

Hey people... question here

to run code like this, do i need to have connected a serial device onto my serial port in order for it to work, or should the code work regardless?... And if i do, do i need to write commands specific to that device or does random text suffice?

Comment by john at 10:50 on Thu 24 March 2011

The program compiles fine, but i get this error while it is running,

Unhandled exception at 0x003c155f in Test4.exe: 0xC0000005: Access violation reading location 0x0d918280.

the aarrow breaks right at the second NULL

HANDLE h = CreateFile(argv[('COM2')],

GENERIC_READ|GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_FLAG_OVERLAPPED,

NULL); //here

Any ideas what could cause this? I am running windows 7 64 bit, using microsoft visual studio 8

Comment by Mike at 16:01 on Thu 31 March 2011

sir,

i have been asked to do serial port programming using C++

it should include opening port, close and view the status of the serial port. You should also be able to control speed, timeout,start bit,stop bit,parity bit and stuff like that

will i b able to use ur code to meet my requirements?

regards

Comment by mayuri at 5:41 on Tue 19 April 2011

hey ppl,

i am able to compile the code but

I get this error: E012_Failed to open port <3>

pls provide me some solution..i hav been stuck in dis

Comment by mayuri at 6:51 on Wed 20 April 2011

Try using this:

HANDLE h = CreateFileA( "COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);

you can change "COM1" to any com port you want, as long as it's listend in Device Manager in Ports(COM & LPT)

If you don't use a specified port , you'll get that error!

Comment by Mike at 19:39 on Mon 16 May 2011

Hai guys!!

I am copied this code and tried to compile in VC++. I am using USB to Serial converter for my laptop. The program is fine. It compiled well without errors. But when I am running the program its giving an error.

"A problem caused the program to stop working correctly. windows will close the program and notify you if a soulution is available."

and then it is asking press any key to continue.......

donno whats wrong I have done.

Can anyone solve my problem??

Thank you.

------Seshu.

Comment by Seshu at 15:02 on Mon 15 August 2011

Thank-you for posting this. I had a much uglier looking code I was using before I found this. I am having some trouble still though, and I assume it is due to something I'm doing wrong in my modifications to this code. I'm trying to modify it to send "{0x02}1?8E{0x03}" through the serial port. Could anyone offer some simple suggestions for how to achieve this? I've been trying to figure this out for months!

Thank-you.

Comment by Shawn at 20:29 on Fri 6 July 2012

Add New Comment

Name:
Email:
(Never displayed publically)
Comment:
HTML Tags allowed - <b>bold</b>, <i>italic</i> and <a href="http://...">Links</a>
Type "NoSpam" in Here:

 

<< Back