This is an Arduino library to utilize the NXP SC16IS741 as a hardware serial port controlled via I2C.
This library is designed to be used with the QwiicUART breakout board.
QwiicUART()
Creates a QwiicUART object and sets the I2C port and address to use.
QwiicUARTQwiicUART(wire)QwiicUART(wire, address)
wire: theTwoWireobject to use to talk to the UART chip. The default value isWire.address: The I2C address of the UART chip. Typical values are:
0x48(default)
0x49
0x4A
0x4B# include <QwiicUART.h> QwiicUART qSerial(Wire, 0x48);
available()
Get the number of bytes (characters) available for reading from the serial port. This is data that’s already arrived and stored in the serial receive buffer (which holds 64 bytes).
available()inherits from the Stream utility class.
qSerial.available()
qSerial: aQwiicUARTserial port object.The number of bytes available to read.
# include <QwiicUART.h> QwiicUART qSerial; void setup() { Serial.begin(9600); Wire.begin(); qSerial.begin(9600); } void loop() { // read from Serial, send to qSerial: if (Serial.available()) { int inByte = Serial.read(); qSerial.print(inByte, DEC); } // read from qSerial, send to Serial: if (qSerial.available()) { int inByte = qSerial.read(); Serial.print(inByte, DEC); } }
availableForWrite()
Get the number of bytes (characters) available for writing in the serial buffer without blocking the write operation.
qSerial.availableForWrite()
qSerial: aQwiicUARTserial port object.The number of bytes available to write.
begin()
Description
Sets the data rate in bits per second (baud) for serial data transmission.
An optional second argument configures the data, parity, and stop bits. The default is 8 data bits, no parity, one stop bit.
Syntax
qSerial.begin(baud)qSerial.begin(baud, config)Parameters
qSerial: aQwiicUARTserial port object.baud: in bits per second. Common values are:1200,2400,4800,9600,16200,38400,57600, and115200. Allowed data types:long.config: sets data, parity, and stop bits. Valid values are:
SERIAL_5N1SERIAL_6N1SERIAL_7N1SERIAL_8N1(default)SERIAL_5N2SERIAL_6N2SERIAL_7N2SERIAL_8N2SERIAL_5E1: even paritySERIAL_6E1SERIAL_7E1SERIAL_8E1SERIAL_5E2SERIAL_6E2SERIAL_7E2SERIAL_8E2SERIAL_5O1: odd paritySERIAL_6O1SERIAL_7O1SERIAL_8O1SERIAL_5O2SERIAL_6O2SERIAL_7O2SERIAL_8O2Example
# include <QwiicUART.h> QwiicUART qSerial; void setup() { Wire.begin(); qSerial.begin(9600); } void loop() {}[!NOTE] The actual baud rate of the SC16IS741 is set using an integer
$divisor$ . When using a 1.8432 MHz clock, as the QwiicUART board does, the baud rate will be:$$\frac{115200}{divisor}$$ This library selects the$divisor$ value that will result in the baud rate closest to what is asked for, but because it is an integer, there is limited resolution, particularly at the higher baud rates.
$divisor$ Baud Rate 1 115200 2 57600 3 38400 4 28800 5 23040 6 19200
digitalReadCts()
Reads the value from the CTS pin.
qSerial.digitalReadCts()
qSerial: aQwiicUARTserial port object.
HIGHorLOW
digitalWriteRts()
Write a
HIGHorLOWvalue to the RTS pin.
HIGHbeing 3.3V andLOWbeing 0V.
qSerial.digitalReadCts(value)
qSerial: aQwiicUARTserial port object.value:HIGHorLOW
end()
Runs flush() then resets the SC16IS741.
qSerial.end()
qSerial: aQwiicUARTserial port object.
find()
Reads data from the serial buffer until the target is found. The function returns
trueif target is found,falseif it times out.
find()inherits from the Stream utility class.
qSerial.find(target)qSerial.find(target, length)
qSerial: aQwiicUARTserial port object.target: the string to search for. Allowed data types:char.length: length of the target. Allowed data types:size_t.Data type:
bool.
findUntil()
Reads data from the serial buffer until a target string of given length or terminator string is found.
The function returns
trueif the target string is found,falseif it times out.
findUntil()inherits from the Stream utility class.
qSerial.findUntil(target, terminal)
qSerial: aQwiicUARTserial port object.target: the string to search for. Allowed data types:char.terminal: the terminal string in the search. Allowed data types:char.Data type:
bool.
flush()
Waits for the transmission of outgoing serial data to complete.
flush()inherits from the Stream utility class.
qSerial.flush()
qSerial: aQwiicUARTserial port object.
parseFloat()
Returns the first valid floating point number from the Serial buffer.
parseFloat()is terminated by the first character that is not a floating point number. The function terminates if it times out (seesetTimeout()).
parseFloat()inherits from the Stream utility class.
qSerial.parseFloat()qSerial.parseFloat(lookahead)qSerial.parseFloat(lookahead, ignore)
qSerial: aQwiicUARTserial port object.lookahead: the mode used to look ahead in the stream for a floating point number. Allowed data types:LookaheadMode. Allowed values:
SKIP_ALL: All characters other than a minus sign, decimal point, or digits are ignored when scanning the stream for a floating point number. This is the default mode.SKIP_NONE: Nothing is skipped, and the stream is not touched unless the first waiting character is valid.SKIP_WHITESPACE: Only tabs, spaces, line feeds, and carriage returns are skipped.ignore: used to skip the indicated char in the search. Used for example to skip thousands divider. Allowed data types:charData type:
float.
parseInt()
Looks for the next valid integer in the incoming serial. The function terminates if it times out (see
setTimeout()).
parseInt()inherits from the Stream utility class.In particular:
- Parsing stops when no characters have been read for a configurable time-out value, or a non-digit is read;
- If no valid digits were read when the time-out (see
setTimeout()) occurs, 0 is returned;
qSerial.parseInt()qSerial.parseInt(lookahead)qSerial.parseInt(lookahead, ignore)
qSerial: aQwiicUARTserial port object.lookahead: the mode used to look ahead in the stream for an integer. Allowed data types:LookaheadMode. Allowed values:
SKIP_ALL: All characters other than digits or a minus sign are ignored when scanning the stream for an integer. This is the default mode.SKIP_NONE: Nothing is skipped, and the stream is not touched unless the first waiting character is valid.SKIP_WHITESPACE: Only tabs, spaces, line feeds, and carriage returns are skipped.ignore: used to skip the indicated char in the search. Used for example to skip thousands divider. Allowed data types:charThe next valid integer. Data type:
long.
peek()
Returns the next byte (character) of incoming serial data without removing it from the internal serial buffer. That is, successive calls to
peek()will return the same character, as will the next call toread().
peek()inherits from the Stream utility class.
qSerial.peek()
qSerial: aQwiicUARTserial port object.The first byte of incoming serial data available (or -1 if no data is available). Data type:
int.
print()
Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is. For example-
qSerial.print(78)gives "78"qSerial.print(1.23456)gives "1.23"qSerial.print('N')gives "N"qSerial.print("Hello world.")gives "Hello world."An optional second parameter specifies the base (format) to use; permitted values are
BIN(binary, or base 2),OCT(octal, or base 8),DEC(decimal, or base 10),HEX(hexadecimal, or base 16). For floating point numbers, this parameter specifies the number of decimal places to use. For example:
qSerial.print(78, BIN)gives "1001110"qSerial.print(78, OCT)gives "116"qSerial.print(78, DEC)gives "78"qSerial.print(78, HEX)gives "4E"qSerial.print(1.23456, 0)gives "1"qSerial.print(1.23456, 2)gives "1.23"qSerial.print(1.23456, 4)gives "1.2346"To send data without conversion to its representation as characters, use
write().
qSerial.print(value)qSerial.print(value, format)
qSerial: aQwiicUARTserial port object.value: the value to print. Allowed data types: any data type.format: specifies the number base (for integral data types) or number of decimal places (for floating point types).The number of bytes written, though reading that number is optional. Data type:
size_t./* Uses a for loop to print numbers in various formats. */ # include <QwiicUART.h> QwiicUART qSerial; void setup() { Wire.begin(); qSerial.begin(9600); } void loop() { // print labels qSerial.print("NO FORMAT"); // prints a label qSerial.print("\t"); // prints a tab qSerial.print("DEC"); qSerial.print("\t"); qSerial.print("HEX"); qSerial.print("\t"); qSerial.print("OCT"); qSerial.print("\t"); qSerial.print("BIN"); qSerial.println(); // carriage return after the last label for (int x = 0; x < 64; x++) { // only part of the ASCII chart, change to suit // print it out in many formats: qSerial.print(x); // print as an ASCII-encoded decimal - same as "DEC" qSerial.print("\t\t"); // prints two tabs to accomodate the label length qSerial.print(x, DEC); // print as an ASCII-encoded decimal qSerial.print("\t"); // prints a tab qSerial.print(x, HEX); // print as an ASCII-encoded hexadecimal qSerial.print("\t"); // prints a tab qSerial.print(x, OCT); // print as an ASCII-encoded octal qSerial.print("\t"); // prints a tab qSerial.println(x, BIN); // print as an ASCII-encoded binary // then adds the carriage return with "println" delay(200); // delay 200 milliseconds } qSerial.println(); // prints another carriage return }[!NOTE] QwiicUART "Serial" transmission is asynchronous. Depending on the baud rate and I2C clock,
print()may return before all the characters are transmitted. If the transmit buffer/FIFO is full thenprint()will block until there is enough space in the buffer. To avoid blocking calls toprint(), you can first check the amount of free space in the transmit buffer usingavailableForWrite().
println()
Prints data to the serial port as human-readable ASCII text followed by a carriage return character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the same forms as
print().
qSerial.println(value)qSerial.println(value, format)
qSerial: aQwiicUARTserial port object.value: the value to print. Allowed data types: any data type.format: specifies the number base (for integral data types) or number of decimal places (for floating point types).The number of bytes written, though reading that number is optional. Data type:
size_t./* Analog input reads an analog input on analog in 0, prints the value out. Created: 2026-03-24 By: Tom Igoe Adapted for QwiicUART on: 2025-02-12 By: C. M. Bulliner */ # include <QwiicUART.h> QwiicUART qSerial; int analogValue = 0; // variable to hold the analog value void setup() { Wire.begin(); qSerial.begin(9600); } void loop() { // read the analog input on pin 0: analogValue = analogRead(0); // print it out in many formats: qSerial.println(analogValue); // print as an ASCII-encoded decimal qSerial.println(analogValue, DEC); // print as an ASCII-encoded decimal qSerial.println(analogValue, HEX); // print as an ASCII-encoded hexadecimal qSerial.println(analogValue, OCT); // print as an ASCII-encoded octal qSerial.println(analogValue, BIN); // print as an ASCII-encoded binary // delay 10 milliseconds before the next reading: delay(10); }[!NOTE] QwiicUART "Serial" transmission is asynchronous. Depending on the baud rate and I2C clock,
println()may return before all the characters are transmitted. If the transmit buffer/FIFO is full thenprintln()will block until there is enough space in the buffer. To avoid blocking calls toprintln(), you can first check the amount of free space in the transmit buffer usingavailableForWrite().
read()
Reads incoming serial data.
read()inherits from the Stream utility class.
qSerial.read()
qSerial: aQwiicUARTserial port object.The first byte of incoming serial data available (or -1 if no data is available). Data type:
int.# include <QwiicUART.h> QwiicUART qSerial; int incomingByte = 0; // for incoming serial data void setup() { Serial.begin(9600); Wire.begin(); qSerial.begin(9600); } void loop() { // send data only when you receive data: if (qSerial.available() > 0) { // read the incoming byte: incomingByte = qSerial.read(); // say what you got: Serial.print("I received: "); Serial.println(incomingByte, DEC); } }
readBytes()
Reads characters from the serial port into a buffer. The function terminates if the determined length has been read, or it times out (see
setTimeout()).
readBytes()returns the number of characters placed in the buffer. A 0 means no valid data was found.
readBytes()inherits from the Stream utility class.
qSerial.readBytes(buffer, length)
qSerial: aQwiicUARTserial port object.buffer: the buffer to store the bytes in. Allowed data types: array ofcharorbyte.length: the number of bytes to read. Allowed data types:int.The number of bytes placed in the buffer. Data type:
size_t.
readBytesUntil()
Reads characters from the serial buffer into an array. The function terminates (checks being done in this order) if the determined length has been read, if it times out (see Serial.setTimeout()), or if the terminator character is detected (in which case the function returns the characters up to the last character before the supplied terminator). The terminator itself is not returned in the buffer.
readBytesUntil()returns the number of characters read into the buffer. A 0 means that the length parameter <= 0, a time out occurred before any other input, or a termination character was found before any other input.
readBytesUntil()inherits from the Stream utility class.
qSerial.readBytesUntil(character, buffer, length)
qSerial: aQwiicUARTserial port object.character: the character to search for. Allowed data types:char.buffer: the buffer to store the bytes in. Allowed data types: array ofcharorbyte.length: the number of bytes to read. Allowed data types:int.Data type:
size_t.[!NOTE] The terminator character is discarded from the serial buffer, unless the number of characters read and copied into the buffer equals
length.
readString()
Reads characters from the serial buffer into a
String. The function terminates if it times out (seesetTimeout()).
readString()inherits from the Stream utility class.
qSerial.readString()
qSerial: aQwiicUARTserial port object.A
Stringread from the serial buffer# include <QwiicUART.h> QwiicUART qSerial; void setup() { Wire.begin(); qSerial.begin(9600); } void loop() { qSerial.println("Enter data:"); while (qSerial.available() == 0) {} //wait for data available String teststr = qSerial.readString(); //read until timeout teststr.trim(); // remove any \r \n whitespace at the end of the String if (teststr == "red") { qSerial.println("A primary color"); } else { qSerial.println("Something else"); } }[!NOTE] The function does not terminate early if the data contains end of line characters. The returned
Stringmay contain carriage return and/or line feed characters if they were received.
readStringUntil()
Reads characters from the serial buffer into a String. The function terminates if it times out (see
setTimeout()).
readStringUntil()inherits from the Stream utility class.
qSerial.readStringUntil(terminator)
qSerial: aQwiicUARTserial port object.terminator: the character to search for. Allowed data types:char.The entire
Stringread from the serial buffer, up to the terminator character. If the terminator character can’t be found, or if there is no data before the terminator character, it will returnNULL.[!NOTE] The terminator character is discarded from the serial buffer. If the terminator character can’t be found, all read characters will be discarded.
setHwFlowCtrlMode()
Sets the usage of the RTS and CTS pins.
The RTS pin is an output. When enabled as a flow control, it will be set
LOWuntil the number of bytes in the receiving buffer exceeds the threshold, then it will be setHIGH. It will be setLOWagian when the receiving buffer is empty.The CTS pin is an input. When enabled as a flow control, the UART will only transmit when this pin is
LOW.
qSerial.setHwFlowCtrlMode(mode)qSerial.setHwFlowCtrlMode(mode, threshold)
qSerial: aQwiicUARTserial port object.
mode: sets flow control mode. Valid values are:
UART_HW_FLOWCTRL_DISABLEUART_HW_FLOWCTRL_RTSUART_HW_FLOWCTRL_CTSUART_HW_FLOWCTRL_CTS_RTS
threshold: sets how full the receiving buffer needs to be before setting the RTS pinHIGH. Min value: 4. Max value: 60, default value: 32.
setMode()
Sets the operating mode of the UART.
When set to
UART_MODE_UART, the UART will act as a normal UART serial port.When set to
UART_MODE_RS485_HALF_DUPLEX, the UART will set the RTS pin high whenever it is transmtting. This is useful when working with a half-duplex RS-485 tranceiver. Typically these transceivers will require a driver enableDEcontrol.
qSerial.setMode(mode)
qSerial: aQwiicUARTserial port object.
mode: sets flow control mode. Valid values are:
UART_MODE_UARTUART_MODE_RS485_HALF_DUPLEX
setTimeout()
Sets the maximum milliseconds to wait for serial data. It defaults to 1000 milliseconds.
setTimeout()inherits from the Stream utility class.
qSerial.setTimeout(time)
qSerial: aQwiicUARTserial port object.time: timeout duration in milliseconds. Allowed data types:long.[!NOTE] QwiicUART functions that use the timeout value set via
setTimeout():
find()findUntil()parseInt()parseFloat()readBytes()readBytesUntil()readString()readStringUntil()
print()
Writes binary data to the serial port. This data is sent as a byte or series of bytes; to send the characters representing the digits of a number use the
print()function instead.
qSerial.write(value)qSerial.write(string)qSerial.write(buffer, length)
qSerial: aQwiicUARTserial port object.value: a value to send as a single byte.string: a string to send as a series of bytes.buffer: an array to send as a series of bytes.length: the number of bytes to be sent from the array.The number of bytes written, though reading that number is optional. Data type:
size_t./* Uses a for loop to print numbers in various formats. */ # include <QwiicUART.h> QwiicUART qSerial; void setup() { Wire.begin(); qSerial.begin(9600); } void loop() { qSerial.write(45); // send a byte with the value 45 int bytesSent = qSerial.write("hello"); //send the string "hello" and return the length of the string. }[!NOTE] QwiicUART "Serial" transmission is asynchronous. Depending on the baud rate and I2C clock,
write()may return before all the characters are transmitted. If the transmit buffer/FIFO is full thenwrite()will block until there is enough space in the buffer. To avoid blocking calls towrite(), you can first check the amount of free space in the transmit buffer usingavailableForWrite().
Much of the documentation in this README is based on the Arduino Docs Language Reference, particularly from the Serial section. Modifications were made.
The source code of this library is distributed under the MIT license. However this README is distributed under the Creative Commons Attribution Share Alike 4.0 license.
