If you spend any time playing with Arduinos, ATtinys or looking at AVR spec sheets, you soon encounter a bewildering smörgåsbord of acronyms for various communication protocols. With examples such as I2C, LIN, SPI, TWI, USI, etc., it can get pretty confusing. If you don’t believe me, just take a look communications column for Digikey’s listing for the ATmega series chips. Confused yet?
What do these terms mean? How do you choose the chip that meets your needs? How do you make use of these protocols? In this article, I take the mystery out of all these acronyms, and provide a brief overview of what they mean and how you use them in your projects. We’ll examine each of the protocols, including some of the terms that are not exactly protocols, and survey some of the software libraries available to make communications easier.
The SPI (Serial Peripheral Interface) is the protocol used by the ICSP (in-circuit serial programming) facility transmitted over the ubiquitous 6-pin (2×3 pin) header used to program AVR chips. It is useful not only for programming AVR chips, but also for other types of communications between ICs. From Wikipedia:Movie Carol (2015)
The Serial Peripheral Interface Bus or SPI (pronounced as either ess-pee-eye, spy or simply S.P.I) bus is a synchronous serial data link standard, named by Motorola, that operates in full duplex mode. Devices communicate in master/slave mode where the master device initiates the data frame. Multiple slave devices are allowed with individual slave select (chip select) lines. Sometimes SPI is called a four-wire serial bus, contrasting with three-, two-, and one-wire serial buses.
One thing I like about this protocol (as compared to those using the UARTs TXD & RXD lines) is that the connection does not need to be reversed. As you can see in the diagram above, MOSI connects to MOSI and MISO to MISO.
Besides using it to communicate or control other AVR chips, you can also hook other useful ICs to your Arduino as well. Examples include a temperature chip and a 4-digit 7-segment LED display driver. The Arduino IDE even has a library that implements this protocol, making use of it a breeze (okay, maybe not that simple, but at least a lot easier). Both ATmega chips and ATtiny chips support this protocol, but ATtiny support is slightly limited – see the section on USI (below) for details.
This protocol is known as both I2C (Inter-Integrated Circuit) and as TWI (two wire interface). From Wikipedia:
I²C (“i-squared cee”; Inter-Integrated Circuit; generically referred to as “two-wire interface”) is a multi-master serial single-ended computer bus invented by Philips that is used to attach low-speed peripherals to a motherboard, embedded system, cellphone, or other electronic device.
It is available on both ATtiny and ATmega chips. Since it uses only two wires, so connections are simple. One line is for the clock and the other for the data. Like the SPI interface, these lines do not need reversing either. The pin names used for this protocol are SCL (clock) and SDA (data). Since it was designed for inter-IC communication, its primary value is driving other chips over a common serial bus without tying up a lot of pins. Each device has its own unique address, so you can connect up to 128 devices to your AVR chip. There are literally thousands of ICs that you can hook to your Arduino or ATtiny to greatly expand its capabilities. Examples include
- Real time clocks
- Data acquisition
- I/O pin expanders
- LED drivers
- Display drivers
and many more. The last example – display drivers is a far superior way to drive displays requiring a lot of pins that using a shift register. The prices for these chips are surprisingly affordable in many cases as well. John over at TronixStuff has an excellent tutorial on using this protocol with your Arduino that includes examples on using some of these ICs.
As with the SPI protocol, you don’t have to roll your own code either. The Arduino IDE has a library that implements this protocol, using simple functions such as read() and write(). Here’s an example:
#include "Wire.h" // enable I2C bus Wire.beginTransmission(deviceAddress); Wire.write(1); Wire.write(digits[one]); Wire.write(digits[ten]); Wire.write(digits[hundred]); Wire.write(digits[thousand]); Wire.endTransmission();
The Arduino Wire library is also compatible with C++ stream i/o, so you can use standard stream functions as well.
Before struggling with shift registers and other hacks to expand your I/O pins, first look to see if there is an I2C chip that does it first.
USI which stands for Universal Serial Interface, does not stand for a communication protocol, but is Atmel’s implementation of serial communication on many of the ATtiny series chips. Most of the ATtinys do not support either I2C or SPI directly. Instead they provide the USI feature. This interface can be used for both two wire (I2C/TWI) and three wire (SPI) synchronous data transfer – either master or slave. Here are some specifics from the ATtiny spec sheets on how these protocols are implemented with USI and where this implementation differs.
The USI three-wire mode is compliant to the Serial Peripheral Interface (SPI) mode 0 and 1, but does not have the slave select (SS) pin functionality. However, this feature can be implemented in software if necessary. Pin names used by this mode are: DI, DO, and USCK.
The USI two-wire mode is compliant to the Inter IC (TWI) bus protocol, but without slew rate limiting on outputs and without input noise filtering. Pin names used in this mode are SCL and SDA.
While I haven’t done a lot of work with these protocols on ATtiny chips, it appears that I2C/TWI communication should be straightforward and the same as the ATmega series. Ditto for the SPI protocol, except that it seems that in slave mode, you can only have one device attached since a slave select pin (SS) is lacking on the ATtiny.
All in all, Atmel has done a great job to support these useful protocols in such tiny and inexpensive chips using this interface.
UART stands for Universal Asynchronous Receiver/Transmitter. USART is a synonym for UART. Instead of being a protocol, a UART/USART is actually a piece of computer hardware that implements asynchronous serial communication. The well-known RS-232 serial protocol is one of many that operate on this hardware. You probably use this protocol regularly, as it is the one used to communicate over the serial port (via USB) connection to your computer.
A Universal Asynchronous Receiver/Transmitter, abbreviated UART (play /ˈjuːɑrt/), is a type of “asynchronous receiver/transmitter”, a piece of computer hardware that translates data between parallel and serial forms. UARTs are commonly used in conjunction with communication standards such as EIA, RS-232, RS-422 or RS-485. The universal designation indicates that the data format and transmission speeds are configurable and that the actual electric signaling levels and methods (such as differential signaling etc.) typically are handled by a special driver circuit external to the UART.
Almost all ATmega series chips, but only a few of the ATtiny chips (Attiny2313/4313 mainly) support this protocol. Surprisingly, this ATtiny series only comes with a maximum of 4 megabytes of RAM, which rules it out for all but the simplest of projects.
The USART hardware is implemented over the TXD & RXD pins. Its presence also permits fuller support of the SPI protocol than does chips containing USI only (most ATtiny chips).
If you need some basic serial communication on an ATtiny, all hope is not lost. The Arduino IDE has a Software Serial library which implements this protocol in software using two digital pins. The Arduino site also has a nice tutorial on using this library.
CAN and LIN
CAN bus (for controller area network) is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other within a vehicle without a host computer.
CAN bus is a message-based protocol, designed specifically for automotive applications but now also used in other areas such as industrial automation and medical equipment.
CAN bus is one of five protocols used in the OBD-II vehicle diagnostics standard. The OBD-II standard has been mandatory for all cars and light trucks sold in the United States since 1996, and the EOBD standard has been mandatory for all petrol vehicles sold in the European Union since 2001 and all diesel vehicles since 2004.
LIN (Local Interconnect Network) is a serial network protocol used for communication between components in vehicles. The need for a cheap serial network arose as the technologies and the facilities implemented in the car grew, while the CAN network was too expensive to implement for every component in the car. European car manufacturers started using different serial communication topologies, which led to compatibility problems.
Unless your project requires this type of communication ability, most hobbyists can ignore these protocols.
I think it is pretty safe to assume we all know what this protocol is (Universal Serial Bus), and of course we would all love to have it on all our AVR chips. Since this protocol is no doubt more expensive to implement, it is supported on only certain ATmega chips and no ATtiny ones. The ATmega chips used for various Arduinos do not have this capability, but instead rely on external chips or cables to permit basic serial communication and programming.
While some non-Arduino boards use the ATmegaXXU2/4 series boards, until recently these were not supported by the Arduino IDE. With version 1.0 now released of the IDE, it is supported. The official Arduino board is called Leonardo. Since it has not yet been released, the version 1.0 of the IDE has it commented out in the boards.txt file. If you want to use your own project with this chip with the Arduino IDE, simply un-comment the Leonardo board lines. The file is found in this path for your installation:
To re-enable this board, simply open the file in a text editor and look for lines starting with “leonardo”. Remove the pound (#) sign in front of each line and save the file.
There are some other AVR chips such as ATXmega which also support USB natively, but these use 3.3 volts and are therefore not compatible with the Arduino ecosystem.
Native USB provides more than simply eliminating an extra IC. Your Arduino/AVR chip can now function as a USB device. That means instead of being limited to serial communication, the AVR chip can mimic popular USB peripherals such as keyboards and mice. The number of cool applications are endless.
For most of us, our ATmegas and ATtinys do not have built-in USB. In like manner to the Software Serial library, there is a great software implementation for USB communication as well. It is called VUSB (virtual USB), and you can even run it on the ATtiny series chips. Not as high performance as native hardware, it is more than enough for emulating a mouse or keyboard. You can even use it to turn an ATtiny into an ICSP programmer.
This protocol stands for External Bus Interface. According to Wikipedia:
The External Bus Interface, usually shortened to EBI, is a computer bus for interfacing small peripheral devices like flash memory with the processor. It is used to expand the internal bus of the processor to enable connection with external memories or other peripherals. EBI can be used to share I/O pins controlling memory devices that are connected to two different memory controllers. Use of EBI reduces the total number of system pins required causing the system cost to come down.
Since I could not find much more information on this protocol, I believe it to be somewhat specialized and not of much interest to most of us.
This subject could warrant an entire article in itself, but to round out the topic at hand, some mention of some of the many libraries that facilitate communication seems appropriate.
- Arduino to Arduino data transfer – this type of communication could be really useful. One example would be to hook several cheaper data gathering circuits together and send the data back to a more expensive Ethernet capable Arduino.
- Interactive command line screen – easy, text-based means of communication from your PC to your Arduino.
- A file based approach to PC communication – uses files in Linux to log Arduino output
- Command control Arduino over serial line – send commands to your Arduino over a serial line. Can also be done wirelessly.
- Bitlash – a telnet console for Arduino
- Long distance serial communications – inexpensive hardware implementation of the RS485 protocol.
- 2B – another PC control over Arduino library
- A plethora of Ethernet/Web-server libraries – too many to describe
- Lots of I2C libraries – how-tos, and libs for various chips
- Dallas 1-wire stuff – info & libs
- Bluetooth & other wireless libraries – go wireless and communicate via bluetooth, RF links and more
Despite the plethora of communications acronyms, for most there are only four that concern us: I2C/TWI, SPI, UART/USART, and USB. I believe all AVR chips support some level of I2C/TWI and SPI protocols. That leaves only the UART and USB interfaces to consider when choosing an ATmega and ATtiny chip. For practical purposes, those interfaces are only implemented on the ATmega series, and the UART interface is almost ubiquitous in the ATmega line as well.
Furthermore, despite the lack of a UART, the ATtiny series chips can be made to implement UART communication by using a software version of the serial library. You can also make use of the software serial library in ATmega chips as well if you need additional communication lines.
That leaves USB for last. At this time, USB-based Arduinos are still somewhat experimental and the chips are not as common. However, like the UART, a software implementation of the USB interface can be used to add USB functionality to those chips missing native USB, even ATtinys.
Between native hardware and additional software libraries, you can use any of these four communication interfaces on virtually any AVR chip. You now also have the knowledge on what all these acronyms mean and what some of the capabilities they offer. Being able to add either serial or USB support via software to the ATtiny chips is really nice, and the ability to used I2C to hook up other interface chips is great as well.
Please contribute your thoughts and favorite I2C chips in the comments below.