Channels ▼

Al Williams

Dr. Dobb's Bloggers

Cutie Serial

June 09, 2014

I've mentioned a few times how the ubiquitous serial port simply refuses to die. Granted, a lot of PCs don't have serial ports anymore, but many devices that connect via USB or Bluetooth still look like serial ports.

I still maintain a lot of code that talks to embedded systems via serial ports, and one major problem is how to abstract the serial port on different platforms. I have a simple module that covers my most common platforms, but honestly it isn't very general purpose and it is pretty bare bones of features.

I noticed that Qt 5.1 has a QSerialPort class that promised to make using the serial port easy on different platforms. I decided to check it out. After all, I generally like Qt if I have to develop GUI code. QtCreator is pleasant to work with outside of a few quirks and the class library is solid and well documented.

If you haven't used QtCreator before, you should try it. It is reminiscent of Visual Basic, but with a nicer backend. However, it does have a few surprises. For example, editing a project means editing a text file (in the GUI editor, though). Adding and deleting member functions requires you to jump from source file to header file (which is true if you aren't using an IDE, I suppose, but it would be nice if the tool took care of it for you).

I am running Kubuntu 14.04, so I already had Qt5 installed. I did not, however, have the serial port library installed. That was in the qtserialport5-dbg package. Depending on the platform you use, you may have to jump through different hoops to get Qt5.1 (or later; I used 5.2) and the library installed.

You have to add the library to the project as well. I created a "widget" project in QtCreator and then opened up the corresponding .pro file. There is a line that reads:


QT       += core gui 

and it should read:


QT       += core gui serialport

You could also add a new line, if you like that better:


QT       	+= core gui 
QT		+= serialport

After that, you are ready to go. You can add the QtSerialPort header to get definitions and autocompletion.

One problem with cross-platform serial code is identifying the port names that are available. I guess the Qt designers agreed, because they made that simple to do. The QSerialPortInfo class creates objects that hold information about a specific port. It also has a static function, AvailablePorts, which returns a QList of QSerialPortInfo objects.

The QSerialPortInfo objects have the things you'd expect: a port name and a file name, for example. But it also contains USB information, if the port is a USB serial port. That's very handy, because if you have a specific vendor ID for a serial chip, you can use that to find the right port regardless of the port name. You can find the online help for the object if you want to read more.

Armed with that list, it is pretty easy to populate a combo box. As step one of the program I wanted to write, I decided to just set up a combo box and then display the information for the port. You can find the entire program online and see it in operation in the figure below.

Here's the code in the main window constructor that fills in the combo box:


MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
// initialize list of serial ports
   ports=QSerialPortInfo::availablePorts();
// fill in combo box
   for (int i=0;i<ports.length();i++)
   {
       ui->comport->addItem(ports[i].portName(),QVariant(i));
   }

}

I stored the index in the data part of the combo box (after converting it to a QVariant). That way even if you sort the combo box later, the entries would still be correct. The ports QList is a member of the class, so once it is filled it, the rest of the program can use it as needed.

Here's the slot code for combo box being selected:


void MainWindow::on_comport_currentIndexChanged(int index)
{
   QString out;
   // get selected index
   int sel=ui->comport->currentData().toInt();
// build up HTML info string in out
   out="<h1>Serial Port Info</h1>";
   ui->output->clear();
   out+=ports[sel].portName()+" "+ports[sel].description()+"<br>";
   out+=ports[sel].systemLocation()+"<br>";
   if (ports[sel].hasVendorIdentifier()&& ports[sel].hasProductIdentifier())
      out+=ports[sel].manufacturer()+" ("+ QString::number(ports[sel].vendorIdentifier(),16) + ":" + QString::number(ports[sel].productIdentifier(),16) + ")";
   // and put it on the screen
   ui->output->setText(out);
}

That looks like a bit of code, but really it just gets the index from the combo box, builds a QString with the data provided, and then sends it to the read-only text box.

As you can see in the figure, all the port information is there and you are ready to open the port and actually talk to something. How do you do that? I'll show you next time.

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