0
0
Power-electronicsComparisonBeginner · 4 min read

SPI vs I2C in Embedded C: Key Differences and Usage Guide

Use 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.

FactorSPII2C
Communication TypeFull-duplex (simultaneous send/receive)Half-duplex (send or receive at a time)
Number of Wires4 (MOSI, MISO, SCLK, SS)2 (SDA, SCL)
SpeedUp to several MbpsTypically up to 400 kbps (standard mode), 1 Mbps (fast mode)
ComplexityMore pins and hardware linesFewer pins, simpler wiring
Device AddressingNo addressing, uses separate SS linesUses 7 or 10-bit addressing
Multi-Master SupportNo native multi-masterSupports multi-master bus
Use CaseHigh speed, multiple devices with dedicated linesSimple 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.

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.

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.

Key Takeaways

SPI offers faster, full-duplex communication but requires more pins and wiring.
I2C uses fewer pins with two-wire communication and supports multiple devices via addressing.
Choose SPI for high-speed, single-master setups with dedicated device lines.
Choose I2C for simpler wiring, multi-device buses, and moderate speed needs.
Embedded C code for SPI and I2C differs mainly in hardware setup and data transfer methods.