Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124

IoT projelerinde, ekranlar (TFT, OLED), SD kart modülleri, RFID okuyucular veya yüksek hassasiyetli harici ADC/DAC entegreleri ile çalışırken I2C protokolünün hızı (400kHz – 1MHz) genellikle yetersiz kalır. Bu senaryolarda devreye, multi megahertz (MHz) mertebelerinde hızlara çıkabilen senkron ve tam çift yönlü (Full-Duplex) çalışan SPI (Serial Peripheral Interface) protokolü girer.
Bu yazıda, SPI protokolünün çalışma mantığını, ESP32 mikrodenetleyicisinin içindeki donanımsal SPI birimlerini ve sahada hayat kurtaran esnek pin atama (Matrix IO) özelliklerini inceliyoruz.


SPI, bir Master (Ana Cihaz) ve bir veya birden fazla Slave (Bağımlı Cihaz) arasında veri aktarımı sağlayan 4 telli bir veri yoludur. Senkron bir protokol olduğu için verinin ne zaman okunacağını belirleyen ortak bir saat sinyali (Clock) hattı bulunur.
ESP32 içinde aslında 4 adet SPI denetleyicisi barındırır (SPI0, SPI1, HSPI ve VSPI). Ancak bunlardan SPI0 ve SPI1, ESP32’nin kendi dahili Flash belleği ve PSRAM’i ile haberleşmesi için ayrılmıştır; geliştirici olarak biz bunlara dokunmayız.
Bizim projelerimizde özgürce kullanabileceğimiz iki adet bağımsız donanımsal SPI birimi vardır: HSPI ve VSPI. İsimlerindeki “H” ve “V” harflerinin donanımsal olarak bir üstünlüğü yoktur (Hardware/Virtual gibi bir ayrım değildir), sadece iki farklı birimi ayırt etmek için verilmiştir. İkisi de aynı hız ve yeteneklere sahiptir.
ESP32’de özel bir kütüphane yapılandırması yapmadan doğrudan SPI.begin() çağırdığınızda, sistem varsayılan olarak VSPI birimini aktif eder.
| Sinyal Adı | VSPI Varsayılan Pin (Default) | HSPI Varsayılan Pin (Default) |
| MOSI | GPIO 23 | GPIO 13 |
| MISO | GPIO 19 | GPIO 12 |
| SCLK | GPIO 18 | GPIO 14 |
| CS / SS | GPIO 5 | GPIO 15 |
ESP32’nin en büyük avantajlarından biri GPIO Matrix mimarisidir. Eğer yukarıda belirtilen varsayılan pinler başka bir sensör veya donanım tarafından işgal edildiyse, SPI hatlarını (MOSI, MISO, SCLK, CS) ESP32’nin hemen hemen istediğiniz herhangi bir GPIO pinine yönlendirebilirsiniz.
Ancak burada dikkat edilmesi gereken kritik bir mühendislik detayı vardır:
💡 IOMUX vs GPIO Matrix: SPI sinyallerini kendi orijinal (yukarıdaki tabloda yer alan) pinlerinde çalıştırırsanız, sinyaller IOMUX üzerinden doğrudan geçer ve $80\text{ MHz}$ gibi çok yüksek frekanslara çıkabilir. Sinyalleri farklı pinlere haritalandırırsanız (GPIO Matrix kullanılır), aradaki anahtarlama katmanı nedeniyle güvenli maksimum hız sınırı $26.6\text{ MHz}$ civarına düşer. Ekran sürerken bu hız farkı önemlidir.
Standart bir SPI cihazını bağlarken ekstra pin belirtmenize gerek yoktur.
C++
#include <SPI.h>
void setup() {
Serial.begin(115200);
// Varsayılan VSPI pinlerini (18, 19, 23, 5) başlatır
SPI.begin();
}
void loop() {
// SPI cihazı ile haberleşme başlatma ayarları
// 10 MHz hızında, MSBFIRST (Önce en yüksek bit) ve SPI_MODE0 frekansında
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(SS, LOW); // Slave cihazı seç
byte gelenVeri = SPI.transfer(0x42); // 0x42 verisini gönder, gelen veriyi oku
digitalWrite(SS, HIGH); // Slave cihazı serbest bırak
SPI.endTransaction();
delay(1000);
}
Eğer pinleri değiştirmek istiyorsanız, begin fonksiyonuna parametre geçmeniz yeterlidir.
C++
#include <SPI.h>
#define CUSTOM_MOSI 25
#define CUSTOM_MISO 26
#define CUSTOM_SCLK 27
#define CUSTOM_CS 14
void setup() {
// Özel pin konfigürasyonu ile SPI hattını ayağa kaldırıyoruz
SPI.begin(CUSTOM_SCLK, CUSTOM_MISO, CUSTOM_MOSI, CUSTOM_CS);
}
void loop() {
// Haberleşme döngüsü burada işletilir
}
Görseldeki şema, endüstriyel ve gömülü sistemlerde sıklıkla kullandığımız I2C (Inter-Integrated Circuit) protokolünün Veri Paketi (Message Frame) yapısını gösteriyor.
İçeriği sitene ekleyebileceğin formatta hem Türkçe görsel tasarımı için metinsel haritasıyla hem de mühendislik mantığına uygun detaylı teknik açıklamasıyla hazırladım.
I2C (Inter-Integrated Circuit), özellikle mikrodenetleyiciler ile kısa mesafedeki sensörler, EEPROM’lar, RTC (Gerçek Zamanlı Saat) modülleri veya donanımsal sürücüler arasında haberleşmeyi sağlayan, sadece 2 tel (SDA: Seri Veri, SCL: Seri Saat) kullanan senkron bir protokoldür.
SPI’dan farklı olarak, hat üzerindeki cihazları seçmek için fiziksel bağımsız hatlar (CS/SS) kullanmak yerine, veri paketinin içerisine gömülmüş Yazılımsal Adresleme mantığını kullanır. Aşağıda, hat üzerinde akan tek bir I2C mesaj paketinin bit seviyesindeki anatomisi yer almaktadır.
Mevcut şemayı Türkçe içeriklerine entegre etmek veya yeniden çizmek (Lucidchart, Canva, Draw.io vb. araçlarla) istersen terim eşleşmeleri ve yerleşim yapısı şu şekildedir:
Plaintext

I2C hattı boştayken (Idle) hem SDA hem de SCL hatları pull-up dirençleri nedeniyle mantıksal 1 (High) seviyesindedir. Haberleşmeyi başlatmak isteyen Master cihaz, SCL hattı hala High seviyesindeyken SDA hattını Low seviyesine çeker. Bu durum hattaki tüm Slave cihazlara “Dinlemeye geçin, yeni bir paket başlıyor” uyarısıdır.
Başlangıç durumundan hemen sonra gelen ilk 7 bit (bazı gelişmiş entegrelerde 10 bit), Master’ın hedeflediği Slave cihazın benzersiz donanımsal adresidir. Hat üzerindeki tüm cihazlar bu adresi okur, ancak sadece kendi adresiyle eşleşen Slave cihaz hatta cevap vermek üzere tetiklenir.
Adres bitlerinin hemen ardından gelen 8. bit, operasyonun yönünü belirler:
0 (Low): Yazma (Write) modudur. Master, Slave cihaza veri göndereceğini bildirir.1 (High): Okuma (Read) modudur. Master, Slave cihazın veri göndermesini bekler.I2C protokolünde her 8 bitlik veri transferinin ardından bir dokuzuncu bitlik “onay” penceresi açılır.
Adres doğrulandıktan sonra asıl taşınmak istenen veri (sensör datası, register adresleri vb.) 8 bitlik (1 Bayt) paketler halinde hatta basılır. Her baytın iletiminden sonra alıcı taraf bir ACK biti döndürmek zorundadır. Paket uzunluğu teorik olarak sınırsızdır; Stop biti gelene kadar ardışık veri çerçeveleri gönderilmeye devam edebilir.
Haberleşmeyi sonlandırmak isteyen Master cihaz, SCL hattı High seviyesindeyken SDA hattını Low’dan High seviyesine çeker. Bu geçiş, hattın tekrar boşa (Idle) çıktığını ve diğer cihazların veya yeni bir paketin hattı kullanabileceğini ilan eder.