C ile AVR Programlama -28- TC0 Zamanlayıcısı Kullanımı

Önceki dersimizde TC0 zamanlayıcı birimini anlatmış ve yazmaçları hakkında bilgi vermiştik. Şimdi bu birimin nasıl kullanıldığını açıklayalım. Bunu açıklamadan önce ön derecelendiricileri ve nasıl hesaplanacağını anlatalım.

Zaman Periyodu = 1 / Frekans 

Örneğin bir ledi her 10 milisaniyede bir yakmak isteyelim. Bunun frekansı 1/10ms yani 100Hz olacaktır. İşlemciye de harici 4MHz kristal takıldığını ve saat hızının 4MHz olduğunu farz edelim. Zamanlayıcılar 0’dan TOP değerine kadar saydığı için 8-bit olan TC0 zamanlayıcısı 0’dan 255’e kadar sayacaktır. Bundan sonra zamanlayıcı taşacak ve tekrar sıfırdan devam edecektir. Zamanlayıcının bu değeri her saat dalgasında değişecektir. Eğer zamanlayıcının değeri 0 ise bir saat palsından sonra 1 olacaktır. Sonra 2,3,4.. diye devam edecektir. F_CPU değeri 4MHz olduğu için Zaman = 1 / 4000000 yani 0.00025 milisaniye olacaktır. Her bir değer artırımı bu kadar kısa zaman içerisinde yapılacaktır.

10 milisaniyelik bir bekleme istediğimizden bu kısa bekleme bile mikrodenetleyicinin saatine göre çok yavaş gelecektir. Bunun ne kadar uzun sürdüğünü aşağıdaki formülü kullanarak hesaplıyoruz.

Zaman Sayımı = (Gereken Bekleme/Saat Periyodu) – 1

Gereken bekleme 10ms ve saat periyodu 0.00025ms olduğu için bunun için 39999 çevirim gereklidir. Yani saatin 39999 kere atması gereklidir. Bunu 8-bit zamanlayıcıda yapmak mümkün değildir çünkü sadece 0-255 arası değer almaktadır. İşte bunu bölecek bir aygıta ihtiyaç vardır. Buna ön derecelendirici (prescaler) diyoruz.

Ön derecelendirici işlemcinin saat hızını belli derecelere bölerek zamanlayıcının sayım işlemini bunun üzerinden yapar. Örneğin ön derecelendirici 8 olduğu zaman 4MHz’lik frekans 0.5MHz’e düşer. Böylelikle 39999 kere sayım yerine 9999 kere sayım gerekir. Yine yüksek bir değer olsa da bu değer 16-bit zamanlayıcıda kullanılabilir.  Zamanlayıcının teknik veri sayfasından anlaşıldığı üzere 8, 64, 256 ve 1024 olmak üzere dört adet bölme değerine sahibiz. Bu bölme değerini işlemcinin saat hızına bölüp saniyede kaç artırım yaptığını bulabiliriz.

Zamanlayıcılar genellikle kesmeler ile kullanılır. Çünkü zamanlayıcının taştığını veya eşleştiğini sürekli denetleyecek kod yazmak mikrodenetleyiciyi gereksiz yere meşgul eder. Bizim yerimize zamanı sayacak ve ardından belirlenen noktaya gelindiğini mikrodenetleyiciye haber veren sistem her zaman daha verimlidir. Örneğin saat 12’de evden çıkmamız gerekiyor. Bunu sürekli saate bakarak mı kararlaştırmak daha kolay olur yoksa çalar saati 12’ye kurmakla mı ? Kesmeleri de aynı bu şekilde düşünebiliriz.

Şimdi TC0 kullanımına dair iki örnek program verelim ve bunları inceleyelim. İlk program 16MHz’de çalışan bir sistemde 1 milisaniye seviyesinde çalışacak şekilde ayarlar ve herhangi bir kesme kullanmaz.

TCCR0A |= (1 << WGM01); WGM01 biti bir (1) yapılarak CTC modunda zamanlayıcı başlatılmıştır. CTC (Clear Timer on Compare) modu ayarlanılan değer ile zamanlayıcının sayma değerini karşılaştırır  ve eşitlik olduğunda zamanlayıcıyı sıfırlar. Zamanlayıcı sıfırlandıktan sonra otomatik olarak saymaya devam eder.

OCR0A = 0xF9; OCR0A yani TC0 çıkış karşılaştırma yazmacına karşılaştırılacak değeri atıyoruz.

TCCR0B |= (1 << CS01) | (1 << CS00); CS00 ve CS01 bitlerini bir (1) yaparak ön derecelendiriciyi 64 olarak belirliyoruz.

while ( (TIFR0 & (1 << TOV0) ) > 0)  TOV0 yani taşma bayrağı biti bir (1) olana kadar programı döngüde bekletiyoruz.

TIFR0 |= (1 << TOV0);  Taşma bayrağını sıfırlıyoruz.

Sonraki programımız ise zamanlayıcıyı 4ms değerine ayarlar ve her 4 milisaniyede bir kesme meydana getirir.

Kesmeler konusuna gelmesek de zamanlayıcılar kesmelerle beraber kullanıldığı için ikisini beraber anlatmamızda yarar var.
TIMSK0 |= (1 << OCIE0A); Bu komutla TC0 Çıkış karşılaştırma eşleşmesi A Kesmesini etkinleştiriyoruz.

sei(); Bu fonksiyon kesmeleri etkin hale getirmek için kullanılır. Kesmeleri devre dışı bırakmak içinse cli(); fonksiyonunu kullanıyoruz.

ISR (TIMER0_COMPA_vect) Burada kesme fonksiyonunu belirliyoruz. Kesme yürüdüğünde buraya yazdığımız komutlar çalışacaktır.

Şimdilik TC0 konusunu burada bitirelim ve diğer zamanlayıcılara geçelim.

Kaynaklar:
enable/disable interrupts, https://www.avrfreaks.net/forum/enabledisable-interrupts, Erişim Tarihi : 25.08.2018

Timers on the ATmega168/328, https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328, Erişim Tarihi: 25.08.2018

AVR Timers – TIMER0, http://maxembedded.com/2011/06/avr-timers-timer0/, Erişim Tarihi : 25.08.2018

ATmega328P – Microchip Technology , http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf, Erişim Tarihi: 25.08.2018

Kapak Resmi :https://d3s11pzv7w3h1q.cloudfront.net/wp-content/uploads/IC-ATMEGA8A-PU-2.jpg

UYARI!!

Gökhan Dökmetaş

"Arduino Eğitim Kitabı" ve "Arduino ve Raspberry PI ile Nesnelerin İnterneti" kitaplarının yazarı. Başkent Teknoloji ve Dedektör Merkezi'nde Ar-ge Sorumlusu. Araştırmacı-Yazar.

You may also like...

2 Responses

  1. İlker Aykut dedi ki:

    Hocam merhaba datasheette focnx=fclk/2*N*(1+OCRnx) şeklinde ifade edilmiş.Buradaki çarpı 2 ifadesi formülde neden kullanılmıyor?

    • Bahsettiğiniz çıkış frekansı hesaplamasında kullanılan formül. focnx derken Ocn değerini değil frekansını ifade eder. PWM konusunun eksik kaldığını görmüş olmalısınız. İlerleyen zamanlarda uygulama yapıp telafi edeceğiz.

Bir cevap yazın

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