Capaian Pembelajaran

  • Memahami konsep komunikasi serial synchronous
  • Mengimplementasikan protokol I2C (Two-Wire Interface)
  • Mengimplementasikan protokol SPI (Serial Peripheral Interface)
  • Membedakan karakteristik I2C vs SPI vs UART
  • Menggunakan sensor dengan interface I2C dan SPI

1. Perbandingan Protokol Serial

Setelah mempelajari UART pada pertemuan sebelumnya, sekarang kita akan mempelajari dua protokol serial synchronous yang umum digunakan dalam sistem embedded: I2C dan SPI.

Parameter UART I2C SPI
Type Asynchronous Synchronous Synchronous
Lines 2 (TX, RX) 2 (SDA, SCL) 4+ (MOSI, MISO, SCK, SS)
Speed Slow-Moderate Slow-Moderate Very Fast
Devices Point-to-point Multi-slave (128 devices) Multi-slave (limited by CS)
Complexity Simple Moderate Simple
Best For PC communication Sensors, small ICs High-speed devices

2. Inter-Integrated Circuit (I2C)

Karakteristik I2C

  • Two-wire interface - SDA (Data) dan SCL (Clock)
  • Multi-master capable - Beberapa master dapat mengontrol bus
  • 7-bit addressing - Mendukung hingga 128 devices (112 usable)
  • Speed variants - Standard (100kbps), Fast (400kbps), High-speed (3.4Mbps)
  • Pull-up resistors - Diperlukan untuk kedua line

Frame Data I2C

Sequence Description Purpose
Start Condition SDA turun saat SCL tinggi Memulai komunikasi
Address Frame 7-bit address + R/W bit Memilih slave device
ACK/NACK Bit acknowledge Konfirmasi penerimaan
Data Frames 8-bit data + ACK Transfer data aktual
Stop Condition SDA naik saat SCL tinggi Mengakhiri komunikasi
i2c_master.c - Implementasi I2C Master

#include 
#include 

#define I2C_START 0x08
#define I2C_MT_SLA_ACK 0x18
#define I2C_MT_DATA_ACK 0x28

void I2C_Init() {
    // Set bit rate (100kHz untuk 16MHz clock)
    TWBR = 72;
    // Enable I2C
    TWCR = (1 << TWEN);
}

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)));
}

uint8_t I2C_Read(uint8_t ack) {
    TWCR = (1 << TWINT) | (1 << TWEN) | (ack ? (1 << TWEA) : 0);
    while (!(TWCR & (1 << TWINT)));
    return TWDR;
}

// Contoh: Baca dari sensor I2C (contoh: BMP180)
void BMP180_ReadTemp() {
    I2C_Start();
    I2C_Write(0xEE); // Address BMP180 + Write
    I2C_Write(0xF4); // Register control
    I2C_Write(0x2E); // Perintah baca temperatur
    I2C_Stop();
    
    _delay_ms(5); // Tunggu konversi
    
    I2C_Start();
    I2C_Write(0xEE); // Address BMP180 + Write
    I2C_Write(0xF6); // Register data MSB
    I2C_Start();
    I2C_Write(0xEF); // Address BMP180 + Read
    uint8_t msb = I2C_Read(1); // Read dengan ACK
    uint8_t lsb = I2C_Read(0); // Read dengan NACK
    I2C_Stop();
    
    int16_t temp = (msb << 8) | lsb;
    // Process temperature data...
}
                        

3. Serial Peripheral Interface (SPI)

Karakteristik SPI

  • Four-wire interface - MOSI, MISO, SCK, SS
  • Full-duplex - Dapat mengirim dan menerima bersamaan
  • Very fast - Hingga 10Mbps+ (tergantung device)
  • Simple protocol - Tidak ada addressing complex
  • Multiple slaves - Dengan multiple chip select

Mode SPI (Clock Polaritas dan Phase)

Mode CPOL CPHA Description
0 0 0 Clock idle low, data captured on rising edge
1 0 1 Clock idle low, data captured on falling edge
2 1 0 Clock idle high, data captured on falling edge
3 1 1 Clock idle high, data captured on rising edge
spi_master.c - Implementasi SPI Master

#include 

// Pin definitions
#define SPI_DDR DDRB
#define SPI_PORT PORTB
#define MOSI PB3
#define MISO PB4
#define SCK PB5
#define SS PB2

void SPI_Init() {
    // Set MOSI, SCK, dan SS sebagai output
    SPI_DDR |= (1 << MOSI) | (1 << SCK) | (1 << SS);
    // Set MISO sebagai input
    SPI_DDR &= ~(1 << MISO);
    
    // Enable SPI, Master, set clock rate fck/16
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
}

void SPI_CS_Low() {
    SPI_PORT &= ~(1 << SS);
}

void SPI_CS_High() {
    SPI_PORT |= (1 << SS);
}

uint8_t SPI_Transfer(uint8_t data) {
    // Mulai transmisi
    SPDR = data;
    // Tunggu transmisi selesai
    while (!(SPSR & (1 << SPIF)));
    // Return data yang diterima
    return SPDR;
}

// Contoh: Baca/write ke SPI device (contoh: SD card, flash memory)
void SPI_Example() {
    SPI_Init();
    SPI_CS_Low();
    
    // Kirim command (contoh: read status register)
    SPI_Transfer(0x05);
    // Baca status
    uint8_t status = SPI_Transfer(0x00);
    
    SPI_CS_High();
    
    // Process status data...
}

// Contoh dengan sensor SPI (contoh: MAX6675 - Thermocouple)
float MAX6675_ReadTemp() {
    SPI_CS_Low();
    _delay_us(1);
    
    // Baca 16-bit data
    uint8_t high_byte = SPI_Transfer(0x00);
    uint8_t low_byte = SPI_Transfer(0x00);
    
    SPI_CS_High();
    
    // Combine bytes
    uint16_t data = (high_byte << 8) | low_byte;
    
    // Check error bit (D2)
    if (data & 0x04) {
        return -1.0; // Error
    }
    
    // Extract temperature (D15-D3)
    data = data >> 3;
    return data * 0.25; // Convert to Celsius
}
                        

4. Simulator Protokol I2C & SPI

Simulator Komunikasi Multi-Device

Pilih protokol untuk melihat perbedaan implementasi

Master

Mikrokontroler

SCL
SDA

Slave 1

Address: 0x48

Status: Idle

I2C Bus Ready

Master

Mikrokontroler

SCK
MOSI
MISO
SS

Slave 1

SPI Device

Status: Idle

SPI Bus Ready

Timing Diagram - I2C vs SPI

I2C SCL
I2C SDA
SPI SCK
SPI MOSI

5. Aplikasi I2C & SPI dalam Embedded Systems

Contoh Device dengan I2C

  • Sensor: BMP180 (Pressure), MPU6050 (Accel/Gyro), TMP102 (Temperature)
  • Display: OLED SSD1306, LCD dengan I2C backpack
  • IO Expander: MCP23017 (16-bit I/O expander)
  • RTC: DS3231 (Real Time Clock)

Contoh Device dengan SPI

  • Memory: SD Card, Flash memory (W25Q64)
  • Display: TFT LCD, Graphic OLED
  • Sensor: MAX6675 (Thermocouple), ADXL345 (Accelerometer)
  • Communication: RF module (nRF24L01), Ethernet (ENC28J60)

Tips Pemilihan Protokol

  • Gunakan I2C untuk: Jumlah pin terbatas, banyak device, kecepatan tidak kritikal
  • Gunakan SPI untuk: Kecepatan tinggi, full-duplex communication, simple protocol
  • Gunakan UART untuk: Komunikasi dengan PC, debugging, jarak lebih panjang

Latihan Praktikum

Implementasikan komunikasi dengan sensor I2C dan SPI

Tugas 1: Sensor I2C - BMP180

Buat program untuk membaca data temperatur dan tekanan dari sensor BMP180:

  • Inisialisasi I2C dengan kecepatan 100kHz
  • Kalibrasi sensor dengan membaca calibration data
  • Baca temperatur (raw data dan konversi ke Celsius)
  • Baca pressure (raw data dan konversi ke hPa)
  • Tampilkan data via UART ke PC setiap 2 detik

Tugas 2: Memory SPI - W25Q64 Flash

Buat program untuk membaca dan menulis data ke SPI flash memory:

  • Inisialisasi SPI dengan mode 0 dan kecepatan maksimal
  • Implementasikan fungsi read manufacturer ID
  • Buat fungsi write data ke sector tertentu
  • Buat fungsi read data dari sector
  • Implementasikan sector erase command