Arduino Timer ve Interrupt Nasıl Kullanılır

Arduino Timer ve Interrupt uygulamasını yaparak belirli zaman aralıklarında işlem yapmak istediğimiz işlemlerin nasıl yapılacağını öğrenmiş olacağız arkadaşlar. Bildiğiniz gibi her Arduino boardunun farklı işlemcileri vardır. Bu işlemciler Microchip firması tarafından üretilen atmega serisi işlemcilerdir. Arduino Uno’ da Atmega328p serisi 8-bit mikrokontrolor kullanılmıştır.

Bu entegrenin içinde Timer0 (8-bit), Timer1 (16-bit) ve Timer2 (8-bit) olmak üzere 3 adet dahili zamanlayıcısı vardır. Zamanlayıcılar counter register denilen değişkeni her clock pulse sinyalinde arttırmaktadırlar. Bu değişlenin değeri 8-bit için bu değer 255, 16-bit için bu değer 65536′ dır. Bu değişken değeri tamamlandığında taşma biti 1 yapılarak otomatik olarak kesme oluşturulur Interrupt Service Routine (ISR).

Arduino için timer’a 16MHz clock sinyali sağlanırsa periyod;

T = 1 / f ( Frekans Hz olarak )

T= 1 / ( 16* 10^6 Hz )

T = 62.5 ns (Eğer 32Mhz için bu değer 31.25 ns olacaktır)

Timer0 – 8-bit bir zamanlayıcıdır. Counter değişkeni maksimum 255 değerini alır. Arduino’ daki delay(), milis() gibi komutları bu zamanlayıcıyı kullanmaktadır.

Timer1 – 16-bit bir zamanlayıcıdır. Counter değişkeni maksimum 65535 değerini alır. Servo kütüphanesi bu zamanlayıcıyı kullanmaktadır.

Timer2 – 8-bit bir zamanlayıcıdır. Counter değişkeni maksimum 255 değerini alır. tone() fonksiyonu bu zamanlayıcıyı kullanmaktadır.

Timer konfigürasyon ayarlarını yapabilmemiz için iki adet register’a ihtiyacımız vardır. Her register 8-bit veri saklar.

Arduino Timer 1 Register
Arduino Timer 1 Register

Bir ölçekleyici (prescaler), zamanlayıcınızın hızını aşağıdaki denkleme göre belirler. Prescalar değerini aşağıdaki tablodan elde edebilirsiniz.

(timer speed (Hz)) = (Arduino clock speed (16MHz)) / prescaler
Timer Prescalar
Timer Prescalar

Eğer prescaler değerini 1 (CS12:0, CS11:0, CS10:1) yaparsanız timer’ ınızın hızı 16Mhz olacaktır. Yani 16Mhz’ lik bir hız ile counter register değerimiz +1 olacaktır. Dolduğunda ise kesmemiz (interrupts) oluşacaktır. Yukarıda hesapladığımız gibi 62,5 ns’ de bir değişken bir artacaktır. İşte bu kesme değerini buradaki prescalar değerleriyle oynarak değiştirebiliriz.

Örneğin; CS10 değerini 1 yaparsak prescalar 8 olacaktır. Buda counter register’ ın 8 kat daha yavaş artacağı anlamına gelir. Yani 62,5 * 8 = 500 ns (0,5 us) de counter register değişkeni bir artacaktır.

Bu sayede Timer1 16-bit olduğu için 65536 * 0,5 us = 32.77 ms olur. f = 1 / T = 30,51 Hz olur.

Arduino üzerinde Timer’ ı programlarsak;

#define LED 13 // Uno board üzerinde led
 
void setup()
{
  pinMode(PIN, OUTPUT);
  //  Timer1 Ayarlanması
  cli();         // tüm interruptlar devre dışı
  TCCR1A = 0;    // tüm TCCR1A reg clear
  TCCR1B = 0;    // tüm TCCR1B reg clear
 
  TIMSK1 |= (1 << TOIE1); // timer1 için overflow (taşma) interruptını açar
 
  TCCR1B |= (1 << CS11); //  böleni 8 olarak ayarladık. Yani 16/8 = 2 MHZ
 
  sei();//Tüm interruptları çalıştır.
 
}

ISR(TIMER1_OVF_vect)
{ 
  digitalWrite(PIN, !digitalRead(PIN));   // LEDi yak, yanıksa söndür
}
 
void loop()
{
 
}

Aşağıdaki örnekte ise Timer1 zamanlayıcı presclar değeri 1024 olarak ayarlanmıştır. Artım hızı 64 us olmaktadır. Kesme için 65536 değeri için taşma 4194 sn olmaktadır.

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

Clear Timer on Compare Match Kesmesi (CTC)

Fakat aşağıdaki kodda taşma kesmesi yerine Clear Timer on Compare Match Kesmesi (CTC) özelliğini kullanarak kesme oluşturacağız arkadaşlar. Bu özellik sayesinde taşma değerini beklemeden bizim belirlediğimiz değerde kesme oluşturabiliriz arkadaşlar. Bunun için aşağıdaki formülü kullanarak istediğimiz frekansı hesaplayabiliriz.

Compare Match Register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] – 1

#define PIN 13 // ARduino Board üzerindeki LED

void setup()
{
  pinMode(PIN, OUTPUT);

  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  
  TCCR1B |= (1 << WGM12);   // turn on CTC mode
  
  TCCR1B |= (1 << CS12) | (1 << CS10);    // Set CS10 and CS12 bits for 1024 prescaler
  
  TIMSK1 |= (1 << OCIE1A);   // enable timer compare interrupt
}

void loop()
{

}

ISR(TIMER1_COMPA_vect)
{
  digitalWrite(PIN, !digitalRead(PIN));
}

Umarım Arduino üzerindeki zamanlayıcı ve zamanlayıcı kullanarak kesme oluşturma konusunda bilgi sahibi olmuşsunuzdur. Görüşmek üzere.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

This site uses Akismet to reduce spam. Learn how your comment data is processed.