ARDUINO UNO Pin Değişim Kesmesi - Pin Change Interrupt

Arduino Uno kartında kullanılan Atmega328P işlemcisi için kesmeleri incelediğimizde mevcut olan Timer kemeleri ve 2 ve 3 numaralı pinler ile kullanılan harici kesmeler dışında pek de bahsedilmeyen bir kesme türü daha var. Bu kesmenin adı pin değişim kesmesi (PCI - Pin Change Interrupt).

Bu kesmeyi incelediğimizde adından da anlaşılacağı üzere belirlenen herhangi bir pinin lojik seviyesinde (HIGH veya LOW) herhangi değişim meydana geldiğinde yani HIGH iken LOW olduğunda veya LOW iken HIGH olduğunda kesme rutini çalıştırılır. Peki hangi pinlerde bu şiklde kesme oluşur? Arduino Uno ya ait bütün pinleri kullanarak bu şekilde kesme rutinleri çalıştırabiliriz.
Pin değişim kesmesini kullanabilmek için Arduino paltformundan bir miktar ayrılarak Atmega328P işlemcisini fiziksel yapısına ve kendi iç kaydedicilerine (register) müdehale etmemiz gerekecek. İşlemcimizi incelediğimizde PortB, PortC, PortD olmak üzere 3 adet fiziksel portları mevcut. Yukarıdaki resimden bu portların hangi bacaklar üzerinden kullanabileceğimizi görebiliriz. Yeşil renkli olan pinler PORTC, Sarı renkli olan pinler PortB, Mavi renkli olan pinler ise PortD için ayrılmış pinlerdir. Bu portlara ait bütün pinler için kesme tanımlayarak kullanabiliriz. Dikkat etmemiz gereken şey ise PortD0 ve PortD1 pinleri (Arduino Uno için D0 ve D1 pinleri) seri haberleşme için kullanıldığından dolayı başka bir yerde kullanmak işlemciye program atarken problem oluşturabilmektedir.

Şimdi örnek bir program ile devam edelim. Arduino Uno üzerinde örneğin D7 pini ve A0 pini için aynı program içinde çalışan iki ayrı kesme oluşturalım. Bu pinlere yerleştirilen butonlara basıldığında kesme alt programı çağrılsın ve seri port üzerinden bilgisayara veri göndersin.

Burada dikkat etmemiz gereken nokta kesmeleri tanımlarken her bir port isimi için belirlenmiş kesme isimleri isimleri var ve bu isimlere dikkat etmemiz gerekiyor. PortB için PCI0, PortC için PCI1, PortD için PCI2 isimlerini kullanacağız. Şimdi kodlarımıza bakalım...

//.................................................................................................................................................................

#define buton1 A0 //Kesme karşılığı PCINT8
#define buton2 7 //Kesme karşılığı  PCINT23

//cbi ve sbi define fonksiyonları program içerisinde kesme bitlerini ayarlamak için kullanılacaktır
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))    //sfr adresindeki beliritlen biti LOW yapar
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))     //sfr adresindeki beliritlen biti HIGH yapar



void setup() {

  Serial.begin(9600);//Seri haberleşme başlatıldı


  pinMode(buton1, INPUT);
  digitalWrite(buton1, HIGH);
  pinMode(buton2, INPUT);
  digitalWrite(buton2, HIGH);


  //Kesme isimlerini ve kesme için kullanılacak olan pinleri belirleyelim
  sbi (PCICR, PCIE2);    // PCI2 (PortD için) kesmesi aktif hale getirildi
  sbi (PCMSK2, PCINT23); // PortD nin 7. pini (Arduino 7 numaralı digital pini)kesme için tanımlandı

  sbi (PCICR, PCIE1);   // PCI1 (PortC için) kesmesi aktif hale getirildi
  sbi (PCMSK2, PCINT8); // PortC nin 0. pini (Arduino A0 numaralı Analog pini)kesme için tanımlandı

}


void loop()
{

  //İşlmeler kesme içinde yapıldığı için ana döngü içinde bir şey yapmaya gerek yoktur.
}


//Bu kesme alt programları belirlenen pinler HIHG-->LOW veya LOW-->HIGH olduğunda çalışacaktır.
//Yani her durum değişikliğinde kesme çağrılacaktır.

ISR (PCINT2_vect)//PCI2 (PortD) kesme alt programı. Kesme oluştuğunda çalışacak olan kodlar
{
Serial.println("PortD Kesmesi oluştu");
}

ISR (PCINT1_vect)//PCI1 (PortC) kesme alt programı. Kesme oluştuğunda çalışacak olan kodlar
{
Serial.println("PortC Kesmesi oluştu");
}