Channels ▼

Al Williams

Dr. Dobb's Bloggers

Cross Platform Serial

June 17, 2014

The object that represents the serial port in Qt is of class QSerialPort. There are several ways to construct one, but the easiest way is to simply pass the constructor a QSerialPortInfo object. That's handy, since the enumeration code sends you a list of those, one for each serial port on the system.

For the simple project I had in mind, I only needed to write to the serial port and it was sufficient to use the serial port in a blocking manner. However, in a GUI program, blocking for any length of time is a bad idea. It is especially bad to block on receive and have to wait for the serial device to send something before you can continue processing events.

One way around that, of course, is to do your serial I/O in a thread. However, the object does provide slots to notify you when data is available if you want to do asynchronous I/O without a separate thread.

Just to try things out, I decided to recycle the ARM project I talked about a few weeks ago. The code on the microcontroller reads an ASCII-formatted number from 0 to 100 and adjusts an RC servo to indicate the percentage. In other words, sending a 50 causes the servo to travel to its midpoint.

I extended the serial port enumeration program from last time to have a connect button. When you press it, the program connects to the selected port and changes the button to read disconnect. I added a tab named Control that contains a slider allowing you to adjust the servo position. The figures show both tabs of the application and you can download the entire project if you want to try it yourself.

Here's the code that opens the serial port:


// get selected port
        int sel=ui->comport->currentData().toInt();   
        ioport = new QSerialPort(ports[sel],this);     
// open for write
        if (ioport->open(QSerialPort::WriteOnly))
        {
// set parameters
           ioport->setBaudRate(QSerialPort::Baud57600);
           ioport->setFlowControl(QSerialPort::NoFlowControl);

// update UI
           ui->connectBtn->setText(tr("Disconnect"));
           ui->comport->setEnabled(false);
           ui->horizontalSlider->setEnabled(true);
// create stream
           iostream = new QTextStream(ioport);
// fake move the slider to where it is now
           on_horizontalSlider_valueChanged(
ui->horizontalSlider->value());
    ui->tabWidget->setCurrentIndex(1);  // switch tabs
 			}

I was a bit surprised that you have to set the serial parameters after you open the port. If you get it backwards, you'll get some runtime error messages. The serial port does have read and write methods, or you can attach it to a stream like I did here.

I wanted the servo to get set to the current position of the slider, so the last part of the code simulates the slider changing value. The Qt framework will call this same function when the slider actually moves. Here's the code that handles that signal:


void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    if (iostream) *iostream<<value << "\r" << flush;
}

The flush is necessary since QTextStream buffers data. For such a simple example, directly calling write might have been just as well.

I didn't test it, but presumably this same code will work on any supported Qt platform (as long as you are using Qt 5.1 or later). It is nice, too, that the object supplies access to things you might care about as an embedded developer. For example, setting the flow control or directly reading and setting hardware flow control pins.

Despite best efforts, the serial port won't die anytime soon. The Qt library is a great cross-platform way to write code on a host computer that can communicate with your embedded systems over that ubiquitous port.

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