SPI Arduino'nun desteklediği senkron seri
haberleşme türlerinden biridir. Bir Arduino'nun diğer Arduino veya sensörlerle
kısa mesafede haberleşmesini sağlar. Master ve çevresel cihazlara bağlanan MISO
(Master In Slave Out), MOSI (Master Out Slave In) ve SCK (Serial Clock) olmak
üzere üç adet SPI hattı bulunur.
Saat sinyali master cihaz tarafından üretilir. MISO ve MOSI hatlarından da anlaşıldığı gibi SPI protokolünde I2C'den farklı olarak veri hatları tek yönlüdür. Ayrıca çevresel cihazların (slave) adreslerinin olmasına gerek yoktur. Her çevresel cihazın seçim ayağı bulunur. Bu ayağa, SS (Slave Select) denir. Bu hattın sayısı kullanılan çevresel cihazların sayısı kadardır. Her cihaz için master cihazından ayrı SS hattı çıkar. SS hattı LOW (0 volt) düzeyinde olan çevresel cihaz, master cihaz ile iletişime başlar. Örnek olarak SPI haberleşme hattı aşağıdaki resimde gösterilmiştir. Master cihaz iletişime geçmek istediği çevresel cihazın SS pinini LOW (0 Volt) düzeyine çeker
SPI Protokolü Çalışma Prensibi |
Arduino SPI Kütüphanesi
SPI
protokolünü öğrendiğimize göre şimdi haberleşmenin Arduino kısmına bakalım.
Arduino'da SPI fonksiyonlarını kullanabilmemiz için öncelikle "SPI.h"
kütüphanesini projemize eklememiz gerekir. Kütüphane projeye eklendiğinde
aşağıdaki fonksiyonlar kullanılabilir.
SPI
protokolünü öğrendiğimize göre şimdi haberleşmenin Arduino kısmına bakalım.
Arduino'da SPI fonksiyonlarını kullanabilmemiz için öncelikle "SPI.h"
kütüphanesini projemize eklememiz gerekir. Kütüphane projeye eklendiğinde
aşağıdaki fonksiyonlar kullanılabilir.
·
SPI.begin(): SPI haberleşmesini başlatır ve SPI pinlerini
başlangıç konumlarına alır.
·
SPI.setClockDivider(): Bu fonksiyon ile SPI haberleşmesinin saati ayarlanabilir. Fonksiyon değer
olarak saat değişkenlerini almaktadır. Eğer hiçbir değişiklik yapılmazsa SPI
saati "SPI_CLOCK_DIV4" olarak çalışır. Fonksiyonun alabileceği
değişkenler; SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32,
SPI_CLOCK_DIV64, SPI_CLOCK_DIV128'dir.
· SPI.transfer(): SPI hattına veri yollamak veya veri almak için bu fonksiyon kullanılır.
SCK, MISO, MOSI ve SS Bağlantı Pinleri Pinout Diyagramı |
Master board'un kontrolü altındaki bir geçici anahtara her basıldığında Slave board kontrolü altındaki bir ledi yakıp söndürecek devre tasarımı:
/* SPI haberleşmesinde Master*/ #include/* * SPI fonksiyonlarını kullanabilmek için * SPI.h kütüphanesini ekledik */ const int SSpini = 8; /* Slave görevindeki Arduino'nun seçilmesi için 8 numaralı pin SS olarak belirlendi */ void setup() { pinMode(SSpini, OUTPUT); /* SS pini çıkış olarak ayarlandı */ digitalWrite(SSpini, HIGH); /* Slave olan Arduino başlangıçta haberleşmeye geçmemesi için SS pini HIGH yapıldı */ SPI.begin(); /* SPI haberleşmesi başlatıldı */ } void loop() { dataBus(digitalRead(7), SSpini); /* Diğer arduinoya buttondan okunan değer HIGH veya LOW yollandı */ } /* SPI üzerinden veri göndermek için */ void dataBus(int income, int SSpini) { digitalWrite(SSpini, LOW); /* Diğer Arduino'nun veri dinlemeye başlaması için SS hattını LOW'da */ delay(1); /* Kısa bir süre bekleyelim */ int LEDDurum; LEDDurum = SPI.transfer(income); Serial.println(LEDDurum); /* veri karakteri diğer Arduino'ya yollandı*/ digitalWrite(SSpini, HIGH); /* Haberleşmeyi bitirmek için pin HIGH konumunda*/ }
/* SPI haberleşmesinde Slave*/ char i = 0; const int LED = 7; /* LED Arduino'nun 7. pinine bağlanmıştır */ void setup() { pinMode(MISO, OUTPUT); pinMode(SS , INPUT); /* MISO pini OUTPUT, SS pini INPUT olarak ayarlandı */ pinMode(LED, OUTPUT); /* LED pini çıkış olarak ayarlandı */ SPCR |= 0b11000000; SPSR |= 0b00000000; /* Slave mod ve interrupt için ayarlamalar yapıldı */ sei(); /* Interruptlar çalıştırıldı */ } void loop() { delay(100); } /* SPI kesmesi olduğunda çalışacak fonksiyon */ ISR(SPI_STC_vect) { cli(); /* Interruptlar durdurulmuştur */ while (!digitalRead(SS)) { SPDR = i; i ++; if ( i > 255) i = 0; while (!(SPSR & (1 << SPIF))); /* SPI hattında veri aktarımı bitene kadar bekle */ int gelenVeri; gelenVeri = SPDR; if (gelenVeri == HIGH) { digitalWrite(LED, HIGH); } else if (gelenVeri == LOW) { digitalWrite(LED, LOW); } /* SPI üzerinden gelen verinin değerine göre LED'in konumu değiştirildi */ } sei(); /* Interruptlar başlatılmıştır */ }
Bir sonraki yazımda görüşmek üzere...