SPI (Serial Peripheral Interface) Protokolü

watch_later 1/02/2016
comment 6 Comments
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.


MISO: Çevresel cihazlardan (slave) yollanan verilerin master cihaza aktarıldığı hattır

MOSI: Master cihazdan yollanan verilerin çevresel cihazlara aktarıldığı hattır.

SCK: SPI haberleşmesinde senkronu sağlayan saat sinyalinin bulunduğu hattır. 

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.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 Fritzing Şeması
Arduino Sketch:                        
/* 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...
avatar
Adsız

Çok istifade ettim. paylaşımların devamını diliyorum.

delete 5 Ocak 2016 10:26
avatar

Yorumun için teşekkürler...

delete 5 Ocak 2016 10:28
avatar

En düzgün ve özgün SPI örneği. Teşekkür ederim.

delete 29 Ocak 2017 04:28
avatar

Ben teşekkür ederim takip ettiğin için.

delete 9 Şubat 2017 23:02
avatar

Selam. Ben miso hatlarının kararsızlığı ile karşılaşıyorum galiba. bu yüzden birşey sormak istiyorum aynı modülden 10 adet slave olacak ve aynı zamanda yine bu seri haberleşmesi yapan bir adette 11. olarak sd kart bağlamak istiyorum. nasıl bir yol izlemeliyim. benim amacım kod geliştirmek ve slave cihazları olabildiğince kararlı bir halde çalışturmaktır. 10 adet mfrc522 olsun. örneğin bunun üzerinden kodlama nasıl olabilir.

delete 29 Kasım 2020 03:03
avatar
enes

hocam spi ile adc değer nasıl okunur

delete 16 Mart 2022 23:00



sentiment_satisfied Emoticon