Sosyal Medya  

FacebookTwitterDiggLinkedinRSS Feed
   

Bir problemin çözümünü gerçeklerken, işlemcilerde en çok ihtiyaç duyduğumuz konulardan biri de zamanlayıcılardır. Belirli bir iş belirli zamanlarda yapılmak istendiğinde, o sürenin ölçümü için zamanlayıcılar kullanılır. Bu makalemde, Microchip firmasının üretmiş olduğu PIC18F2580 işlemcisi örnek alınarak, zamanlayıcılar ille nasıl işlem yapıldığını anlatacağım. PIC18F2580 işlemcisinin datasheet'ine buradan indirebilirisiniz. Yazılım geliştiriken kullanacağım platform MplabX ve yazılım dili de XC8'dir.

 Kesme(Interrupt) Nedir?

Kesmeyi günlük bir olaydan örnek vererek anlatmaya çalışayım. Örneğin; evinizde yemek yapacaksınız ve hastanede de önem verdiğiniz biri var ve ondan da telefon bekliyorsunuz. Normalde işiniz yemek yapmak olduğu için, başladınız yemeğe ama kulağınız telefonda. Siz yemek yaparken biranda telefonunuz çaldı ve çalar çalmaz elinizdeki tüm işi bıraktınız ve telefonu açtınız. Telefonu kapattıktan sonra da kaldığınız yerden yemek yapmaya devam ettiniz. İşte burada yapmakta olduğunuz işi bir süre bıraktırıp, önceliği olan başka bir işe yönelme durumuna kesme adını veriyoruz. Yani telefonun çalması sizin hayatınızda bir kesme oluşturdu.

İşlemciler de rutin olarak yapması gerek işleri gerçekleştirirken daha önceden tanımlanmış olan önceliği yüksek bir durumla karşılaşıldığında, elindeki tüm işleri bırakıp o durum için tanımlanan işlemleri yapıp, daha sonra rutin işine kaldığı yerden devam eder. Burada işlemcinin rutin işini yarıda bırakıp, başka bir işe yönelmesi için gerçekleşen olaya kesme (interrupt) adını veriyoruz.

PIC18F2580'de 12 adet kesme bulunmakta ve bu kesmeler 10 farklı kayıtçı(register) ile kontrol edilmektedir:

  • RCON
  • INTCON
  • INTCON2
  • INTCON3
  • PIR1, PIR2, PIR3
  • PIE1, PIE2, PIE3
  • IPR1, IPR2, IPR3

Tüm kesmelerin aktif olabilmesi için INTCON kayıtçısının 7. biti olan GIE kayıtçısının değeri 1 olarak ayarlanmalıdır.

Zamanlayıcı Kesmesi

Belirli bir işi belirtilen bir zamanda yapmak için zamanlayıcı kesmesi kullanılır. Örneğin; butona basıldıktan 1. motor çalışsın, 5dk sonra 2. motor çalışsın, 15dk sonra 1. ve 2. motor durup 3. motor çalışmaya başlasın şeklinde bir problemle karşılaşabiliriz. Problemin içine zamanlayıcı girdiği için işlemcideki zamanlayıcı kesmelerini kullanırız. Tam 5dk. olduğunda işlemci tüm işini bırakıp, 2. motoru çalıştırmaya gider ve daha sonra da kaldığı yerden devam eder. 15dk. olduğunda da işlemci yine tüm işini bırakıp, 1. ve 2. motoru durdurur ve 3. motoru çalıştırır.

PIC18F2580 işlemcisinde 1 adet 8bit, 3 adet de 16bit olmak üzere toplamda 4 adet zamanlayıcı(timer) bulunur. Biz bu yazımızda Timer0 zamanlayıcı kesmesini kullanacağız.

Timer0 kesmesini kullanabilmek için öncelikle bazı ayarlamalar yapmamız gerekiyor:

T0CON: Timer 0 Control Register

T0CON kayıtçısı Timer 0'ın temel ayarlarının yapıldığı yerdir.

 Timer0 zamanlayıcısının çalışabilmesi için herşeyden önce 7. bit olan TIMER0ON biti 1 yapılmalıdır.

T08BIT: Zamanlayıcımızı 8bitlik mi yoksa 16bitlik mi çalıştırmak istediğimizi seçiyoruz. Eğer 8bit seçersek zamanlayıcı hafızası(TMR0) değeri 255; 16bit seçersek de 65535 olur.

T0CS: Zamanlayıcının referans saatinin belirleneceği bit. İşlemciye dışarıdan bağlanan kristaller, işlemci içerisinden 4'te 1 oranından darbe oluşturabilirler. Yani 40MHz'lik bir kristal bağladığımızda, işlemcinin hızı 40/4=10MHz olarak hesaplanır.

T0SE: Zamanlayıcı içerisindeki sayacın yükselen kenarda mı yoksa düşen kenarda mı artacağını belirten bit.

PSA: Zamanlayıcının sayacındaki herbir artışı geciktirme kullanılıp kullanılmayacağını belirten bit. Bu ne demek? Örneğin; işlemcimize 4MHz'lik bir kristal bağladık. O zaman işlemcimizin hızı 1/(4MHz/4)=1us olur. Yani zamanlayıcının sayacı her 1us'de 1 artar. Eğer bir sayac değerini 2us'de bir arttırmak istersek, prescaler dediğimiz gecikme ayarını yapmamız gerekiyor.

T0PS<2:0>: Gecikme miktarının ayarlandığı bitler.

TMR0: İçerisinde sayaç değeri tutulan kayıtçıdır. Her bir adım aralığında içindeki değer bir artar. Ne zaman ki içerisindeki değer 0 oldu, o zaman kesme bayrağı 1 yapılır. Eğer zamanlayıcımızı 16bit olarak ayarlamışsak 65535'e kadar, 8bitlik ayarlamışsak da 255'e kadar sayar. TMR0 sayıcısının ilk 8bit'i TMR0L kayıtçısında, son 8biti de TMR0H kayıtçısında tutulur.

Timer0 Zamanlayıcısı Kesme Ayarı

 Timer 0 zamanlayıcı kesmesini kurmak için INTCON kayıtçısından yararlanılmakta.

Timer0 zamanlayıcı kesmesi kurmak için şu adımlar izlenir:

  • T0CON kayıtçısını ayarla
  • TMR0H ve TMR0L değerlerini ayarla
  • INTCON kayıtçısının 5.biti olan TMR0IE bitini 1 yap
  • INTCON kayıtçısının 2.biti olan TMR0IF bitini 0 yap. TMR0IF biti 1 olduğunda işlemci kesmeye girer.
  • INTCON kayıtçısının 7. biti olan GIE/GIEH bitinin 1 yap. GIE/GIEH biti tüm kesmeleri aktif eder.

TMR0H ve TMR0L Ayarları

TMR0H ve TMR0L kayıtçılarının sayac değerinin tuttuğunu söylemiştik. TMR0 kayıtçısı değeri her 0 oluşunda TMR0IF bayrağı 1 yapılarak, işlemcinin kesmeye gitmesi sağlanır.

Peki bir işlemcinin adım aralığı nedir? Bir işlemcinin çalışabilmesi için zaman darbesine ihtiyaç vardır. İşlemci her bir komutu bu zaman darbesine göre gerçekleştirir. Bu zaman darbesi işlemciye bağlanan kristaller ile oluşturulur. Makalemin devamında, PIC18F2580 işlemcisine 40MHz kristal bağlanmış kabul edeceğiz.

Eğer timer0 zamanlayıcısı işlemciye bağlanan kristalin 4'te birini kullanır. 40MHz işlemcimiz için timer0 zamanlayıcısı 10MHz olarak çalışır. Eğer prescaler değeri aktif edilmemişse, TMR0 içerisindeki sayaç değeri, 1/10MHz = 100ns'de bir artacaktır.

Kesme süresi = TMR0 * Prescaler * ( 1/ (Fosc/4) )

Eğer biz her 10ms'de bir kesmeye girilmesini istersek, TMR0 sayacımızın sayma değerinin;       10ms/100ns = 100000(yüz bin)
olarak ayarlamalıyız. Ama timer0 kayıtçımız en fazla 65535 değerini alabildiği için bu mümkün değil. Bu yüzden prescaler özelliğini kullanmalıyız. Prescaler değerini 2 ayarlarsak, TMR0 kayıtçısının sayma değerini de 100000/2=50000 olarak ayarlayabiliriz. Burada unutulmaması gereken önemli bir kısım var.

Peki TMR0 kayıtçısının sayma değeri nedir? 16bitlik timer0 zamanlayıcısı için TMR0 kayıtçısı en fazla 65535 değerini alabileceği söylemiştik. TMR0 sayaç değeri her adım aralığında 1 artar. Sayaç değeri 65535 olduktan sonraki artışta, sayaç 0 olur ve TMR0IF bayrağı 1 yapılarak işlemci kesmeye gönderilir. Eğer biz TMR0 kayıtçısının 50000 sayıp, kesmeye girmesini istiyorsak, TMR0 değerini;
       65535 - 50000 = 15535
olarak ayarlamalıyız. Bunun anlamı, TMR0 kayıtçısı içerisindeki sayaç 15535 değerinden başyalayacak ve 65535 olduktan sonra kesmeye gidecek.

Örnek Uygulama

Bu uygulamamızda; PIC18F2580 işlemcisinin RB7 pinine bağlı bir ledi 1sn açık, 1sn kapalı yapacak programı yazalım.

#include <xc.h>
#include<stdlib.h>

#define _XTAL_FREQ 40000000 //40MHz
#define LED PORTBbits.RB7

typedef unsigned int uint;
typedef unsigned char uchar;

uchar Sayac=0;
const uint TMR0_Sayac=50000;

void picAyar()
{
    TRISA = 0; 
	TRISB = 0; 
	TRISC = 0;

    PORTA = 0; 
    PORTB = 0;
	PORTC = 0;


    //Timer Kurulumu -- 10ms'de bir kesmeye girilecek
    T0CON = 0b10000000; //TIMER0 Aktif, PRESCALE= 1:2 (1/(40MHz / 4)*2 = 200nS)  *50000
    WRITETIMER0(65535-TMR0_Sayac); //10ms'de bir Timer0 kesmesine girilecek. TMR0 sayacına değer giriliyor.
    INTCONbits.TMR0IE=1;
    INTCONbits.TMR0IF=0;
    ei(); // Tüm kesmeler aktif edildi
}
void main(void)
{
    picAyar();
    while(1){}   
}

void interrupt kesmeler()
{
    di(); // Tüm kesmeler pasif
    if(INTCONbits.TMR0IE && INTCONbits.TMR0IF) // Timer-0 Kesmesi
    { 
        if(++Sayac >= 100)
        {// 1sn'de LED'i Tersle
            LED = ~LED;
            Sayac=0;
        }
        WRITETIMER0(65535-TMR0_Sayac);
        INTCONbits.TMR0IF=0;
    }
    ei(); // Tüm kesmeler aktif
}

 

Bir makalemin de sonua geldik. Bu makalemde işlemcilerde en çok ihtiyaç duyulan zamanlayıcı kesmesi hakkında temel bir bilgi vermeye çalıştım. Umarım sizler için faydalı bir yazı olmuştur.

Bir sonraki makalemde görüşünceye dek, sağlıcakla kalın.

Muhammet EFE

 

Yorumlar   

0 # Serhat Evcim 06-01-2015 16:10
Emeğine sağlık kardeşim , her zaman olduğu gibi çok faydalı bir döküman. Birçok kişinin işine yarayacaktır.

Sevgiler :)
Cevap
0 # Mert 22-01-2015 20:39
Güzel bir makale daha. Emeğiniz ve ilginiz için teşekkür ederim.
Cevap
0 # cem üstün 29-04-2017 18:43
PIC in herhangibir pinine metal bir cisimle dokunduğumuzda PIC reset atıyor veya INT0 kesmesi aktif ise PIC kesmeye giriyor. bu sorun nasıl aşılır , klasik yöntemler den biri PIC voltaj uçlarına küçük degerlilkli kapasite koymak ,fakat bu çözüm değil , INT0 kesmesi daha hassas ve duyarlı , aynı şebeke hattına temas olsa bile PIC kesmeye giriyor, program veya donanım nasıl bir çözüm bulunmalı
Cevap

Yorum ekle


Güvenlik kodu
Yenile

   
© muhammetefe.com

Joomla Hata Ayıklama Konsolu

Oturum

Profil Bilgisi

Bellek Kullanımı

Veritabanı Sorguları