You can use the serial communications interface to communicate with devices such as displays, sensors, and data acquisition systems.
The ConnectCore 8X provides access to three UART interfaces:
-
LPUART0 is routed to the expansion connector:
-
Rx: J27 pin 19
-
Tx: J27 pin 17
-
CTS: J27 pin 20
-
RTS: J27 pin 18
-
-
MCA UART0 is routed to the expansion connector:
-
Rx: MCA_IO9 - J20 pin 8
-
Tx: MCA_IO10 - J20 pin 9
-
CTS: MCA_IO5 - J20 pin 10
-
RTS: MCA_IO8 - J20 pin 7
-
-
MCA UART2 is routed to the XBee socket:
-
Rx: J12 pin 2
-
Tx: J12 pin 3
-
CTS: J13 pin 9
-
RTS: J13 pin 5
-
These three UART interfaces have hardware flow control lines (RTS and CTS).
See the ConnectCore 8X Hardware Reference Manual for information about the available serial ports.
Digi adds to Android an API to manage these serial port interfaces. With this API, you can perform common operations such as configuring the connection, sending and receiving data, etc. See the Digi APIx javadoc for a complete list of the available methods in this API.
Unless noted, all serial API methods require com.digi.android.permission.SERIAL
permission.
If your application does not have the *com.digi.android.permission.SERIAL permission it will not have access to any serial port service feature.
|
First, a new SerialPortManager
object must be instantiated by passing the Android Application Context.
import android.app.Activity;
import android.os.Bundle;
import com.digi.android.serial.SerialPortManager;
public class SerialPortSampleActivity extends Activity {
SerialPortManager serialPortManager;
[...]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Instantiate the Serial Port manager object.
serialPortManager= new SerialPortManager(this);
[...]
}
[...]
}
The serial port API allows you to:
Open/close a serial port
The SerialPortManager
allows you to create a SerialPort
object for a specific port name.
The listSerialPorts()
method lists all the available serial ports in the device.
You can also specify other serial port parameters using a SerialPortParameters
object or directly in the openSerialPort()
method.
Method | Description |
---|---|
|
Creates and opens a |
|
Creates and opens a |
|
Creates and opens a |
When they are not specified, the default serial port parameter values are:
-
Baud rate: 9600
-
Data bits: 8
-
Stop bits: 1
-
Parity: None
-
Flow control: None
-
Read timeout: 3 seconds
The |
The three methods that open the serial port may fail for the following reasons:
-
If the serial port name is invalid or does not exist, the
openSerialPort()
method throws aNoSuchPortException
. -
If the serial port is already in use by other application(s), the
openSerialPort()
method throws aPortInUseException
. -
If the serial port parameters are invalid, the
openSerialPort()
method throws aUnsupportedCommOperationException
.
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortManager;
import com.digi.android.serial.SerialPortParameters;
[...]
SerialPortManager serialPortManager = ...;
// Get the list of available serial ports.
String[] portNames = serialPortManager.listSerialPorts();
// Define a serial configuration: 115200/8/N/1 and hardware flow control.
SerialPortParameters params = new SerialPortParameters(
9600, /* baudrate: 9600 */
SerialPort.DATABITS_8, /* data bits: 8 */
SerialPort.STOPBITS_1, /* stop bits: 1 */
SerialPort.PARITY_NONE, /* parity: none */
SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT, /* flow ctrl: hardware */
2000 /* read timeout: 2s */);
// Open the available serial ports with the previous configuration.
SerialPorts[] ports = new SerialPorts[portNames.length];
for (int i = 0; i < portNames.length; i++)
ports[i] = serialPortManager.openSerialPort(portNames[i], params);
[...]
Once you have finished with a serial port, you must close it. This frees the port so that other applications can use it.
To close a serial port, use the close()
method of the SerialPort
object.
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortManager;
[...]
SerialPortManager serialPortManager = ...;
SerialPort port = ...;
[...]
// Close the serial port.
port.close();
[...]
Configure a serial port
Before sending and receiving data, the serial port must be configured.
You can set the configuration when opening a port, but the SerialPort
class also offers methods to get and change values once the port is opened:
Method | Description |
---|---|
|
Retrieves the serial port name. |
|
Retrieves the configured baud rate. |
|
Retrieves the configured number of data bits. |
|
Retrieves the configured number of stop bits. |
|
Retrieves the configured parity. |
|
Retrieves the configured flow control. |
|
Configures the serial port with the given values for baud rate, number of data bits, number of stop bits, parity, and flow control. |
The port configuration may fail if the given port parameters are invalid.
In this case the setPortParameters()
method throws a UnsupportedCommOperationException
.
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortManager;
[...]
SerialPortManager serialPortManager = ...;
SerialPort port = ...;
[...]
// Read old configuration.
System.out.println("Port: " + port.getName() + "\n"
+ " Baud rate: " + port.getBaudRate() + "\n"
+ " Data bits: " + port.getDataBits() + "\n"
+ " Stop bits: " + port.getStopBits() + "\n"
+ " Parity: " + port.getParity() + "\n"
+ " Flow control: " + port.getFlowControl());
// Set a new configuration: 38400/8/E/1, no flow control.
port.setPortParameters(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_EVEN, SerialPort.FLOWCONTROL_NONE);
[...]
When you are done with the serial port you need to close it by calling the close() method.
|
Monitor serial port events
You can monitor different serial port events, such as data available, lines state changes, or errors during the communication. To do so, follow these steps:
Step 1: Subscribe to serial port notifications
Use the registerEventListener(ISerialPortEventListener)
method of the SerialPort
object to subscribe to serial port notifications.
import com.digi.android.serial.SerialPort;
[...]
SerialPort port = ...;
// Create the serial port listener.
MySerialPortListener mySerialPortListener = ...;
// Register the serial port listener.
port.registerEventListener(mySerialPortListener);
[...]
The subscribed listener class, MySerialPortListener
, must implement the ISerialPortEventListener
interface.
This interface defines the serialEvent(SerialPortEvent)
method that is called every time a new serial port event occurs.
The received event is represented by the SerialPortEvent
object.
To distinguish between the different notifications, use the getEventType()
method to get the EventType
and filter.
import com.digi.android.serial.ISerialPortEventListener;
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortEvent;
public class MySerialPortListener implements ISerialPortEventListener {
@Override
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
case BI:
System.out.println("Break interrupt received");
break;
case CD:
System.out.println("Carrier detect received");
break;
case CTS:
System.out.println("CTS line activated");
break;
case DSR:
System.out.println("DSR line activated");
break;
case RI:
System.out.println("Ring Indicator received");
break;
case FE:
System.out.println("Received framing error");
break;
case PE:
System.out.println("Received parity error");
break;
case OE:
System.out.println("Buffer overrun error");
break;
case DATA_AVAILABLE:
System.out.println("Data to read available");
break;
default:
System.out.println("Unknown event");
break;
}
}
}
Only one listener can be subscribed per SerialPort
object.
If you try to register more, a TooManyListenerException
will be thrown.
Step 2: Enable notifications
Once the listener is implemented, you can use it to listen to particular serial port events.
By default, the listener is not notified about any of the previous events.
To notify the listener, request the reception of each SerialPort
event type individually.
Use the following methods:
Method | Description |
---|---|
|
Enables/disables Break interrupt notifications. |
|
Enables/disables Carrier Detect notifications. |
|
Enables/disables CTS notifications. |
|
Enables/disables data to read is available. |
|
Enables/disables DSR notifications. |
|
Enables/disables framing error notifications. |
|
Enables/disables output buffer empty notifications. |
|
Enables/disables overrun error notifications. |
|
Enables/disables parity error notifications. |
|
Enables/disables Ring Indicator notifications. |
import com.digi.android.serial.SerialPort;
[...]
SerialPort port = ...;
MySerialPortListener mySerialPortListener = ...;
port.registerEventListener(mySerialPortListener);
// Enable notifications.
port.notifyOnDataAvailable(true);
port.notifyOnCTS(true);
port.notifyOnDSR(true);
port.notifyOnRingIndicator(true);
port.notifyOnBreakInterrupt(true);
port.notifyOnCarrierDetect(true);
port.notifyOnFramingError(true);
port.notifyOnOverrunError(true);
port.notifyOnParityError(true);
[...]
Step 3: Unsubscribe to serial port notifications
If you no longer wish to be notified about any serial port event, use the unregisterEventListener()
method to unsubscribe to the registered listener.
import com.digi.android.serial.SerialPort;
[...]
SerialPort port = ...;
MySerialPortListener mySerialPortListener = ...;
port.registerEventListener(mySerialPortListener);
[...]
// Remove the serial port event listener.
port.unregisterEventListener();
[...]
When you are done with the serial port you need to:
|
Communicate with serial devices
When the serial port is open, you can communicate with the serial device connected to it (transmit and receive data).
Send data
You can send data through the serial port in two ways:
-
Write directly to the serial port using the
writeData(byte[] data, int numBytes)
method. -
Get the serial port’s
OutputStream
object and invoke one of the existingwrite()
methods.
import java.io.OutputStream;
import com.digi.android.serial.SerialPort;
[...]
SerialPort port = ...;
String dataToSend = "This is the data to send";
// Send data through the serial port directly.
port.writeData(dataToSend.getBytes(), dataToSend.getBytes().length);
// Get the port output stream.
OutputStream outStream = port.getOutputStream();
// Send data through the serial port using the output stream.
outStream.write(dataToSend.getBytes());
[...]
When you are done with the serial port you need to:
|
Receive data
You can receive data from the serial port in two ways:
-
Read directly from the serial port using the
readData(byte[] buffer, int numBytes)
method. -
Get the serial port’s
InputStream
object and invoke one of the existingread()
methods.
import java.io.InputStream;
import java.io.IOException;
import com.digi.android.serial.SerialPort;
private static final int BUFFER_SIZE = 1024;
[...]
SerialPort port = ...;
[...]
private void readData() {
try {
byte[] readBuffer = new byte[BUFFER_SIZE];
// Read the serial port.
int numBytes = port.readData(readBuffer, BUFFER_SIZE);
if (numBytes > 0)
System.out.println("Read: " + new String(readBuffer, 0, numBytes));
} catch (IOException e) {
e.printStackTrace();
}
}
private void readDataInputStream() {
// Get the port input stream.
InputStream inStream = port.getInputStream();
int availableBytes = inStream.available();
if (availableBytes > 0) {
byte[] readBuffer = new byte[availableBytes];
// Read the serial port input stream.
int numBytes = inStream.read(readBuffer, 0, availableBytes);
if (numBytes > 0)
System.out.println("Read: " + new String(readBuffer, 0, availableBytes));
}
}
[...]
Use the data available serial port event (EventType.DATA_AVAILABLE
) of your registered ISerialPortEventListener
to know when to read data:
import com.digi.android.serial.ISerialPortEventListener;
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortEvent;
public class MySerialPortListener implements ISerialPortEventListener {
@Override
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
case DATA_AVAILABLE:
/* Uncomment one of the following methods to read data. */
// readData();
// readDataInputStream()
break;
}
}
}
Do not forget to subscribe your listener to receive data available events and to enable this notification on your SerialPort
object.
import com.digi.android.serial.SerialPort;
[...]
SerialPort port = ...;
// Create the serial port listener.
MySerialPortListener mySerialPortListener = ...;
// Register the serial port listener.
port.registerEventListener(mySerialPortListener);
// Enable data available notifications.
port.notifyOnDataAvailable(true);
[...]
When you are done with the serial port you need to:
|
Manage serial port lines
The SerialPort
class also offers different methods to get the current state of the port lines and set some of them:
Method | Description |
---|---|
|
Gets the state of the CD (Carrier Detect) line. |
|
Gets the state of the CTS (Clear To Send) line. |
|
Gets the state of the DSR (Data Set Ready) line. |
|
Gets the state of the DTR (Data Terminal Ready) line. |
|
Sets or clears the DTR (Data Terminal Ready) line. |
|
Gets the state of the RI (Ring Indicator) line. |
|
Gets the state of the RTS (Request To Send) line. |
|
Sets or clears the RTS (Request To Send) line. |
|
Sends a break signal in the duration of the specified number of milliseconds. |
import com.digi.android.serial.SerialPort;
import com.digi.android.serial.SerialPortManager;
[...]
SerialPortManager serialPortManager = ...;
SerialPort port = ...;
[...]
// Read lines state.
System.out.println("CD: " + port.isCD());
System.out.println("CTS: " + port.isCTS());
System.out.println("DSR: " + port.isDSR());
System.out.println("DTR: " + port.isDTR());
System.out.println("RI: " + port.isRI());
System.out.println("RTS: " + port.isRTS());
// Set lines state.
port.setDTR(true);
port.setRTS(true);
// Send a break signal of 1 second.
port.sendBreak(1000);
[...]
When you are done with the serial port you need to:
|
Serial example
The Serial Port Sample Application demonstrates the usage of the serial port API. In this example, you can list all the available serial ports, configure them, and send and receive data.
You can import the example using Digi’s Android Studio plugin. For more information, see Import a Digi sample application. To look at the application source code, go to the GitHub repository.