Communications - Ariel.International

Referencing serial ports in Arduino IDE

Category: Communications
Published: Sunday, 05 June 2016
Written by Administrator

Arduino-based MCUs have usually more than one serial port available.

These are named in <HardwareSerial.h> as Serial, Serial1, ... , Serialx.

Normally, when a simple serial output is needed, the selected port is directly named in the setup loop:

Serial.begin(baudrate);

This is the simplest form, but also the least flexible, because in case of a port change it requires processing the whole program source.

To make programs more solid it is possible to reference serial ports in a number of ways, allowing to switch between them with a single change at compile time or even by a variable at execution time.

 

HM-11 Bluetooth 4.0 BLE Serial Module Board

HM-11

Product Details

9,90 €
EU982665
In stock 1000

USB To RS485 TTL Serial Converter Adapter FTDI Interface FT232RL 75176

USB486

Product Details

9,90 €
EU961537
In stock 1000

Compile Time port selection

The simplest way to control serial output is to use a pre-processor statement.

These are lines of code preceeded by a hashtag "#" which influence the behavior of arduino IDE compiler.

Some popular preprocessor statements are:

#include - to include a library in the source code
#define - to define a mnemonic label to be replaced by a value throughtout the source code

It is possible to utilize a #define directive to give a name to the serial port function, ie.:

#define mnemonic_name Port

(please note, no semicolon at the end of #directives!)

So if we put such directive in the first line of our code, ie.:

#define debugPort Serial1

in the following code we will be able to write:

debugPort.begin(baudrate);
debugPort.print("Hello!");

This allows the modification of the output port by a single line of code.

In the case of a system with more than one serial port, it is possible to define these and switch them around AT COMPILE TIME.

#define gpsPort Serial1
#define debugPort Serial

Execution Time port selection

Switching port selection at execution time, based on a variable or other condition, is a totally different story.

For this we need to create a variable which holds a pointer to the serial port.

We are not getting here in a deep explanation of pointers and reference, otherwise we would miss our simpler objective.

Anyhow, all you need to know is that you can create a variable that holds a reference to another variable or object, called pointer, so that this reference can be set and modified at execution time.

The first question you should ask yourself is: what type of variable do I need to hold such reference?

The simple answer is: one of the type of the object to be contained.

In our case we are talking about serial ports, the definition of which is explained in a system library named "HardwareSerial".

So the first thing you have to do is include that library in your source code:

#include "HardwareSerial.h"

Now you have your object type available, so you can define your variable, which is of type HardwareSerial:

HardwareSerial *sPort;

This definition is put outside any routine, so that it is a global definition valid throughout your code.

Please notice the asterisk (*) in front of the variable name, which means that this is not a variable of type HardwareSerial, but rather a pointer to an object of type HardwareSerial.

I am trying to be very plain here, in order to avoid confusion.

Then in setup() you can check for a flag or a variable to decide which port should be set:

void setup() {
bool swP = true;

if (swP)
    sPort = &Serial;
else
    sPort = &Serial1;
}

Now notice the "&" sign in front of the serial port name.

This is the complement of the (*) sign above and it means: store a reference to this object in the pointer variable.

Having done this, you can reference your object with all familiar methods like begin(), write() or print().

The only detail is that in this case the referencing symbol is not a dot (.) but a arrow (->).

So you will write :

sPort->begin(115200);
sPort->print("Hello!");

This is due to the complex world of syntax, in which we do not want to enter at this point.

It is actually possible to reference by a dot, but due to complex reasons which would be very clear when understood, it is not possible to do it globally but only locally.

What does that mean?

That you can always create a reference to your object inside a routine at execution time and load it with your pointer, so you can use it with a dot instead of an arrow.

Just wirte:

void loop() {
HardwareSerial& port = *sPort;
port.println("Hello!");
}

Once again, look at the "&" symbol meaning "reference of" and the "*" symbol meaning "pointer to".

Anyhow I find it useless and confusing, because I tend to forget what I did program earlier. The arrow rings a bell to the referencing of objects and tells me there is something there to be careful of.

So here is all there is to this matter. Hope this is useful to someone.

 

CP2102 Micro USB to UART TTL Module 6Pin Serial Converter STC Replace FT232

CP2102

Product Details

6,00 €
EU10026357
In stock 0

HC-12 433 SI4463 Wireless Serial Module Remote 1000M With Antenna

HC-12

Product Details

12,90 €
EU973522
In stock 1000

A complete example follows:

#include "HardwareSerial.h"

HardwareSerial *sPort;
byte b = 5;

void setup() {

  bool swP = true;

  if (swP)
      sPort = &Serial;
  else
      sPort = &Serial1;

  sPort->begin(115200);
  }

void loop()
  {
  HardwareSerial& port = *sPort;
  port.println(b++,HEX);
  delay(1000);
  }

 

Log in to comment