SPI vs I2C in Embedded C: Key Differences and Usage Guide
SPI when you need faster data transfer and multiple devices with dedicated lines, and I2C when you want simpler wiring with fewer pins and moderate speed. SPI is full-duplex and faster, while I2C is half-duplex and supports multi-master setups.Quick Comparison
Here is a quick side-by-side comparison of SPI and I2C protocols for embedded C projects.
| Factor | SPI | I2C |
|---|---|---|
| Communication Type | Full-duplex (simultaneous send/receive) | Half-duplex (send or receive at a time) |
| Number of Wires | 4 (MOSI, MISO, SCLK, SS) | 2 (SDA, SCL) |
| Speed | Up to several Mbps | Typically up to 400 kbps (standard mode), 1 Mbps (fast mode) |
| Complexity | More pins and hardware lines | Fewer pins, simpler wiring |
| Device Addressing | No addressing, uses separate SS lines | Uses 7 or 10-bit addressing |
| Multi-Master Support | No native multi-master | Supports multi-master bus |
| Use Case | High speed, multiple devices with dedicated lines | Simple connections, moderate speed, multiple devices |
Key Differences
SPI (Serial Peripheral Interface) uses separate lines for data input (MISO), data output (MOSI), clock (SCLK), and a slave select (SS) line for each device. This allows full-duplex communication, meaning data can be sent and received at the same time, making it faster for large data transfers. However, it requires more pins and wiring, especially when multiple devices are connected because each device needs its own SS line.
I2C (Inter-Integrated Circuit) uses only two lines: data (SDA) and clock (SCL). It supports multiple devices on the same bus by using unique addresses for each device. Communication is half-duplex, so data is sent or received one way at a time. I2C supports multi-master setups, allowing more than one controller on the bus, but it is slower compared to SPI.
In embedded C, choosing between SPI and I2C depends on your hardware pin availability, speed requirements, and complexity you can manage. SPI is preferred for speed and simplicity in single-master setups, while I2C is better for saving pins and handling multiple devices with simpler wiring.
Code Comparison
Example: Sending a byte (0x55) to a device using SPI in embedded C.
#include <stdint.h> #include <avr/io.h> void SPI_Init() { // Set MOSI, SCK and SS as output DDRB |= (1 << PB3) | (1 << PB5) | (1 << PB2); // Enable SPI, Master mode, set clock rate fck/16 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); } uint8_t SPI_Transmit(uint8_t data) { SPDR = data; // Start transmission while(!(SPSR & (1 << SPIF))) ; // Wait for transmission complete return SPDR; // Return received data } int main() { SPI_Init(); uint8_t received = SPI_Transmit(0x55); while(1) { // Main loop } return 0; }
I2C Equivalent
Example: Sending a byte (0x55) to a device with address 0x50 using I2C in embedded C.
#include <stdint.h> #include <avr/io.h> #define F_SCL 100000UL // SCL frequency #define Prescaler 1 #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2) void I2C_Init() { TWBR = (uint8_t)TWBR_val; } void I2C_Start() { TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); while (!(TWCR & (1 << TWINT))) ; } void I2C_Stop() { TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); } void I2C_Write(uint8_t data) { TWDR = data; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))) ; } int main() { I2C_Init(); I2C_Start(); I2C_Write(0x50 << 1); // Device address + write bit I2C_Write(0x55); // Data byte I2C_Stop(); while(1) { // Main loop } return 0; }
When to Use Which
Choose SPI when:
- You need fast data transfer rates (e.g., audio, displays, sensors with high data rates).
- You have enough pins for multiple device select lines.
- You want full-duplex communication.
Choose I2C when:
- You want to minimize wiring and pin count.
- You have multiple devices on the same bus with unique addresses.
- Your speed requirements are moderate and half-duplex is acceptable.
- You need multi-master support.
In summary, use SPI for speed and simplicity in single-master setups, and I2C for simpler wiring and multi-device communication with fewer pins.