28 Haziran 2025 Cumartesi

 



Basitçe kesme, Arduino’da kullanılan işlemcimizin, bizim belirlediğimiz bir anda yapmakta olduğu işi bırakıp, bizim istediğimiz işi yapması ve sonra kaldığı yerden devam etmesidir.

Bildiğiniz üzere Arduino gibi tek işlemci birimine (veya tek çekirdekli)  sahip donanımlarda herhangi bir işletim sistemi (RTOS) kullanılmadığı durumlarda işlem sırası yukarıdan aşağıya doğru sıra ile gerçekleşir. Normal şartlar altında bu sıra asla terk edilmez ve girişlerdeki değişikler sırası geldiğinde kontrol edilir. Ancak çok uzun yazılım içeren veya içerisinde yüksek bekleme süresine sahip uygulamalarda düşük tepki süresine ihtiyaç duyulduğunda pinin okunma sırasını beklemek çok geç kalınmasına sebep olabilir. Bu gibi durumlarda kesmeler (Interrupt) çokça işe yararlar.

Akıllarda daha iyi otursun diye bir örnek vermek gerekirse; siz belirli aralıklar ile bilgisayarınızda belirli işleri yapıyorsunuz. Bilgisayar başında ödevinizi yapıp, ders çalışıyorsunuz. Ve aniden kapı çalıyor. Ne yaparsınız? Tabi ki de yaptığınız işi bırakıp kapıyı açar daha sonra yarım kalan işe geri dönersiniz. İşte bu örnekte, hali hazırda yapmakta olduğunuz iş Arduino için örnek vermek gerekirse, void loop() fonksiyonu, kapının çalması ise kesme yani interrupt’tur.

Örneğin bizim arduino’nun interrupt pinlerine bağlı bir butonumuz olsun. Normal şartlarda interrupt kullanmadan direk buton kodu ile if-else şeklinde butonu kullanmayı denersek kodumuz sadece if kısmı geldiğinde butona basılıp basılmadığını kontrol edecek ve o zaman if’in içine girebilecek. Örneğin 5 saniye yanıp 5 saniye sönen bir ledimiz olsun ve butona basıldığında ledin yanıyorsa sönmesini, sönük durumda ise yanmasını isteyelim. Bu durumda koddaki 5 saniyelik delay kısmında butona istediğimiz kadar basalım kod beklemede olduğu için hiç bir işlemi yerine getiremeyecektir. İşte bu noktada devreye interrupt giriyor. Interrupt, kod delay fonksiyonu içinde bile olsa devreye girip istenilen işlemleri yaptırabiliyor. Yani kısaca interrupt, anlık müdahale yapmamız gereken yerlerde kullanılıyor.

Kesmelerin Geçici Olarak Devre Dışı Bırakılması

Kesmeler, belirli önemli görevlerin arka planda gerçekleşmesine izin verir ve varsayılan olarak etkindir. Bazen, belirli koşullar altında, kodunuzda kritik bir bölüme ihtiyacınız olabilir. Kesmeler, kodun zamanlamasını hafifçe bozabildiği için bu kritik bölümde CPU'nun kesintiye uğramadan çalışmasını isteriz. İşte böyle bir durumla karşılaştığımızda kesmeleri geçici olarak devre dışı bırakıp sonra tekrar aktif hale getirebiliriz.

Arduino (Atmega328p) bu amaçla kullanabileceğiniz global bir kesme etkinleştirme/devre dışı bırakma kontrol bitine sahiptir. Bunlar:

noInterrupts ( ) :Küresel kesmeleri devre dışı bırakır.

interrupts ( )   :Küresel kesmeleri devre dışı bırakıldıktan sonra yeniden etkinleştirir.

void setup() {}

 

void loop()

{

     noInterrupts();

     // Kritik bölüm

     interrupts();

     // Kodun Geri Kalanı

}


Yukarıdaki komutlara alternatif olarak, aynı işlevselliği sağlayan ancak makro oldukları için çok daha hızlı olan iki Arduino makrosu (fonksiyonu) vardır. Arduino'nun Atmega328p mikrodenetleyicisinin talimat setinde SEI ve CLI birleştirme talimatları vardır. Bu iki makro aşağıdaki gibidir:

cli ():Kesme genel etkinleştirme bayrağı bitini temizle (tüm kesmeleri devre dışı bırak).

sei ():Kesme genel etkinleştirme bayrağı bitini ayarla (kesmeleri devre dışı bıraktıktan sonra yeniden etkinleştir).

void setup() {}

 

void loop()

{

     cli();

     // Kritik bölüm

     sei();

     // Kodun Geri Kalanı

}

 

NOT: Kesmelerin devre dışı bırakılması, zamanlama işlevlerini (milisaniye, mikro ve gecikme işlevleri gibi), gelen iletişimi ve bazı işlemleri bozacağından kullanımı mümkün olduğunca en aza indirilmelidir.

  

Arduino’da dış kesme, zaman kesmesi, pin değişim kesmesi ve haberleşme kesmesi gibi kesmeler bulunmaktadır. Haberleşme kesmeleri dış kesmenin haberleşme donanımlarında bulunan modelidir. Örneğin; seri porttan veri gelmesi durumunda yapılmasını istediğimiz işlemler varsa bu kesmeler sayesinde gerçekleştirilebilir.


1-   Dış Kesme(External Interrupt)

Dış kesmeler, Arduino’nun özel pinlerinde gerçekleşen voltaj değişimlerini takip eden kesmelerdir. Örneğin Arduino’nun dış kesme pinine bağlanmış bir düğmeye basıldığında, dış kesme Arduino’ya otomatik olarak haber verir.

Arduino kartlarının her birisinin dış kesme pini vardır. Arduino Uno için bu pinler Dijital 2 ve 3 numaralı pinlerdir. Bu pinlerden arduino sürekli olarak dinleme yapabilir ve pindeki voltaj değişimlerini anında algılayabilir.


Aşağıdaki tabloda Arduino türlerine göre dış kesme özelliğine sahip pinler gösterilmiştir.

Board

Kesme için kullanılabilecek dijital pinler

Uno, Nano, Mini, other 328-based

2, 3

Mega, Mega2560, MegaADK

2, 3, 18, 19, 20, 21

Micro, Leonardo, other 32u4-based

0, 1, 2, 3, 7

Zero

4. hariç tüm dijital pinler

MKR1000 Rev.1

0, 1, 4, 5, 6, 7, 8, 9, A1, A2

Due

Tüm dijital pinler

 

Arduino Uno’da dijital 2 ve 3 nolu pinlere baktığımızda INT0 ve INT1 yazdığını görebilirsiniz. Bunlar “Interrupt 1” ve “Interrupt 2” olarak ifade edilir ve kesmelerin kolay kullanımı için özelleştirilmiştir. Kesmenin kullanımı için bazı modlar belirlenmiştir. Bunlar şu şekildedir:

·         LOW              : Pin gerilimi Lojik-0 olması durumudur.

·         CHANGE       : Pin geriliminin değişmesi durumudur. 0’dan 5’e yada 5’ten 0’a.

·         RISING          : Pin geriliminin Lojik-0′ dan Lojik-1′ e geçmesi durumudur.

·         FALLING        : Pin geriliminin Lojik-1′ den Lojik-0′ a düşmesi durumudur.

Not: Burada bahsedilen Lojik-1, Uno, Mega vb. 5V mikrodenetleyiciler için 2.5V üzeridir. Due gibi 3.3V mikrodenetleyiciler için 1.65V üzeridir.

Arduino da dış kesme attachInterrupt(); fonksiyonu kullanılarak yapılmaktadır. attachInterrup(); fonksiyonu içerisinde 3 adet değişken barındırır.

    attachInterrupt (dijitalPin, kesme fonksiyonu, kesme modu);


dijitalPin       :Arduino’nun kesme için kullandığımız pinidir. Fakat buraya yazacağımız değer Arduino pin numarası değil interrupt numarasıdır. Örneğin; Arduino UNO da 2. dijital pinden kesme yapılacaksa buraya 0, 3. dijital pinden kesme yapılacaksa ise buraya 1 yazılmalıdır.

Kesme fonksiyonu :Kesmeye girildiğinde yapılması gereken işlemlerin içinde bulunduğu fonksiyondur. Void loop’un dışına yazılmalıdır.

Kesme modu       :Kesmeye hangi durumda girileceğini gösteren moddur. Örneğin; pin geriliminin Lojik-0′ dan Lojik-1′ e geçmesi durumunda kesme olacaksa RISING yazılmalıdır.

Kesme fonksiyonunu aşağıdaki türde de yazabiliriz:

    attachInterrupt(digitalPinToInterrupt(2), kesme fonksiyonu, kesme modu);


digitalPinToInterrupt(); fonskiyonu, kullanılacak dijital pin için interrupt numarasını döndüren bir fonksiyondur. Bu fonksiyon da aynı işi yapar.

Yazılımın çalışması sırasında kesmenin modunu değiştirmek veya tamamen devre dışı bırakmak isteyebilirsiniz. Bunun için aşağıdaki fonksiyonu kullanmanız kesmeyi devre dışı bırakmak için yeterli olacaktır.

detachInterrupt(digitalPinToInterrupt(2));


2-   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.

Arduino Uno ya ait bütün pinleri kullanarak bu şekilde kesme rutinleri çalıştırabiliriz. Dikkat etmemiz gereken şey ise; PortD0 ve PortD1 pinleri (Arduino Uno için 0 ve 1 pinleri) seri haberleşme için kullanıldığından dolayı bu pinleri başka bir yerde kullanmak işlemciye program atarken problem oluşturabilmektedir.



Atmega328P’nin pin değişim kesmesinin vektörleri vardır. Kullanmak istediğimiz pine göre vektör tanımı yapılmalıdır. Şöyle:

·         ISR (PCINT0_vect) : PortB’ye ait pinler. (Arduino 8 – 13 pinleri).

·         ISR (PCINT1_vect) : PortC’ye ait pinler. (Arduino A0 – A5 pinleri).

·         ISR (PCINT2_vect) : PortD’ye ait pinler. (Arduino 0 – 7 pinleri).

 

Vektör tanımı program içerisinde aşağıdaki örnekteki gibi yapılır. Yani kesme oluştuğunda aşağıdaki kısım çalışır:

ISR (PCINT0_vect)

{

//komutlar

}


İstediğimiz pine ait pin değişim kesmesini yapmak için bu kesmeye ait register’larda yapmamız gereken işlemler de aşağıdaki fonksiyon ile gerçekleştirilir:

void pciSetup(byte pin)

{

    *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin

    PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt

    PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group

}


Kesme için pin seçimi de aşağıdaki komutla yapılır:

void setup()

{

  pciSetup(pin);

}


EK BİLGİ:

Burada Pin Değişim Kesmesini kontrol eden aşağıdaki register’ların ayarlarıyla ilgili detaylı bilgilere internet üzerindeki kaynaklardan ulaşılabilir. Biz şu an yukarıdaki bilgiler ışığında program yazacağız.

Ø  PCICR  (Pin Change Interrupt Control Register)

Hangi porta ait pinlerde kesme olacağını ayarlarız. PortB, PortC, PortD.

Ø  PCIFR  (Pin Change Interrupt Flag Register)

Porttaki pinlerde değişim olduğunda registerin ilgili pini 1 olur.

Ø  PCMSK  (Pin Change Mask Register)

Portlara ait hangi pinlerde kesme yapılacaksa o pin 1, diğerleri 0 yapılır.


3-   Zaman Kesmesi(Timer Interrupt)

Timer Nedir:

Timer; belirli zaman aralıklarında yapmak istediğimiz olayların gerçekleşmesinde bize yardımcı olan yapıdır. Belirlediğimiz bir süre sonunda, belirlediğimiz görevleri yaptırabiliriz. İşlemciye o zaman dilimi geldiğinde ne yapması gerektiğini hatırlatır. Timer, zamanı saymak, gecikmeler oluşturmak veya periyodik olaylar oluşturmak için kullanılabilir. Örneğin; 1 saniyede bir kodda nerede olursak olalım sensörden veri okumak istersek bu kesmeyi kullanabiliriz. Kod o sırada delay() fonksiyonu içinde bile olsa sensörden veri almaya devam edecektir.

Klasik bir örnek olan belirli zaman aralıklarında herhangi bir çıkışa bağlı led’i yakmak istediğimizde, timer kullanmadığınızı varsayarsak, bu işlemi gerçekleştirmek için geçen zamanı millis(), micros() fonksiyonları ile sürekli olarak kontrol etmeli ya da delay() gibi kaçınılması gereken komutlarla o an işlemciyi bloke etmek zorunda kalabiliriz. Bunları yapmak yerine işlemcide var olan bu yapılar ile gereken zaman kontrolünü sağlayabiliriz. Bunu yaparken işlemcide diğer paralel işlemlerin devam etmesi ise bize çoklu işlem yapabilme yeteneği kazandırır.

Timer Nasıl Çalışır:

Timer’lar, sayaç yazmacı olarak bilinen counter register değişkenini, kayıtçıya(TCNTx) yüklenen bir başlangıç değerinden itibaren her clock sinyalinde 1 arttırırlar. Bu yazmaç, Timer’ın bit sayısına bağlı olarak maximum bir değere kadar ya da belirlediğimiz bir karşılaştırma değerine kadar ulaşır. Timer’lar genellikle 8 bit veya 16 bit olarak karşımıza çıkarlar. 8 bit ise maximum 255’e, 16 bit ise maximum 65535’e kadar çıkar. Bu yazmaç maksimum değerine ya da daha önce belirlediğimiz karşılaştırma değerine ulaştığı zaman kayıtçı sıfırlanır(ya da sıfırdan başlar) ve Interrupt Service Routine (ISR) ile kesme oluşturulur. Bu kesmede tüm kontrolleri ISR sağlamaktadır.

Örneğin; 8 bitlik counter register’ın ilk değeri 50 olarak belirlendi diyelim. Her clock sinyalinde bu değer bir artırılacaktır. Counter register’ın değeri, 255 olduktan bir adım sonra sıfırlanacaktır. Bu noktada zaman kesmesi gerçekleşecektir. Kesme gerçekleştiğinde Arduino otomatik olarak kesme fonksiyonunu çalıştıracaktır.

Timer, çalışması için bir clock sinyaline ihtiyaç duyar. Bu sinyal her oluştuğunda counter’ı 1 arttırır. Bu sinyal harici olabileceği gibi dâhili olarak da çoğu işlemcide mevcuttur.

Örneğin; bir timer’a 16MHz clock sinyali sağlarsak, bu timer için 1 periyot




olur.

 

Bu timer’ların sayısı kullandığınız Arduino çeşidine göre değişiklik göstermektedir. Örneğin; Uno’ da Timer0, Timer1 ve Timer2 olmak üzere 3 tane varken Mega’ da bu sayı 5′ e kadar çıkmaktadır. 

Arduino Uno Timer

Timer0

8 bit

0 - 255

Timer1

16 bit

0 - 65535

Timer2

8 bit

0 - 255


Timer’larda Prescaler Ayarı

Timer’ın çalışması için osilatör’de bir prescalar ayarı denilen bir ayar bulunmaktadır. Buna zamanlayıcı ön ölçekleyici ya da bölme oranı da denilebilir. Bu ayar bizim kristalimizin çalışma frekansını düşürmek için kullanılır. Arduino osilatörü 16Mhz’ de çalışır. Örneğin biz prescalar değerini 64 yapalım. Bu durumda frekansımız;

olur. Bu prescalar değerini kullanmadığımızda frekans çok yüksek olacağı için timer çok hızlı sayacak ve belki de 1 sn’den çok daha küçük değerlerin üzerine çıkamayacağız.

Aşağıda Timer0, Timer1, Timer2 prescalar değerini belirlemek için register’da yapılması gereken değişiklikleri gösteren clock seçimi bilgi tabloları yer almaktadır.



Arduino Timers Control Registers

1.    TCCRxA, TCCRxB: Bunlar zamanlayıcı kontrol kayıtçılarıdır. x; zamanlayıcı numarasını temsil eder. Timer0 kullanıyorsanız, TCCR0A ve TCCR0B kayıtçılarıyla ilgilenmemiz gerekir. Bu kayıtçılardaki WGM00, WGM01, WGM02 bitleriyle zaman kesmesi modu ayarlanır.

2.    TCCRxB: Bu kayıtçıdaki CS00, CS01 ve CS02 bitleri osilatörün prescaler değerini ayarlamak için kullanılır.

3.    TCNTx: Timer’ın başlangıç değerini belirlediğimiz kayıtçıdır. Timer counter kayıtçısıdır.

4.    OCRxA, OCRxB: Timer’ın bitiş değerini belirlediğimiz, karşılaştırma yapacağımız kayıtçıdır. TCNTx ile belirlediğimiz Timer başlangıç değeri, bu iki kayıtçıdan herhangi birine yüklediğimiz değer ile karşılaştırılır. Eşleşme olunca kesmeye gidilir. Timer kesmesinin CTC modunda kullanılır.

5.    TMISKx: OCIExA ve OCIExB bitleri ile OCRxA ve OCRxB için karşılaştırma kesmeleri aktif edilir. TOIEx ile de overflow kesmesi aktif edilir.

6.    ICRx: Giriş yakalama kayıtçısı. Bu kayıtçı Analog Karşılaştırıcı konusunda işlenecektir.



NOT: Kayıtçıların bitlerinde değişiklik yapmak için: “|=” (veya eşit), “&=” (ve eşit),”=” (eşit) şeklindeki bitsel operatörler kullanılabilir. Kayıtçıdaki herhangi bir biti 1 yapmak için; “|=” i, 0 yapmak için; “&=” i kullanabiliriz. Bu bitsel operatörler kullanıldığında, kayıtçıdaki 0 yapılacak bitler önce, 1 yapılacak bitler ise en son ayarlanmalıdır. Çünkü bazı kayıtçılarda bu operatörlerle bir bit sıfır yapıldığında, tüm kayıtçıyı sıfırladığı görüldü.  Bu nedenlerden dolayı bu operatörler yerine kayıtçı_adı=0b10010001 şeklinde ya da bitSet() ve bitClear() komutlarının kullanımı daha sağlıklı olmaktadır.

 

NOT: Kesme alt programları içerisinde seri port ekranına yazdırma işlemi yapılmamalıdır.

 

İki Farklı Zaman Kesmesi Modu Vardır:

·         Normal Mod veya Overflow Interrupt

·         Clear Timer on Compare Match Interrupt (CTC)

Overflow Interrupt; sayaçta taşma(overflow) meydana geldiğinde kesmeye gidilmesi.

CTC ise; bizim daha önceden set ettiğimiz bir count değerine eşit olunca kesmeye gidilmesi.

 

 

a.   Clear Timer on Compare Match Kesmesi ( CTC )

CTC kesmesinde başlangıç değeri; TCNTx kayıtçısında, bitiş değeri ya da karşılaştırma değeri ise; OCRxA veya OCRxB kayıtçısında belirlenir. Başlangıç değerinden itibaren sayma işlemi başlar. Sayma işlemi sırasında karşılaştırma değerine ulaşıldığında kayıtçı sıfırlanacak-sıfıra temizlenecek ve bir kesme fonksiyonu içerisine girilecektir. Bu fonksiyon ISR(TIMERx_COMPy_vect) fonksiyonudur. Buradaki “x” değeri timer numarası(0,1,2), “y” değeri ise karşılaştırma kayıtçısı harfidir(A,B). Kayıtçılar sıfırlanacak demiştik. Bu nedenle kesme fonksiyonu içerisinde kayıtçılara değerleri tekrar verilmelidir.

Örneğin; 8 bitlik bir timer olsun. Timer’ın ilk değeri 100, son değeri 250 olarak belirlensin. Bu değer her bir saat darbesinde artacak olup 250’yi geçtiği anda sıfırlanacaktır ve kesme fonksiyonu içerisine girilecektir.

Zaman kesmesinin oluşma süresi aşağıdaki formül ile hesaplanabilir:



        olur. Bu formülde Timer bitiş değerini 8 bitlik timer’da maksimum 255’e kadar, 16 bitlik timer’da maksimum 65535’e kadar değer girilerek kesme süresi değiştirilebilir. Formüldeki +1 ise 0’ın da dâhil olmasındandır.



CTC zaman kesmesi örnek-1:

void setup ()

{

  cli(); //tüm kesmeler durduruldu

 

  //timer0 kesmesi

  TCCR0A = 0;     //TCCROA register 0'lanıyor

  TCCR0B = 0;     //TCCROB register 0’lanıyor

  TCNT0 = 0;      //timer0 başlangıç değeri sıfırlandı

  OCR0A = 124;    //timer0 bitiş/karşılaştırma değeri belirlendi

  TCCR0A |= (1 << WGM01); //CTC(Clear Timer on Compare Match) mod açıldı

  TCCR0B |= (1 << CS01) | (1 << CS00); //prescalar değeri 64 yapıldı

  TIMSK0 |= (1 << OCIE0A);  //timer0 OCR0A karşılaştırma kesmesi aktif edildi

 

  //timerl kesmesi

  TCCR1A = 0;     //TCCR1A register 0’lanıyor

  TCCR1B = 0;     //TCCR1B register 0'lanıyor

  TCNT1 = 0;      //timer1 başlangıç değeri sıfırlandı

  OCR1A = 15624;  //timer1 bitiş/karşılaştırma değeri belirlendi

  TCCR1B |= (1 << WGM12);   //CTC(Clear Timer on Compare Matah) mod açıldı

  TCCR1B |= (1 << CS12) | (1 « CS10); //prescalar değeri 1024 yapıldı

  TIMSK1 |= (1 << OCIE1A);  //timerl OCR1A karşılaştırma kesmesi aktif edildi

 

  //timer2 kesmesi

  TCCR2A = 0;     //TCCR2A register 0'lanıyor

  TCCR2B = 0;     //TCCR2B register 0’lanıyor

  TCNT2 = 0;      //timer2 başlangıç değeri sıfırlandı

  OCR2A = 249;    //timer2 bitiş/karşılaştırma değeri belirlendi

  TCCR2A |= (1 << WGM21);   //CTC(Clear Timer on Compare Matah) mod açıldı

  TCCR2B |= (1 << CS21);    //prescalar değeri 8 yapıldı

  TIMSK2 |= (1 << OCIE2A);  //timer2 OCR2A karşılaştırma kesmesi aktif edildi

 

  sei(); //tüm kesmelere izin verildi

}

 

void loop()

{

  //Do Nothing

}

 

 

//CTC zaman kesmesi olduğunda çalışacak kesme alt programı

ISR(TIMER0_COMPA_vect)

{

  //komutlar

}

ISR(TIMER1_COMPA_vect)

{

  //komutlar

}

ISR(TIMER2_COMPA_vect)

{

  //komutlar

}




CTC zaman kesmesi örnek-2:

#define LED_A_PIN 13

#define LED_B_PIN 8

 

void setup()

{

  TCCR1A = 0;           //Init Timer1A

  TCCR1B = 0;           //Init Timer1B

  TCCR1B |= B00000011;  //Prescaler = 64

  OCR1A = 20000;        //Timer1 Compare1A Register

  OCR1B = 8750;         //Timer1 Compare1B Register

  TIMSK1 |= B00000110;  //Timer1 OCR1A and OCR1B Compare Interrupts Enable

  pinMode(LED_A_PIN, OUTPUT);

  pinMode(LED_B_PIN, OUTPUT);

}

 

void loop()

{

  //Do Nothing

}

 

ISR(TIMER1_COMPA_vect)

{

  OCR1A += 20000;

  digitalWrite(LED_A_PIN, !digitalRead(LED_A_PIN));

}

 

ISR(TIMER1_COMPB_vect)

{

  OCR1B += 8750;

  digitalWrite(LED_B_PIN, !digitalRead(LED_B_PIN));

}


b.   Normal Mod ya da Overflow Kesmesi

Zamanlayıcı ön yükleme kesmesi anlamına gelir. TCNTx kayıtçısından başlangıç değerini verdikten sonra Timer bit sayısı durumuna göre, 8 bit ise 255’e, 16 bit ise 65535’e kadar sayar ve ardından taşma-overflow meydana gelir. Bu taşma sonucu kayıtçı sıfırlanmaz fakat sıfırdan tekrar başlar ve bir kesme fonksiyonu içerisine girilecektir. Bu fonksiyon ISR(TIMERx_OVF_vect) fonksiyonudur. Kayıtçı sıfırdan tekrar başlar demiştik. Bu nedenle kesme fonksiyonu içerisinde kayıtçıya değeri tekrar verilmelidir.

Overflow kesme süresi aşağıdaki formülle hesaplanır:



Overflow kesmesi örnek:

void setup ()

{

  pinMode(9, OUTPUT);

  cli() ;  //tüm kesmeler durduruldu

 

  //Timerl için ayarlar yapılıyor

  TCCR1A = 0;              //TCCR1A register 0’landı

  TCCR1B = 0;              //TCCR1B register 0’landı

  TCCR1B |= (1 << CS11);   // prescalar değeri 8 yapıldı. Yani 16/8 =2 Mhz

  TCNT1 = 40535;           //timer1 başlangıç değeri belirlendi

  TIMSK1 | = (1 << TOIE1); //Overflow kesmesi aktif edildi

 

  sei();  //tüm kesmelere izin verildi

}

 

//Overflow kesmesi olduğunda çalışacak kesme alt programı

ISR(TIMER1_OVF_vect)

{

  digitalWrite(9, !digitalRead(9));

  TCNT1 = 40535;  //timer1 başlangıç değeri tekrar belirlendi

}


Overflow kesmesinin bazı dezavantajlarından bir tanesi istediğimiz frekans değerlerinin tam olarak ayarlanabilmesinin zor olmasıdır. Çünkü her seferinde counter’ın sona kadar arttırılıp kesmenin oluşması beklenmektedir. Bunun yerine daha hassas frekans oynamaları yapabildiğimiz, timer’in bizim belirlediğimiz bir değere ulaşmasından sonra kesmeye gidilmesini sağlayan CTC kesmesi daha verimlidir.


Zaman kesmesinde harici clock kullanımı:

Zaman kesmesinde normalde Arduino’nun frekansı clock sinyali olarak kullanılır ama istersek clock sinyalini dışardan bir kaynaktan da kullanabiliriz. Yani herhangi bir elektronik devreden, NE555 entegresi gibi bir kaynaktan üretilen clock sinyalini de timer kesmesi için kullanmamız mümkündür.

Arduino Uno Atmega328p’de harici clock kullanılırken; Timer0 kesmesi için clock sinyali 4. pinden, Timer1 kesmesi için clock sinyali 5. pinden verilir. TCCR1B register’ındaki ilgili CS…’ler set edilir. Hangi CS’lerin set edileceği ve yükselen-düşen kenar seçimi yukarıdaki Timer tablolarında yer almaktadır. Bu kesmede prescalar değeri yoktur. Dolayısıyla kesme süresi aşağıdaki formüldeki gibi olur:


Bu ayarlamalar dışında geri kalan kod yazımı aynı olur. 


ÖNEMLİ: Harici clock sinyali ile ilgili 2 farklı uygulama yaptık. Birincisi; buton kullanarak 5 nolu pinden clock sinyali verdik. İkincisi; 3 nolu pinden PWM sinyali gönderip, bu pini bir direnç üzerinden 5 nolu pine bağlayarak clock sinyali verdik. Aslında Arduino’nun ürettiği PWM sinyalini, tekrar Arduino’nun Timer1’i için harici clock kaynağı olarak kullanmış olduk.

 

 

4-   Timer1 Giriş Yakalama Kesmesi

Atmega328’e ait Timer1’de giriş yakalama işlevi vardır. Giriş yakalama pininde (ICP1) veya analog karşılaştırıcı çıkışında (ACO) bir mantık seviyesi değişikliği meydana geldiğinde bir yakalama tetiklenir. Gerekli ayarlamalar yapılarak kesmeye gidilmesi sağlanır. Timer1 giriş yakalama kesmesi, 50. Konu olan “Analog Karşılaştırıcı Kullanımı” konusunda detaylı olarak anlatılmış ve çeşitli uygulamalar yapılmıştır.

 

 

Timer’ları Kullanan Fonksiyonlar:

Zaman kesmesi konumuzda bahsettiğimiz Timer’ları, Arduino, bazı komutlarında ya da fonksiyonlarında kullanmaktadır. Bunlar:

·         Timer0, delay(), millis() ve micros() gibi zamanlama fonksiyonları tarafından kullanılır.

·         Arduino Uno'daki timer1 veya Arduino Mega'daki timer5 servo kütüphanesi tarafından kullanılır.

·         Timer2, tone() fonksiyonu tarafından kullanılır.

·         PWM için kullanılan analogWrite() komutu, 6 adet PWM çıkış pininden:

v  5 ve 6. Pinler için; Timer0’ı

v  9 ve 10. Pinler için; Timer1’i

v  11 ve 13. Pinler için Timer2’yi kullanır.

Timer’ları kullanırken aynı zamanda bu fonksiyonlardan biri de kullanılacaksa, zaman sayacını değiştirdiğimizde bu komutlar da etkilenebilir. Bu durum göz önünde bulundurulmalıdır.


Kaynaklar:

https://www.elektrobot.net/arduino-ile-timer-kullanimi/

https://sinanbir.com/arduino-timer-kullanimi-kesmeler-avr-8-bit/

https://www.instructables.com/Arduino-Timer-Interrupts/

https://www.teknikerler.com/arduino-kesmeler-zaman-kesme-ayni-anda-iki-islem-robotik-kodlama-dersleri-75/

https://maker.robotistan.com/arduinoda-kesme-islemleri/

https://www.mekinfo.net/arduino-dersleri-11-interrupt-kesmeler/


____________________________________________________________________________________________________________________________________________________


0 comments:

Yorum Gönder

Arduino Eğitimi Konu - 7

Toplam Sayfa Görüntüleme Sayısı

Seri İletişim Protokolleri

Sensörlerin Arduino İle Kullanımı

Popular Posts

Yararlanılan Kaynaklar

İletişim

gokdag17@gmail.com