Channels ▼

Al Williams

Dr. Dobb's Bloggers

Port of Call

February 10, 2012

A few weeks ago I mentioned how I've been looking for ways to incorporate USB into more of my projects. I've been looking at several "native" options. I also mentioned that there are several techniques for getting a virtual serial port either through a stock cable or building any of a variety of USB ports on the board (including one that fits in a 9-pin serial port socket).

If your application doesn’t demand anything more sophisticated than a serial port, a USB to serial converter really isn’t a bad option. Operating system support is widespread. The 9-pin adapter is a little pricey, but other chips and cables are inexpensive and readily available. You can also preserve any investment you already have in serial port-based software.

I had a project a few weeks ago that needed a large number of PWM channels controlled by some PC software. Since it is getting hard to find PCs with serial ports, I built a stock PIC board but replaced the 9-pin RS-232 connector with a USB adapter (the USB-DB9 from FTDI).

[Click image to view at full size]

That was easy, but then I needed software to communicate with the board itself. Lately I've been experimenting with the Qt framework (Qt now has preliminary support for Android, but that's a topic for another blog). Qt provides a lot of abstractions, but serial ports aren't among them.

On the other hand, I had some code from a serial-controlled I/O interface handy that has parallel implementations for Linux and Windows, so I thought that would make a good fit for Qt, which is adept at handling multiple platforms. I’ve never been one to pass up a chance to steal code (especially my own), so I pulled a copy from the existing project and set about converting to work for this one. On the other hand, maybe I should have borrowed the code at http://is.gd/l9UCzR or http://is.gd/991kuP, but I figured it was better to use code I'd used before.

The original project was a C program, but it was simple enough to convert to C++ in case I wanted to use a Qt facilities. The code was simple enough that renaming the source files did the trick. The code has three files: a header, a Linux source file, and a Windows source file. Obviously, you only build one of the source files. The header is the same in either case.

Here’s an excerpt from the header (you can find the entire project online here):

/** Open the GP3 serial port.
 *   @param port The name of the port (varies by platform, e.g., COM1, /dev/cua0, etc.)
 *   @return -1 for error
 */
int gp3openport(const char *port);  // returns -1 for error
/** Close the GP3 port.
 */
void gp3closeport();
/** Write a byte to the GP3.
 * This function blocks if the GP3 is not ready.
 * @param byte The byte to write
 * @return 1 for success
 */
int gp3write(int byte);   // returns 1 for success
/** Read a byte from the GP3.
 * This function blocks until a byte is received
 * @return Character or -1 in case of error
 */
unsigned int gp3read(void);  // returns character or -1 for error

Simple enough functions: open, read, write, and close. I was mainly concerned with the Linux side for this project, but I did bring both source files into the new project. The Linux side sounds like it should be deceptively simple, right? Open some file in /dev and read and write from it.

It isn't quite that simple. First, you have to open a serial port in a certain way.


 fd=open(lport,O_RDWR|O_NOCTTY|O_NDELAY);
  if (fd<0)
    {
      return -1;
    }

This opens the port for reading and writing and does not make the serial port into a controlling terminal (the O_NOCTTY flag). The O_NDELAY flag prevents some systems from waiting for a carrier detect line. The problem is, it also means reads and writes will return immediately. If you call a read, for example, and there's no data (yet) the call just returns and your program has to deal with that. If you don't mind just spinning and waiting, that's ok, but it makes it a lot harder to do smart things like time out.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video