Dasar · 11 mnt baca

Apa Itu SPI? Penjelasan Pin MOSI, MISO, SCK, dan CS untuk Arduino

Apa itu SPI dan bagaimana cara kerjanya? Pin MOSI, MISO, SCK, dan CS, mode dan kecepatan SPI, banyak perangkat, pin Uno, Mega, ESP32, dan Pico, serta bentrok kartu SD + RFID.

SPI (Serial Peripheral Interface) adalah metode komunikasi yang memungkinkan mikrokontroler bertukar data dengan sangat cepat dengan perangkat seperti kartu SD, pembaca RFID, layar TFT berwarna, atau modul nirkabel lewat empat kabel. Ada jalur clock (SCK), dua jalur terpisah untuk data di masing-masing arah (MOSI dan MISO), dan jalur CS yang memilih perangkat mana yang sedang diajak bicara. Karena bisa puluhan kali lebih cepat daripada I2C, SPI menjadi bus pilihan untuk modul yang memindahkan data dalam jumlah besar.

Di artikel ini kamu akan belajar cara kerja SPI, nama-nama pin dan penamaan barunya, empat mode SPI, batas kecepatan, pin di Arduino Uno, Mega, ESP32 (VSPI dan HSPI), dan Raspberry Pi Pico, cara menghubungkan beberapa perangkat ke bus yang sama, dan kenapa kartu SD dan pembaca RFID RC522 bermasalah kalau dipakai bersama. Di bagian terakhir kita membandingkan SPI dengan I2C dan UART.

Apa itu SPI dan bagaimana cara kerjanya?

SPI selalu punya satu controller (dulu disebut master) dan satu atau lebih periferal (dulu disebut slave). Hanya controller yang membangkitkan clock; dengan kata lain, Arduino yang memulai percakapan, menentukan kecepatannya, dan mengakhirinya. Pada setiap pulsa clock, controller mengirim satu bit di MOSI dan pada momen yang sama periferal mengirim balik satu bit di MISO. Shift register di kedua sisi membentuk semacam cincin: setelah 8 pulsa clock, byte milik controller sudah pindah ke periferal dan byte milik periferal ke controller. Karena itu SPI bersifat full duplex: membaca dan menulis terjadi bersamaan.

JalurNama lamaNama baruArahPeran
SCK / SCLKSerial ClockSCKController → periferalSinyal clock; satu bit berpindah di setiap pulsa
MOSIMaster Out Slave InCOPI / SDOController → periferalData dari Arduino ke modul
MISOMaster In Slave OutCIPO / SDIPeriferal → controllerData dari modul kembali ke Arduino
CS / SSSlave SelectCS (Chip Select)Controller → periferalModul itu mendengarkan selama CS-nya LOW; setiap perangkat punya CS sendiri

Label di modul tidak selalu sama, dan inilah sumber kebingungan terbesar. Di modul RFID RC522, jalur CS diberi label SDA (tidak ada hubungannya dengan SDA milik I2C), di nRF24L01 namanya CSN, di MCP3008 CS/SHDN, dan di beberapa layar kamu akan melihat nama seperti DIN (MOSI), CLK (SCK), dan DOUT (MISO). Aturannya sederhana: input data (DIN, SDI, MOSI) masuk ke MOSI Arduino dan output data (DOUT, SDO, MISO) masuk ke MISO Arduino.

  1. Controller menarik jalur CS perangkat yang ingin diajak bicara ke LOW. Semua perangkat lain menjaga CS-nya tetap HIGH dan melepaskan jalur MISO.
  2. Controller mulai membangkitkan pulsa clock di SCK.
  3. Pada setiap pulsa, satu bit keluar lewat MOSI dan satu bit masuk lewat MISO. Urutan bit biasanya dimulai dari bit paling signifikan (MSB first).
  4. Setelah jumlah byte yang dibutuhkan (perintah, alamat, data) selesai dipindahkan, controller mengembalikan CS ke HIGH dan perangkat menyelesaikan operasinya.

Mode SPI: CPOL dan CPHA

SPI tidak punya satu standar tunggal; perangkat berbeda-beda dalam level clock ketika diam (CPOL, clock polarity) dan tepi clock tempat data dibaca (CPHA, clock phase). Empat kombinasi dari dua pengaturan ini membentuk empat mode SPI. Kalau controller dan perangkat tidak berada di mode yang sama, data bergeser satu bit dan kamu membaca nilai yang tidak bermakna. Untungnya, sebagian besar modul memakai Mode 0.

ModeCPOLCPHAClock ketika diamTepi pembacaan dataContoh perangkat
SPI_MODE000LOWNaikKartu SD, RC522, nRF24L01, MAX7219, MCP3008, 74HC595
SPI_MODE101LOWTurunBeberapa chip ADC dan driver
SPI_MODE210HIGHTurunJarang dipakai
SPI_MODE311HIGHNaikAkselerometer ADXL345, beberapa layar ST7789 tanpa pin CS
Kalau dari sebuah modul kamu terus membaca 0xFF, 0x00, atau nilai tidak masuk akal yang berbeda-beda setiap kali, cek dulu mode SPI dan kecepatan clock maksimum di datasheet. Menurunkan kecepatan ke 1 MHz lalu mencoba lagi dengan cepat menunjukkan apakah masalahnya di pengkabelan atau di pengaturan.

Kecepatan SPI dan panjang kabel

Di SPI, controller yang menentukan kecepatan, dan batasnya biasanya ada di perangkat itu sendiri. Arduino Uno bisa sampai 8 MHz, setengah dari clock 16 MHz-nya; bawaan library SPI adalah 4 MHz. ESP32 bisa membangkitkan sampai 80 MHz di pin SPI khususnya (IO_MUX), dan batasnya turun ketika sinyal diarahkan ke pin lain lewat GPIO matrix. Raspberry Pi Pico bisa mencapai sekitar 62,5 MHz dengan clock sistem 125 MHz. Sinyal SPI yang cepat butuh kabel pendek: dengan breadboard dan kabel jumper 10–20 cm, beberapa MHz tidak masalah; di 20–30 MHz ke atas, buat kabel sependek mungkin dan pakai sambungan solder kalau bisa. Panjang beberapa meter tidak cocok untuk SPI.

PerangkatPeranClock SPI maksimum (datasheet)Mode SPI
Kartu MicroSDPencatatan data400 kHz di awal, lalu sampai 25 MHzMode 0
RC522 (MFRC522)Pembaca RFID10 MHzMode 0
nRF24L01Nirkabel 2,4 GHz10 MHzMode 0
MAX7219LED matrix / 7-segmen10 MHzMode 0
MCP3008ADC 10-bit 8 kanal3,6 MHz pada 5 V, 1,35 MHz pada 2,7 VMode 0 atau 3
ILI9341TFT berwarna 2,4–3,2 inci10 MHz untuk menulis (dalam praktik digerakkan jauh lebih cepat)Mode 0

Pin SPI: Arduino Uno, Mega, ESP32, dan Raspberry Pi Pico

JalurArduino Uno / NanoArduino MegaESP32 VSPI (bawaan)ESP32 HSPIRaspberry Pi Pico SPI0
SCKD13D52GPIO 18GPIO 14GP18
MOSID11D51GPIO 23GPIO 13GP19 (TX)
MISOD12D50GPIO 19GPIO 12GP16 (RX)
CS (bawaan)D10D53GPIO 5GPIO 15GP17
Level logika5 V5 V3,3 V3,3 V3,3 V

Di Uno, jalur SPI yang sama juga ada di header ICSP 6 pin di tepi board; di board seperti Leonardo dan Micro, SPI hanya tersedia di ICSP. D10 tidak wajib dipakai untuk CS; kamu bisa memakai pin digital mana saja. Namun, di Uno jangan biarkan D10 sebagai input: kalau hardware SPI membaca LOW di D10 ketika pin itu berupa input, ia keluar dari mode controller. SPI.begin() otomatis menjadikan pin ini output, dan jangan kamu ubah menjadi input untuk tugas lain. Di ESP32, objek SPI Arduino memakai VSPI secara bawaan; berkat GPIO matrix, kamu juga bisa memindahkan SPI ke hampir semua pin yang kamu mau. Di Pico, SPI0 dan SPI1 bisa ditempatkan di beberapa kelompok pin yang berbeda (misalnya GP10, GP11, GP12 untuk SPI1); lihat alat Pinout untuk detailnya.

RC522, nRF24L01, dan kartu SD sendiri adalah perangkat 3,3 V. Menyambungkannya langsung ke sinyal 5 V milik Uno bisa merusaknya lama-kelamaan. Sebagian besar modul kartu SD siap pakai sudah punya level shifter; beri daya RC522 dan nRF24L01 dari pin 3V3 dan pertimbangkan konverter level logika di jalur sinyal. ESP32 dan Pico memang sudah bekerja di 3,3 V, jadi langsung kompatibel dengan perangkat ini.

Library SPI Arduino: fungsi dasar

FungsiFungsinya apa?
SPI.begin()Memulai hardware SPI; menjadikan pin SCK, MOSI, dan SS sebagai output.
SPISettings(kecepatan, MSBFIRST, SPI_MODE0)Menyimpan kecepatan, urutan bit, dan mode sebuah perangkat dalam satu objek.
SPI.beginTransaction(pengaturan)Menerapkan pengaturan dan memesan bus untuk perangkat ini; membuat peralihan antarperangkat dengan pengaturan berbeda menjadi aman.
SPI.transfer(byte)Mengirim satu byte dan mengembalikan byte yang diterima pada waktu yang sama.
SPI.transfer16(nilai)Mengirim dan menerima nilai 16-bit sekaligus.
SPI.transfer(buffer, panjang)Mengirim sebuah array; byte yang diterima menimpa array yang sama.
SPI.endTransaction()Melepaskan bus; dipanggil setelah CS dijadikan HIGH.

Contoh pertama: mengirim data ke 74HC595 lewat SPI

Cara termudah memahami SPI adalah dengan shift register 74HC595, karena 595 sebenarnya adalah periferal SPI paling sederhana, yang tidak punya MISO. Pin MOSI Arduino masuk ke input DS milik 595, SCK ke SH_CP, dan D10 ke ST_CP yang berfungsi sebagai latch. Berbeda dengan fungsi shiftOut(), hardware SPI mengirim byte dalam beberapa mikrodetik:

C++ (Arduino IDE)
1// Donanım SPI ile 74HC595: 8 LED'i iki kabloyla sürmek / 74HC595 over hardware SPI: 8 LEDs from two data wires
2// D11 (MOSI) -> DS (14), D13 (SCK) -> SH_CP (11), D10 -> ST_CP / latch (12)
3#include <SPI.h>
4
5const int LATCH_PIN = 10;     // 595'te CS gibi davranır / acts like CS on the 595
6
7void write595(byte value) {
8  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));  // 4 MHz, mod 0 / 4 MHz, mode 0
9  digitalWrite(LATCH_PIN, LOW);
10  SPI.transfer(value);                 // 8 biti gönder / shift out 8 bits
11  digitalWrite(LATCH_PIN, HIGH);       // yükselen kenarda çıkışlara aktar / latch on the rising edge
12  SPI.endTransaction();
13}
14
15void setup() {
16  pinMode(LATCH_PIN, OUTPUT);
17  digitalWrite(LATCH_PIN, HIGH);
18  SPI.begin();
19}
20
21void loop() {
22  for (int i = 0; i < 8; i++) {        // yürüyen ışık / running light
23    write595(1 << i);
24    delay(100);
25  }
26}

Membaca data lewat SPI: ADC MCP3008

Untuk melihat komunikasi full duplex, kita pakai MCP3008. Chip ini menambahkan 8 input analog 10-bit lagi ke Arduino; ini alternatif yang bagus untuk ADC ESP32 yang tidak linier atau Pico yang hanya punya 3 input analog. Dasar-dasar pembacaan analog sudah kami bahas di artikel Apa Itu ADC?. Pengkabelan: CLK → D13, DOUT → D12, DIN → D11, CS → D10, VDD dan VREF → 5V, AGND dan DGND → GND.

C++ (Arduino IDE)
1// MCP3008 (8 kanal, 10 bit ADC) okuma / Reading an MCP3008 (8-channel 10-bit ADC)
2// D13 -> CLK, D12 <- DOUT, D11 -> DIN, D10 -> CS/SHDN
3#include <SPI.h>
4
5const int CS_PIN = 10;
6SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);   // 1 MHz, mod 0 / 1 MHz, mode 0
7
8int readMCP3008(byte channel) {
9  SPI.beginTransaction(mcpSettings);
10  digitalWrite(CS_PIN, LOW);                   // cihazı seç / select the chip
11  SPI.transfer(0x01);                          // başlangıç biti / start bit
12  byte high = SPI.transfer(0x80 | (channel << 4));   // tek uçlu + kanal / single-ended + channel
13  byte low = SPI.transfer(0x00);               // kalan 8 bit / remaining 8 bits
14  digitalWrite(CS_PIN, HIGH);                  // seçimi bırak / release the chip
15  SPI.endTransaction();
16  return ((high & 0x03) << 8) | low;           // 10 bitlik sonuç / 10-bit result
17}
18
19void setup() {
20  Serial.begin(9600);
21  pinMode(CS_PIN, OUTPUT);
22  digitalWrite(CS_PIN, HIGH);                  // başta seçili değil / not selected at start
23  SPI.begin();
24}
25
26void loop() {
27  int raw = readMCP3008(0);
28  float volts = raw * 5.0 / 1023.0;
29  Serial.print("CH0: ");
30  Serial.print(raw);
31  Serial.print("  ");
32  Serial.print(volts, 2);
33  Serial.println(" V");
34  delay(500);
35}

Di sini kita mengirim tiga byte dan menerima tiga byte bersamaan. Byte pertama (0x01) hanya bit start; byte kedua membawa mode single-ended dan nomor kanal, sementara MCP3008 mengirim balik 2 bit teratas dari hasilnya. Byte ketiga adalah 0x00; isinya tidak penting, byte ini hanya dikirim untuk membangkitkan pulsa clock dan menerima 8 bit sisa hasilnya. Di SPI, “membaca” selalu berarti mengirim sesuatu. Hasilnya antara 0 dan 1023 dan diubah ke volt relatif terhadap VREF (di sini 5 V).

Beberapa perangkat SPI: jalur CS terpisah

Perbedaan terbesar SPI dari I2C adalah SPI tidak memakai alamat. Perangkat-perangkat berbagi jalur SCK, MOSI, dan MISO, dan masing-masing mendapat kabel CS sendiri dari Arduino. Hanya perangkat yang CS-nya LOW yang mendengarkan, dan hanya perangkat itu yang menulis data ke MISO. Tiga perangkat butuh 3 + 3 = 6 kabel, lima perangkat 3 + 5 = 8 kabel; jumlah pin bertambah seiring jumlah perangkat. Beberapa chip seperti 74HC595 dan MAX7219 bisa dirangkai berantai (daisy-chain) sebagai gantinya: output satu chip masuk ke input chip berikutnya dan semuanya digerakkan dengan satu CS.

  • Hanya satu CS yang boleh LOW pada satu waktu. Kalau dua perangkat terpilih bersamaan, keduanya bertabrakan di jalur MISO dan kamu membaca data rusak dari keduanya.
  • Di setup(), jadikan dulu setiap pin CS sebagai output dan tarik ke HIGH, baru setelah itu jalankan library-nya. Pin CS yang mengambang bisa secara acak terbaca LOW dan merebut bus.
  • Pakai beginTransaction untuk setiap perangkat. Kartu SD mungkin mau 25 MHz dan MCP3008 1 MHz; transaksi menerapkan kecepatan dan mode yang benar secara otomatis di setiap peralihan.
  • Kalau kamu memakai SPI di dalam interrupt, beri tahu library dengan SPI.usingInterrupt(), atau jangan lakukan pekerjaan SPI di dalam interrupt.
  • Menambahkan pull-up 10 kΩ di jalur CS setiap perangkat mencegah perangkat memilih dirinya sendiri ketika Arduino sedang boot atau reset.

Kartu SD dan RFID di bus yang sama: kenapa tidak jalan?

Pertanyaan klasik di forum Arduino: RFID RC522 bekerja kalau sendirian, modul kartu SD bekerja kalau sendirian, tetapi ketika keduanya ada di bus SPI yang sama, salah satu atau keduanya diam. Bahkan ketika pin CS sudah benar di software, masalahnya biasanya ada di hardware. Banyak modul kartu SD murah punya chip buffer 74LVC125 yang mengubah sinyal 5 V menjadi 3,3 V, dan kanal chip ini yang menggerakkan jalur MISO selalu aktif. Jadi, bahkan ketika CS kartu SD HIGH, modul tidak melepaskan MISO; ketika RC522 mencoba menjawab, jalur itu diperebutkan oleh dua output.

  • Pilih modul yang tepat: modul yang membuat MISO berimpedansi tinggi ketika CS HIGH bisa berbagi bus tanpa masalah. Untuk tahu apakah sebuah modul melepaskan jalurnya, tarik MISO lewat 10 kΩ ke GND lalu ke 5 V dengan CS HIGH, dan ukur dengan multimeter.
  • Hubungkan pin enable buffer ke CS: kalau kamu sudah terbiasa menyolder, mengangkat pin OE kanal MISO pada 74LVC125 dari GND lalu menyambungkannya ke jalur CS modul akan membereskan masalah ini untuk selamanya.
  • Tambahkan resistor seri di MISO: memasang resistor seri sekitar 1 kΩ di output MISO modul SD membuat RC522 bisa mengalahkan jalur itu. Ini solusi darurat yang mudah tetapi membatasi kecepatan.
  • Pakai bus SPI terpisah: di ESP32, kalau kartu SD kamu sambungkan ke VSPI dan RC522 ke HSPI, kedua perangkat tidak pernah bertemu. Uno tidak punya SPI hardware kedua, jadi pilihan ini tidak ada di sana.
  • Perhatikan urutan start: pertama jadikan semua pin CS HIGH, lalu panggil SPI.begin(), lalu SD.begin() dan PCD_Init(). Contoh di bawah mengikuti urutan ini.
C++ (Arduino IDE)
1// Aynı SPI hattında SD kart ve RC522 RFID / SD card and RC522 RFID on the same SPI bus
2// Ortak / shared: D11 MOSI, D12 MISO, D13 SCK. CS: SD -> D4, RC522 SDA(SS) -> D10, RC522 RST -> D9
3#include <SPI.h>
4#include <SD.h>
5#include <MFRC522.h>
6
7const int SD_CS = 4;
8const int RFID_CS = 10;
9const int RFID_RST = 9;
10
11MFRC522 rfid(RFID_CS, RFID_RST);
12
13void setup() {
14  Serial.begin(9600);
15  // Önce TÜM CS pinlerini HIGH yap: hiçbir cihaz hattı meşgul etmesin
16  // First drive ALL CS pins HIGH so no device grabs the bus
17  pinMode(SD_CS, OUTPUT);
18  digitalWrite(SD_CS, HIGH);
19  pinMode(RFID_CS, OUTPUT);
20  digitalWrite(RFID_CS, HIGH);
21
22  SPI.begin();
23  if (!SD.begin(SD_CS)) {
24    Serial.println(F("SD bulunamadi / SD not found"));
25  }
26  rfid.PCD_Init();
27  Serial.println(F("Karti okut / Scan a card"));
28}
29
30void loop() {
31  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
32
33  String uid = "";
34  for (byte i = 0; i < rfid.uid.size; i++) {
35    if (rfid.uid.uidByte[i] < 0x10) uid += "0";
36    uid += String(rfid.uid.uidByte[i], HEX);
37  }
38  rfid.PICC_HaltA();
39
40  File f = SD.open("kartlar.txt", FILE_WRITE);   // kütüphane CS'yi kendisi yönetir / the library handles CS itself
41  if (f) {
42    f.print(millis());
43    f.print(";");
44    f.println(uid);
45    f.close();
46    Serial.println("Kaydedildi / Saved: " + uid);
47  } else {
48    Serial.println(F("Dosya acilamadi / File open failed"));
49  }
50}

Di kode ini, library SD dan library MFRC522 menjadikan pin CS-nya masing-masing LOW dan HIGH sendiri; yang perlu kamu lakukan hanya membiarkan keduanya HIGH di awal dan memastikan hardware berbagi MISO dengan benar. Kode ini menulis UID setiap kartu yang dipindai, bersama timestamp, ke file kartlar.txt (nama file bahasa Turki untuk “kartu-kartu”). Di Uno, kedua library ini bersama-sama memakai sekitar setengah RAM; makro F() menghemat ruang dengan menyimpan teks konstan di flash.

VSPI dan HSPI di ESP32: dua bus SPI terpisah

ESP32 punya empat unit SPI di dalamnya; SPI0 dan SPI1 dipakai khusus untuk memori flash internal, sehingga tersisa VSPI (SPI3) dan HSPI (SPI2) untukmu. Memakai keduanya adalah cara paling rapi untuk memisahkan perangkat dengan kecepatan dan mode yang sangat berbeda atau untuk menghindari bentrok MISO di atas. Di core Arduino, kamu membuat objek SPIClass untuk bus kedua dan memberinya pin dengan begin(). Kode di bawah menjalankan kartu SD di VSPI bawaan dan MCP3008 di HSPI, lalu menambahkan satu pembacaan ke file CSV setiap detik:

C++ (Arduino IDE)
1// ESP32: iki ayrı SPI hattı / two separate SPI buses
2// VSPI (varsayılan SPI / default SPI): SD kart / SD card -> SCK 18, MISO 19, MOSI 23, CS 5
3// HSPI: MCP3008 -> SCK 14, MISO 12, MOSI 13, CS 15
4#include <SPI.h>
5#include <SD.h>
6
7const int SD_CS = 5;
8const int ADC_CS = 15;
9
10SPIClass hspi(HSPI);                              // ikinci donanım SPI / second hardware SPI
11SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);
12
13int readMCP3008(byte channel) {
14  hspi.beginTransaction(mcpSettings);
15  digitalWrite(ADC_CS, LOW);
16  hspi.transfer(0x01);
17  byte high = hspi.transfer(0x80 | (channel << 4));
18  byte low = hspi.transfer(0x00);
19  digitalWrite(ADC_CS, HIGH);
20  hspi.endTransaction();
21  return ((high & 0x03) << 8) | low;
22}
23
24void setup() {
25  Serial.begin(115200);
26  pinMode(ADC_CS, OUTPUT);
27  digitalWrite(ADC_CS, HIGH);
28  hspi.begin(14, 12, 13, ADC_CS);                 // SCK, MISO, MOSI, SS
29
30  if (!SD.begin(SD_CS)) {                         // SD varsayılan VSPI'yi kullanır / SD uses the default VSPI
31    Serial.println("SD bulunamadi / SD not found");
32  }
33}
34
35void loop() {
36  int raw = readMCP3008(0);
37  File f = SD.open("/olcum.csv", FILE_APPEND);    // ekle kipinde aç / open in append mode
38  if (f) {
39    f.printf("%lu,%d\n", millis(), raw);
40    f.close();
41  }
42  Serial.printf("CH0: %d\n", raw);
43  delay(1000);
44}
GPIO 12, pin MISO milik HSPI, adalah salah satu pin boot (strapping) ESP32: kalau pin ini HIGH ketika boot, board mengira flash bekerja di 1,8 V dan tidak mau menyala. Jangan sambungkan modul yang punya resistor pull-up di MISO (seperti kebanyakan modul kartu SD) ke HSPI, atau pindahkan MISO ke pin lain. Karena itu kartu SD di contoh ini dipasang di VSPI.

SPI dengan Raspberry Pi Pico (MicroPython)

Pico punya dua unit SPI hardware (SPI0 dan SPI1), yang di MicroPython dipakai lewat kelas machine.SPI. Parameter polarity dan phase sesuai dengan CPOL dan CPHA; kalau keduanya 0, itu Mode 0. CS kamu atur sendiri sebagai pin output biasa. Fungsi write_readinto() paling baik menunjukkan sifat full duplex SPI: sambil mengirim satu array, ia menulis byte yang masuk ke array lain. Kita baca MCP3008 yang sama, kali ini dengan daya 3,3 V:

MicroPython
1# Raspberry Pi Pico: SPI0 ile MCP3008 okuma / reading an MCP3008 on SPI0
2# GP18 -> CLK, GP19 -> DIN (MOSI), GP16 <- DOUT (MISO), GP17 -> CS. MCP3008 VDD ve VREF 3V3 / VDD and VREF on 3V3
3from machine import Pin, SPI
4import time
5
6spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0,   # mod 0 / mode 0
7          sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8cs = Pin(17, Pin.OUT, value=1)                          # başta seçili değil / not selected at start
9
10def read_mcp3008(channel):
11    tx = bytearray([0x01, 0x80 | (channel << 4), 0x00])
12    rx = bytearray(3)
13    cs.value(0)                                          # cihazı seç / select the chip
14    spi.write_readinto(tx, rx)                           # aynı anda gönder ve al / send and receive at once
15    cs.value(1)
16    return ((rx[1] & 0x03) << 8) | rx[2]
17
18while True:
19    raw = read_mcp3008(0)
20    print("CH0:", raw, "{:.2f} V".format(raw * 3.3 / 1023))
21    time.sleep(0.5)

Perbandingan SPI vs I2C vs UART

FiturSPII2CUART
Jumlah kabel4 (+1 CS untuk setiap perangkat tambahan)2 (SDA, SCL)2 (TX, RX)
Kecepatan umum1–80 MHz100 kHz, 400 kHz, 1 MHz9600–115200 baud (sampai beberapa Mbit/s)
ClockAda (dibangkitkan controller)Ada (dibangkitkan controller)Tidak ada; kedua sisi menyepakati baud rate yang sama
ArahFull duplexHalf duplexFull duplex
Pemilihan perangkatKabel CS terpisahAlamat 7-bitHanya dua perangkat (point to point)
Komponen tambahanTidak perluResistor pull-upTidak perlu
JarakPendek (di board, beberapa puluh cm)Pendek (sekitar 1 m)Beberapa meter; jauh lebih panjang dengan RS-485
Modul umumKartu SD, RC522, TFT, nRF24L01, MAX7219OLED, backpack LCD I2C, RTC, BME280, MPU6050GPS, HC-05, SIM800L, ESP-01, komputer

Pilihannya biasanya ditentukan oleh modul, tetapi di desainmu sendiri aturan ini membantu: kalau kecepatan dan volume data penting (gambar di layar, file, audio), pakai SPI; kalau kamu butuh sedikit kabel dan banyak sensor lambat, pakai I2C; kalau kamu mau koneksi sederhana berbasis teks di antara dua perangkat, pakai UART. Penjelasan lengkap UART ada di artikel Komunikasi Serial UART. Memakai ketiganya di proyek yang sama juga sangat umum: misalnya data logger yang membaca sensor lewat I2C, menulis ke kartu SD lewat SPI, dan mengambil posisi dari GPS lewat UART.

Modul yang memakai SPI dan ide proyek

  • Kunci pintu berkartu dan log akses: baca kartu dengan RC522 lalu tulis tanggal dan UID ke kartu SD.
  • Pencatat suhu: rekam data sensor ke kartu microSD sebagai CSV lalu buat grafiknya di Excel.
  • Papan teks berjalan: tampilkan jam dan pesan di modul LED matrix MAX7219 yang dirangkai berantai.
  • Antarmuka berwarna: gambar grafik dan menu di layar TFT ILI9341; sambungkan juga panel sentuhnya ke bus SPI yang sama.
  • Remote nirkabel: kirim perintah ke mobil robotmu dengan dua modul nRF24L01.
  • Pengukuran multikanal: buat controller MIDI dengan 8 potensiometer atau sistem penyiraman dengan 8 sensor kelembapan tanah memakai MCP3008.

Kesalahan umum dan cara memperbaikinya

GejalaKemungkinan penyebabSolusi
Selalu membaca 0xFF atau 0x00MISO tidak tersambung, MOSI dan MISO tertukar, atau perangkat tidak mendapat dayaSambungkan DIN ke MOSI dan DOUT ke MISO; ukur VCC perangkat
Nilainya tidak masuk akal atau bergeser satu bitMode SPI salah atau clock terlalu cepat untuk perangkatPakai mode dari datasheet, turunkan kecepatan ke 1 MHz, lalu coba lagi
Dua perangkat yang bekerja kalau sendirian tidak mau bekerja bersamaSalah satu modul tidak melepaskan MISO, atau pin CS tidak HIGH di awalJadikan semua pin CS HIGH lebih dulu; ganti modul yang tidak melepaskan MISO atau pakai bus SPI terpisah
SPI tiba-tiba berhenti di UnoD10 dipakai sebagai input dan tertarik ke LOWBiarkan D10 sebagai output; kamu bisa memakainya sebagai CS
ESP32 tidak mau boot ketika HSPI tersambungGPIO 12 tertahan HIGH ketika bootPindahkan MISO yang ber-pull-up ke VSPI atau pilih pin lain untuk MISO
Error acak di kabel panjangPantulan dan derau pada sinyal cepatPerpendek kabel, turunkan kecepatan, jalankan kabel GND di samping kabel sinyal
Logic analyzer 8 kanal yang murah sangat berguna untuk melihat apa yang terjadi di SPI: alat ini merekam SCK, MOSI, MISO, dan CS bersamaan dan menerjemahkan byte mana yang keluar dan mana yang kembali. Begitu kamu bilang “kodenya benar tapi tidak jalan”, alat ini menunjukkan dalam hitungan detik apakah masalahnya di pengkabelan atau di pengaturan.

SPI adalah bahasa bersama modul-modul cepat di dunia Arduino, dari kartu SD sampai layar berwarna: begitu kamu memahami empat kabel, logika CS, dan empat mode, menyambungkan modul SPI baru hanya butuh beberapa menit. Di aplikasi BlueGrays kamu bisa menemukan proyek membaca kartu RFID dan kunci pintu, pencatat suhu microSD, serta jam dot matrix MAX7219, langkah demi langkah lengkap dengan skema rangkaian dan kode.

Pertanyaan umum

SPI singkatan dari apa?

SPI adalah singkatan dari Serial Peripheral Interface. SPI memungkinkan controller bertukar data dengan cepat dan sinkron dengan periferal lewat empat jalur: SCK, MOSI, MISO, dan CS.

Apa itu MOSI dan MISO?

MOSI (Master Out Slave In) adalah jalur data dari controller ke periferal; MISO (Master In Slave Out) adalah jalur data dari periferal kembali ke controller. Dalam penamaan baru, keduanya juga disebut COPI dan CIPO. Di modul, DIN biasanya masuk ke MOSI dan DOUT ke MISO.

Pin SPI di Arduino Uno yang mana saja?

Di Arduino Uno dan Nano, SCK adalah D13, MISO D12, MOSI D11, dan CS bawaan D10. Jalur yang sama juga ada di header ICSP 6 pin pada board. Di Arduino Mega, SCK adalah D52, MISO D50, MOSI D51, dan CS D53.

Apa bedanya SPI dan I2C?

SPI memakai empat kabel, bersifat full duplex, dan bisa berjalan di puluhan MHz; setiap perangkat butuh kabel CS sendiri. I2C hanya memakai dua kabel dan memilih perangkat lewat alamat, tetapi berjalan di kecepatan yang jauh lebih rendah seperti 100–400 kHz dan butuh resistor pull-up.

Berapa banyak perangkat yang bisa disambungkan ke satu bus SPI?

Secara teori tidak ada batasnya; yang kamu butuhkan hanya satu pin CS kosong di controller untuk setiap perangkat. Dalam praktik, masalah muncul di kecepatan tinggi seiring bertambahnya kapasitansi bus dan panjang kabel. Kalau pinnya habis, kamu bisa memperbanyak jalur CS dengan dekoder 74HC138 atau memakai perangkat yang bisa dirangkai berantai (daisy-chain).

Kenapa kartu SD dan pembaca RFID tidak mau bekerja di bus SPI yang sama?

Level shifter di banyak modul kartu SD murah tidak melepaskan jalur MISO bahkan ketika CS HIGH, dan ini merusak jawaban RC522. Solusinya: pakai modul yang melepaskan MISO dengan benar, hubungkan pin enable chip buffer ke CS, atau pasang kedua perangkat di bus SPI terpisah pada ESP32.

Lihat semua proyek
Membaca Nilai RFID
#53Pemula
Premium

Membaca Nilai RFID

Gantungan kunci akses gedung atau kartu aksesmu menyimpan nomor ID rahasia, dan proyek ini membacanya. Dekatkan kartu ke pembaca RFID dan Arduino menulis nomor kartunya ke layar komputermu. Langkah pe

4.7(47)
61
Autentikasi RFID
#54Menengah
Premium

Autentikasi RFID

Persis seperti akses kartu di pintu apartemen: kamu mendekatkan kartumu ke pembaca RFID, dan Arduino membandingkan nomornya dengan yang tersimpan. Kartu yang benar menyalakan LED hijau selama tiga det

4.8(64)
83
Pembaca Kartu RFID RC522 ESP32 (dengan LCD)
#123Menengah

Pembaca Kartu RFID RC522 ESP32 (dengan LCD)

Di proyek ini, kita menyambungkan modul RFID RC522 berbasis MFRC522 ke ESP32 lewat SPI dan membaca UID kartu/tag. Ini menjadi dasar untuk aplikasi seperti kunci pintu, sistem keanggotaan, dan kontrol akses. Kita menampilkan UID yang terbaca di layar LCD; versi ini tidak membandingkannya dengan daftar kartu yang diizinkan. PERINGATAN: RC522 hanya bekerja di 3.3V; memberinya 5V akan membakar modulnya!

4.8(21)
39
Kunci Pintu RFID ESP32 (RC522 + Servo + OLED + Buzzer + LED)
#137Mahir
Premium

Kunci Pintu RFID ESP32 (RC522 + Servo + OLED + Buzzer + LED)

Kita membuat kunci pintu pintar dengan ESP32, modul RFID RC522, motor servo SG90, layar OLED SSD1306, buzzer aktif, dan 2 LED. Ketika sebuah kartu dipindai, UID-nya dibandingkan dengan daftar kartu resmi yang disimpan di kode; jika resmi, motor servo berputar untuk membuka kunci (LED hijau + 2 bunyi bip pendek), dan pintu otomatis terkunci lagi setelah 5 detik. Untuk kartu tidak resmi, LED merah menyala, peringatan diberikan dengan 3 bunyi bip cepat, dan UID yang terbaca ditampilkan di layar.

4.8(9)
15
Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)
#144Mahir
Premium

Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)

Buat pencatat suhu bercap waktu dengan ESP32! Baca suhu/kelembapan DHT22 setiap menit, ambil waktu sebenarnya dari RTC DS1307, dan catat ke kartu microSD sebagai CSV. OLED menampilkan suhu langsung (font besar), kelembapan, cap waktu, dan penghitung catatan. File /temp_log.csv bisa dibuka di Excel, Google Sheets, atau Python pandas; cocok untuk rumah kaca, suhu kamar, data laboratorium, penyimpanan makanan, atau sarang lebah.

4.7(7)
12
Jam dan Kalender Dot Matrix (MAX7219, DS1307)
#84Menengah
Premium

Jam dan Kalender Dot Matrix (MAX7219, DS1307)

Papan bercahaya untuk meja atau dinding yang menampilkan waktu dan tanggal dengan teks berjalan. Layar LED 8x32 menampilkan jam berangka besar dengan dua titik yang berkedip setiap detik; di awal seti

5.0(37)
59
Animasi LED dan Teks Matrix 4x 32x8
#90Menengah
Premium

Animasi LED dan Teks Matrix 4x 32x8

Tumpuk empat modul LED matrix panjang dan kamu mendapat layar persegi dengan lebih dari seribu titik cahaya. Pertama, huruf-huruf berjatuhan dari atas seperti hujan di film, lalu tirai terbuka dan dua

4.6(40)
66
Ular Piksel Matrix 8x8
#88Mahir
Premium

Ular Piksel Matrix 8x8

Buat sendiri dan mainkan game ular klasik. Di matrix lampu 8x8 yang berwarna-warni, kamu mengarahkan ular hijau dengan joystick dan memakan apel merah; di setiap apel ular bertambah panjang, sedikit l

4.7(39)
57