Microcontrollers like the Arduino are an essential part of DIY projects including robotics. In the last article, we saw the Pin layout and GPIO functions of the Arduino Uno, the Raspberry Pi and the Raspberry Pico. GPIO pins can either read or write digital data, that is a continuous high or low voltage, or work with analog data, a PWM signal that alternates between high and low voltage in a compressed time frame. We also saw that these microcontrollers and single-board computers support different GPIO functions, including protocols to communicate data with other hardware.
This article provides an overview to all of these connection protocols. To be explicit, I will present protocols that require a direct wiring of devices, and therefore exclude protocols like radio, Bluetooth and WLAN. For each protocol, I will explain the essential working principles, detail how to setup and connected devices, and discuss aspects like data transmission range and data amount. I will use the common terminology of client-server to differentiate the roles of participating nodes.
In the first section, we will learn about serial communication essentials. Then, the next sections detail each of the following protocols:
- W1 (1 Wire)
- I2C (2 Wire)
- SPI (4 Wire)
Serial communication forms the basic data transmission method of many integrated circuit devices. Essentially, data is transmitted in one way, 1 bit at a time, from sender to receiver. To safeguard transmission errors, the transmitted data can include error checking codes, typically CRC. To ensure transmission success, the receiver can send an acknowledge information.
Serial communication is preferred to parallel communication in cases where the cost of having multiple connections (inlines, wires, cables etc.) is too high because of distance or manufacturing costs. Until today, serial communication is widely used to connect different types of hardware with each other, forming the basis for very different protocols.
With the 1-Wire protocol, a one-to-many connection between a server and several clients can be made by using only one data transmission/power wire[^1]. The connection is half-duplex, bi-directional, 16.3Khz transmission speed.
Typically, an open-drain MOSFET is used to connect the devices. The connection between the server and the client is in high voltage state by using a pull-up resistor. To transmit data, the pull-up resistor is connected to ground, then a low-voltage connection between the server and client is made for data transmission. The high voltage state is used to charge a capacitor that provides power to the connected client.
Messages are 8bit MSB. A typical transaction works as follows:
- The server sends a reset pulse
- The clients send an acknowledge message
- The server sends an 8bit command
- Server and client exchange groups of 8bit data
- To safeguard against transmission errors, 8bit CRCs can be used
I2C, Inter-Integrated-Circuit, is a 2-Wire protocol to enable many-to-many connections between clients and servers: The two wires are serial data (SDA) and serial clock (SCL). The connection is half-duplex, bidirectional, with a fixed, configurable transmission speed of 0.1, 0.4, 1.0, 3.4 or 5.0 MBit.
The SDA and the SCL line are kept constantly in a High voltage stage, where the SDA lines uses pull-up resistors. When a server starts its transmission, it closes its MOSFET gate to drop the SDA line to a low state. Then, by applying different voltages to the SDA and the SCL lines, information is transmitted. A low voltage on the SDA lines also signifies that one master node is communicating - keeping the others quiet. A low voltage on the SCL lines signifies the same information for the clients.
All devices in the I2C bus have 7bit addresses. To address devices, and receive conformations, 2 bits are used. Therefore, all messages in I2C are 9bits MSB. A typical transaction is:
- The server sends a 7-Bit address, and a read/write bit
- The addressed client acknowledges with a bit (thus completing the 9bits message format)
- Depending on the message, server either sends write data to a client, distinguishing the registers/buffers and the data to write, or it expects the client to write its data at a designated register/buffer from which the server reads
- The transmission is finished when both SDA and SCL are again in the high state
The I2C system has a complex set of registers for capturing the global state of the system and coordinate how different devices can interact. The register addresses, and their data, is vendor and device specific.
SPI, Serial Peripheral Interface, is a many-to-one connection protocol of multiple clients to one server. It requires 4 wires: SCL for clock, SCS for selecting a client, SDTS for data transmission of the server, SDTC for data transmissions of the clients. The connection if full-duplex, bidirectional, and has no limit for transmission speed (10MB or more can be achieved).
The bit frame is configurable, usually 8bits, but also 12Bit or 16Bits are used. Data is sent with LSB.
In the base state, SCS is high (using pull-up resistors), SCL, SDTS and SDTC are low. When the server initiates communication, it pulls SCS to low using a MOSFET gate, and sends data over SCL. Then, the server uses SDTS and the selected client uses SDTC to communicate, full-duplex, with each other.
A typical communication is as follows:
- The server determines the clock speed for connecting to a client
- The server sets SCS to low voltage, and sends data over SDTS
- The addressed client responds on the SDTC line and in the chosen clock speed
- Server and client exchange data
- Server sets SCS to high voltage, and SCL to low
SPI requires a dedicated SDTC wire for each connected client, which has a strong impact on integrated circuit design. Therefore, daisy-chaining can be used to design a circuit with only on SDTC wire, and additional changes to the data transmission protocol. Interestingly, there is no fixed standard of the SPI protocol, but several vendor-specific implementations that follow the same guidelines.
UART and RS-232
These two protocols govern the direct one-to-one connection between two devices. Specifically, RS-232 defines the physical transmission characteristics: electrical signals, their timing and meaning, as well as the physical size of hardware pins and connectors. A minimal RS-232 connection can be achieved with just two wires: TXD for transmitting data, and RXC for receiving data. On top of this physical standard. UART defines the logical messaging, which is quite configurable: simplex, half-duplex or full duplex, with varying communication speeds of at least 115,2 KBit.
In the base state, both TXD and RXD lines are high. The sender switches TXD to high and begins transmitting data immediately, while the receiver uses RXD to acknowledge the data. Sender and receiver also use these lines to synchronize their clock
Transmitted data is 7-11 bits LSB, including start and stop bits.
A typical message exchange is as follows:
- The sender sends a start bit, a 5- or 9-bit message, and the stop bit
- The receiver buffers the incoming message in his shift register
- When no data is received anymore - e.g. a complete clock cycle is in the logical low state - the data from the shift transmitter is flushed to other parts of the integrated circuit
The UART standard is interesting in its historical meaning. Although the early physical manifestations of RS-232 - COM ports - almost vanished from todays end-consumer computers, the standard is emulated in many microcontrollers to allow serial-over-usb connections.
The following table summarizes the characteristics of each protocol:
+-----------------------------------+-----------------+-----------------+-----------------+----------------+ | 1-Wire | I2C | SPI | UART | | +-----------------------------------+-----------------+-----------------+-----------------+----------------+ | Message Direction | bi-directional | bi-directional | bi-directional | bi-directional | | Message Synchronicity | half-duplex | half-duplex | full-duplex | half-duplex | | | | | | | | Server <=> Client | 1 <=> * | * <=> * | 1 <=> * | 1 <=> 1 | | Wires per Device | 1 | 2 | 4 | 1 | | Number of Devices | 56Bit | 7bit | * | 2 | | | | | | | | Bit Rate | 16.3 Kbit/s | 0.1 MB/s | | | | 0.4 MB/s | | | | | | 1 MB/s | | | | | | 3.2 mb/s | | | | | | 5.0 MB/s | 20MB/s | 0,2Mb/s | | | | Frame | 8Bit | 9Bit | 8Bit | | | 12Bit | | | | | | 16Bit | 5-9Bit | | | | | | | | | | | Physical Distance | 1m | | | | | (with special hardware 100-300m) | 1m | 0,2m | 15m | | +-----------------------------------+-----------------+-----------------+-----------------+----------------+
A notice: The characteristics of the SPI system depend on the overall setup: Clock speed of the microprocessor, total amount of resistors etc.
Forming wired connection between microcontrollers and sensors in order to exchange data is a task that you will encounter in your projects. This article explained the basics of the connection protocols 1-Wire, I2C, SPI and UART/RS232. We explained aspects like message synchronicity, bit rate and frame structure, as well as physical aspects like how many clients can connect and how long the total distance of all wires are. Which protocol will you use in your projects?
[^1]: All devices in an integrated circuit need also a connection to ground, so technically two wires are needed.