Click here to Skip to main content
15,889,992 members
Articles / Mobile Apps
Article

Simple Serial Communication

Rate me:
Please Sign up or sign in to vote.
4.09/5 (13 votes)
24 Jun 20033 min read 195.1K   9K   75   18
A C++ class to allow simple serial communication in Win32 platforms

Introduction

This is a proposal for a C++ class to handle simple serial communications, which means send and receive some bytes, and control the state of serial communication signals. In many cases, what one needs is to be able to communicate by a serial port to certain devices or electronic circuits. As simplicity is the main goal in this class, it is developed for synchronous read and write operation instead of overlapped ones and also assuming that there is no hardware (or software) flow control so the communications signals can be freely controlled. If you need an event driven serial communication (overlapped read/write, signals changes controlled by even, etc.) you can look in this site for the article Serial communication for Win32 with modem support By thierrydollar

Using the code

To use the class CSerialPort you must call CSerialPort::Open then does read or write operation, set or test the state of communications signals and closes the port once finished (not mandatory because the destructor does it). The read and write methods make no assumption about type and format of data send or received, you must take into account if you are handling a character or binary format, if there is Unicode, mbcs, etc. The open function if defined as follows:

virtual BOOL Open(LPCTSTR PortName, DWORD BaudRate, BYTE ByteSize, <BR>  BYTE Parity, BYTE StopBits,
  DWORD DesiredAccess = GENERIC_READ|GENERIC_WRITE);

There is no assumption about communication parameters because they are specific to each serial communication and must be known in order to establish a successful communication. Even, if the most frequent name of serial ports are “COM1:” to “COM4:”, there can be more than 4 serial ports in a machine and the serial driver is not forced to follow the “COMxx” name convention so a serial port can have any name in Win32 platforms. It would be a good idea to have a static function to obtain the names of installed serial ports but, as far as I know, there is not a documented way to do that. There is a simple way to know about installed ports: assuming that ports names follow the “COMxx:” convention they try to open all possible ports and if there is an error and GetLastError() returns ERROR_FILE_NOT_FOUND then the port isn’t installed. There is another way to know installed ports names and it is searching in registry but it is undocumented and platform depend.

With article there is a simple sample of using the mentioned class, the example is a program that reads bar codes from a serial bar code reader. Normally bar code readers send the read bar code ended by carriage return and line feed characters (this can be configured and even could be different for specific manufacturer) and the code is an ASCII string. There is a class (CBarCodeReader ) derived from CSerialPort that encapsulate the described protocol and its read method returns the read bar code (if any) directly in an string. There is not much more to say, the rest is in the code and it is simple (at least should be :-) )

Remarks

Remember that this is a simple instead of complete way of using serial devices. The proposed code can be used in Win32 Platforms and Windows CE versions. Pocket PC developers (I didn’t try others Windows CE versions) must take into account that manufacturers can have specific implementations of serial APIs (as other APIs). Even if it is true that such implementations must agree to Pocket PC implementation, I have found small differences from one device to another. For instance: in a Dell Axim Pocket PC device the signal CD must be externally supplied (the voltage present) in order to read or do any operation with serial port, there is no function errors if you try without that signal on, but you won’t obtain any result. I have tried the same in Compaq iPAQs and it is possible to read without any specific external signal on (as should be).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questioncan I connect serial port by 2 pc Pin
jhonutp5-Jun-08 18:41
jhonutp5-Jun-08 18:41 
Questioncontrolling a toy car Pin
fikree20-Mar-08 10:46
fikree20-Mar-08 10:46 
GeneralNeed help communicating with a Series F4s/D controller Pin
LoadSFSU28-Sep-06 15:35
LoadSFSU28-Sep-06 15:35 
QuestionXON/XOFF flow control issue Pin
Chitragar1-Nov-05 19:36
Chitragar1-Nov-05 19:36 
GeneralSimple Serial Communication Pin
vc-programmer-15-Sep-04 23:30
vc-programmer-15-Sep-04 23:30 
GeneralRe: Simple Serial Communication Pin
Idael Cardoso16-Sep-04 8:32
Idael Cardoso16-Sep-04 8:32 
QuestionCan make communication hang up in one case Pin
Simon66615-Sep-04 6:26
Simon66615-Sep-04 6:26 
AnswerRe: Can make communication hang up in one case Pin
Simon66616-Sep-04 7:59
Simon66616-Sep-04 7:59 
Generaldialog based application interaction Pin
moto muzphee5-Jun-04 23:42
moto muzphee5-Jun-04 23:42 
GeneralRe: dialog based application interaction Pin
A_Yakout6-Jun-04 1:42
A_Yakout6-Jun-04 1:42 
GeneralRe: dialog based application interaction Pin
Idael Cardoso6-Jun-04 9:24
Idael Cardoso6-Jun-04 9:24 
As you didn't give more details I assume that you are talking about MFC dialog based application. I also assume that you have some device from where you can read the revolution per minute of a motor using a RS-232 link.
In the code accompanying this article I include a MFC dialog based application as an example. The given app shows how to read information form a serial barcode reader. It queries the serial port for data at regular interval using a Windows timer. In the main dialog you can fin the following definitions:
CBarCodeReader m_BarCodeReader; 
// CBarCodeReader is a direct descendant of CSerialPort 
// You can use CSerialPort directly.
UINT m_Timer; //The timer value

The other step is adding in the OnInitDialog message handler the following line:
m_Timer = SetTimer(1, 300 /*Change according to your needs*/, 0);

Add a message handler for the message WM_TIMER and read the serial port in
the OnTimer message handler. In the test app I gave the OnTimer is as follows:
void CTestDlg::OnTimer(UINT nIDEvent) 
{
  //Check if there is any data in the serial port and save it in the variable 
  //m_BarCode (Cstring) that represent an edit box in the dialog. 
  if ( m_BarCodeReader.Read(m_BarCode) > 0 ) 
  {
    UpdateData(FALSE); //If something was read update the UI
    MessageBeep(MB_ICONASTERISK); //Sound a beep.
  }
  CDialog::OnTimer(nIDEvent);
}

The rest is open your port calling CSerialPort::Open or CBarCodeReader::Open depending on which one you used. You can do it in OnInitDialog message handler or in response to some button action (as in my demo app) or when your app logic requires it.
In your case if your device gives you the speed of the motor as an ASCII characters ended in the characters carriage return and line feed (as in the default configuration for many serial barcode readers) you can the explained code without many modifications. If the speed is given as ASCII but ended in other character or as a fixed length string then you can create (cut and paste) a class similar to CBarCodeReader and change the method Read according to your needs. But if your device give you the values as binary data or any non ASCII protocol then you must use CSerialPort directed and you OnTimer should like this:
void CTestDlg::OnTimer(UINT nIDEvent) 
{
  //m_SerialPort should be defined in your dialog class interface 
  //as CSerialPort m_SerialPort;
  BYTE buffer[255]; //Use any other method more appropriated to create the buffer
  DWORD read; 
  while ( (read = m_SerialPort.Read(buffer, sizeof(buffer))) > 0 ) 
  {
    //Process the buffer data here 
  }
  CDialog::OnTimer(nIDEvent);
}
Resuming:

  • You must declare in your dialog a variable of type CSerialPort.
  • In the OnInitDialog handler you must initialize the timer.
  • Add a WM_TIMER message handler to your dialog and in the OnTimer handler read the serial port data.
  • You must open the port in the OnInitDialog handler or any other.
The described method is suitable if you can check the port at determined time intervals. If you need to read the port immediately when some data arrives then you need to use some of the notification mechanism instead of this polling mechanism.

Regards,
Idael
GeneralRe: dialog based application interaction Pin
SimonDM7-Sep-04 6:07
SimonDM7-Sep-04 6:07 
GeneralRe: dialog based application interaction Pin
Idael Cardoso7-Sep-04 6:45
Idael Cardoso7-Sep-04 6:45 
GeneralRe: dialog based application interaction Pin
Simon6667-Sep-04 7:00
Simon6667-Sep-04 7:00 
GeneralRe: dialog based application interaction Pin
Idael Cardoso8-Sep-04 5:02
Idael Cardoso8-Sep-04 5:02 
QuestionHow to get serial ports from registry Pin
conrad Braam25-Sep-03 6:44
conrad Braam25-Sep-03 6:44 
GeneralRe: Cool article! Pin
Idael Cardoso25-Jun-03 23:28
Idael Cardoso25-Jun-03 23:28 
GeneralYeah, you are right Pin
wheregone25-Jun-03 14:30
wheregone25-Jun-03 14:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.