Digital interfaces: explained

Interfaces and protocols can be quite confusing for people taking their first steps into electronics and Arduino, but they are just like the languages spoken by microcontrollers and sensors. If two devices support the same interface, they can “speak” to each other with digital signals of ones and zeroes.

Over the years, many different and incompatible protocols have been designed that each require slightly different connections and have their own benefits. To help you understand the mysterious three letter abbreviations, here’s an explanation of the most commonly seen.

Jargon Buster!

ProtocolA set of rules governing the exchange or transmission of data between devices.
Data(in this context) Bits that make up a meaningful message to be processed by a computer.
BusChannel via which data is sent between devices. Like a “data highway” that can have multiple connections to many devices (not just two!)
Half-duplexBoth sender and receiver can talk, but only one can be talking at a time (like a walkie-talkie)
Full-duplexSender and receiver can talk to each other (send data) at the same time (like a cell phone)
BitBinary digit. A single One or zero
Floating (describing a connection/pin)Not connected to any fixed voltage reference: as if it was “floating” in mid-air. Can cause problems by picking up radio waves and turning them into random voltages.
Pull-up/Pull-down resistorA resistor that “pulls” the voltage of a wire “up” to supply voltage or “down” to ground. Prevents the voltage from floating and causing erratic behavior.
Jargon Buster

I²C (Inter-Integrated Circuit)

I²C is a simple bus that only needs two digital pins to work, great for limited I/O microcontrollers such as the ATTiny85. A data wire (SDA) sends bits of data while a clock wire (SCL) keeps both devices synchronized so they don’t miss any ones or zeroes.

I²C is very common with digital sensors and devices that don’t need to send much data (such as real-time clocks or low capacity EEPROM memory). It is also used in port expanders – handy little chips that give you many more I/O pins to work with, controlled or read over I²C!

It is half-duplex as there is only one single data wire – if two devices tried to send data at the same time, they would “talk over” each other’s signal and produce garbled data. Each I²C device has an fixed address; this is, as the name suggests, just a unique identifier for every device on the bus so they can be addressed individually. Bear in mind that there are only 255 possible addresses, and there may be conflicts where two devices have the same address: these can sometimes be resolved by “jumpers” that change signals to pins that make the chip have a different address.

common I²C BME280 module

How to use I²C

The I²C protocol requires pull-up resistors on both SDA and SCL pins (commonly used values are 10 kΩ and 4.7 kΩ). Some modules (especially Adafruit modules) have these built-in, but it’s something to check if your circuit doesn’t work first time. Connections are pretty simple:

SDASDASerial DAta – carries data
SCLSCLSerial CLock – carries sync/”clock” signal
Nothing much to it.

Trivia: There are various ways to write/type the I²C name. It can also be written I2C or sometimes directly abbreviated IIC. The general consensus is that it is pronounced like “eye squared cee”.

SPI (Serial Peripheral Interface)

SPI is slightly more advanced than I²C, as it is full-duplex, with a dedicated transmit and receive pin. Instead of using addresses, it uses a chip select (CS) system where each device has a chip select pin that needs a corresponding pin on the master microcontroller. When the chip select pin of a device is low (zero volts), the device listens for data and responds to clock pulses. Otherwise (when the CS pin is high), the device ignores everything. This allows control of each device without needing unique addresses that might conflict, but takes up an I/O pin for each device on the SPI bus.

SPI supports faster speeds than I²C, so is often used for places that need high data rates such as color displays or SD cards. Although it may seem complicated at first, once you get the hang of it it’s just as easy as I²C. (“easy as S P I” just doesn’t have the same ring to it…)

SPI liquid-crystal display (LCD) module from Adafruit

How to use SPI

MISOMISOMain In Subdevice Out – data from device to main controller
MOSIMOSIMain Out Subdevice In – data from main controller to device
SCKSCKSerial Clock – synchronizes data transfer
CS (any GPIO pin)SS/CSChip Select – tells a device to listen for data
FOUR pins?!!

Trivia: SPI is a de facto standard… this is the most common implementation but some manufacturers may have added their own quirks.

UART (Universal Asynchronous Receiver Transmitter)
also known as Serial

UARTs come in many shapes and sizes, but they all provide full-duplex information transmission. They are often referred to as “serial” ports or simply “Serial”. The term “asynchronous” means that the receiver is not synchronised with the transmitter by way of a clock pin – both ends of the connection need a reasonably accurate (within 0.5%) timing source to communicate via UART. Only two devices can be connected to one UART – if you have multiple, you will need a UART for each one.

UARTs are often used for communication between a microcontroller/embedded system and a computer; if you’re using an Arduino, you’ll probably be familiar with Serial Monitor which allows you to talk to your trinket over a UART (It’s actually a bit more complex than that, but that’s for a later post). UARTs are also commonly used for communication between microcontrollers or to more complex modules such as radio transceivers and GPS location modules.

An important concept with UARTs is baud rate, which is the number of bits sent per second. Both devices need to have the same baud rate set, because otherwise the bits would not be received correctly – however, sometimes an auto-baud feature is available, where a device can automatically determine the baud rate of data transmission. A higher baud rate means that data can be sent faster, but the risk of errors due to interference is also higher.

Adafruit FONA 808 GSM and GPS module. It can call like a phone, but it’s on a handy board!

How to use UART

Wiring up a UART can be confusing due to the way TX/RX are flipped on each end. It makes it easier if you think of their purpose – TX stands for “transmit”, RX stands for “receive”. What you’re doing is connecting one side’s transmitter to the other’s receiver, so the sent data is received properly. It will not work if you connect TX to TX and RX to RX!

Sometimes you may see other pins such as DTR (Data Terminal Ready), RTS (Request to Send), CTS (Clear to Send), DSR (Data Set Ready). These are known as flow control pins, and are usually optional in most UART implementations. Consult your particular device’s documentation for more details.

MicrocontrollerDevice/other microcontrollerPurpose
TX (transmit)RX (receive)Connect data the MCU sends to the device.
RX (receive)TX (transmit)Data path for data the device sends to the MCU.
It’s backwards!!!

Trivia: The baud unit is named after Émile Baudot, a French telegraph engineer who invented one of the first character encodings in 1870.

Which one can I use?

Microcontrollers commonly have peripherals for these protocols, which are specialized circuits integrated into their silicon. If your MCU has hardware I²C/SPI/Serial, it will be able to communicate at the highest speeds without putting extra load on the processor. For example, the Arduino Uno has all three of hardware I²C, SPI and Serial, but the hardware UART is used to program the device, so it is not usable by default. The Arduino Mega 2560 has four Serial ports, three of which are usable, but the small ATtiny85 has only SPI and no I²C or Serial!

If your microcontroller does not have enough hardware peripherals, you can often find libraries that other people have made to toggle a regular I/O pin in the right way to emulate the protocol. This is sometimes called “bitbanging”. Although this may work, it requires precise timing that interrupts whatever your code is doing, and is often limited to slower speeds. If you’re using many bitbanged peripherals, it may be a sign that you’re using the wrong microcontroller.

That’s all for now!

Hopefully this post has provided some useful information about these common protocols, so you can go and make your next idea. Happy tinkering!

This post is the first in a series. A second instalment is coming soonTM





Leave a Reply

Your email address will not be published. Required fields are marked *