Not 15’te timer0’ın zamanlayıcı olarak kullanılmasını görmüştük.  Bu yazımızda ise Timer0’ın sayıcı olarak kullanılmasına bir örnek vereceğiz. Timer0 dahili saat kaynağı ile çalışabildiği gibi RA4 pininden uygulanacak harici bir sinyal ile de saydırılabilir. Bu harici sinyal ile de Timer0’ı zamanlayıcı olarak kullanabiliriz. Fakat biz şu anda Timer0’ı sadece saydırma amaçlı kullanacağız. Zaten mantığını anlayınca harici saat kaynağı ile zamanlayıcı olarak kullanmanın hiç bir farkı olmadığını siz de göreceksiniz. Bir önceki yazımızda Timer0’ı kurmak için gerekli işlemlerin sıralamasını anlatırken şunları söylemiştik;

  1. OPTION REGISTER-TMR0 Clock Source Select biti ayarlanır(0 ise osilatör frekansı, 1 ise harici saat sinyali(RA4 pininden verilecek olan) Timer0 için kaynak olarak belirlenir.)
  2. OPTION REGISTER-TMR0 Source Edge Select biti ayarlanır( eğer kaynak olarak harici, seçili ise 1 düşen kenar veya 0 yükselen kenar tetiklemesi belirlemek için kullanılır)
  3. OPTION REGISTER-Prescaler Assignment biti ayarlanır. Timer0 için 0, Watch dog timer için 1 seçilir. Biz 0 seçiyoruz. (watchdog timer daha sonra anlatılacak).
  4. OPTION REGISTER-PS2-PS1-PS0 bitleri. İte bu bitler Timer0′ın en can alıcı ayarını oluşturur. Timer0′ın kesme oluşturacağı süreyi hesaplayabilmek için bu bitlerin değerleri ile oynarız ve bize en iyi sonucu verecek değeri seçeriz.
  5. TMR0 registerına gerekli değer yüklenmelidir.
  6. INTCON – INTERRUPT CONTROL REGISTER’ındaki  GIE: Global Interrupt Enable bit’i  “1″ yapılmalıdır.
  7. INTCON – INTERRUPT CONTROL REGISTER’ındaki   T0IF: TMR0 Overflow Interrupt Flag bit’i “0″ yapılmalıdır.
  8. INTCON – INTERRUPT CONTROL REGISTER’ındaki  T0IE: TMR0 Overflow Interrupt Enable bit’i “1″ yapılmalıdır.

Buradan da görebileceğiniz gibi bizim diğer uygulamadan farklı olarak değiştireceğimiz iki register vardır. Birincisi OPTION REGISTER-T0CS(TMR0 Clock Source Select biti) , diğeri OPTION REGISTER-T0SE(TMR0 Source Edge Select) bitidir. Bunlardan birincisi Timer0 için saat kaynağını seçmek için kullanılır. Eğer biz bu biti 1 yaparsak Timer0 için RA4 pininden gelecek sinyali saat kaynağı olarak belirlemiş oluruz. T0SE biti ise timer0’ın bu sinyalin düşen kenarında mı yoksa yükselen kenarında mı sayma yapacağını belirlemek için kullanılır. 1 yaparsak düşen kenar, 0 yaparsak yükselen kenar seçilmiş olur.

Şimdi isterseniz sayıcımızı kurmaya geçelim. Mesela 4 kere bir butona bastığımızda PORTB’nin 0. pinine bağlı led yansın, eğer toplam 8 kere basarsak PORTB’nin 1. pinine bağlı ledde yansın, toplam tuşa basma sayımız 12 olursa ikisi birden sönsün. Hemen bunun uygulamasına geçelim. İstersek prescaler değerini 2 seçer, tuşa her iki defa bastığımızda Timer0’ın 1 saymasını sağlarız, ister prescaler değerini 4 seçer tuşa her 4 defa bastığımızda timer’ın 1 defa artmasını sağlayabiliriz. Bence prescaleri 4 yapmak daha mantıklı. O zaman öyle yapalım. Prescaler değerimizi dört yapmak için Option registerının son 3 bitini 001 olarak ayarlamamız gerekiyor. Yani şimdi butona 4 kez basınca Timer0 1 artacak. Prescalerin belirlediği tam olarak budur işte. Saat kaynağını bölme işlemi gerçekleştirir. Peki biz ne yapmak istiyorduk ? Butona 4 kez basınca bir kesme oluşturmak istiyorduk. O zaman butona 4 kez bastığımızda timer 1 artıyorsa , kesme oluşması için biz TMR0 registerına 255 yüklemeliyiz. Çünkü TMR0 içeriği 255’ten bir artmaya çalışınca kesme oluşuyor. O halde programımızı yazmaya başlayalım.

char i=0;
void interrupt()//kesme alt programı
{
if (INTCON.T0IF)//Timer0 Kesme bayrağı kontrol ediliyor.
{
i++;
TMR0=255;//Timer0 registerına 4 butona basışta bir kez kesme oluşturacak değer yükleniyor.
INTCON.T0IF=0;// Kesme bayrağı sıfırlanıyor.
}
}
//*****************************************************************************
void kurulum()
{
trisb=0;//PORTB çıkış
portb=0;//PORTB'nin tüm pinleri 0 seviyesinde.
OPTION_REG.T0CS=1;// Clock palsi kaynağı olarak dahili osilatör seçildi.
OPTION_REG.T0SE=0;// Butona basıldığında RA4 high seviyeye çekilecek.(yükselen kenar tetiklemesi)
OPTION_REG.PSA=0;//Prescaler değeri Timer0 için kullanılacak.
OPTION_REG.PS2=0;//Prescaler değeri 1:4 olarak seçildi.
OPTION_REG.PS1=0;
OPTION_REG.PS0=1;
INTCON.GIE=1;// tüm kesmelere izin verdik.
INTCON.T0IF=0;//Kesme bayrağını her ihtimale karşı sıfırladık
TMR0=255 ;//Timer0 registerına 4 butona basışta bir kez kesme oluşturacak değer yükleniyor.
INTCON.T0IE=1;//Timer0 kesmesini aktif ettik.
}
//*****************************************************************************
void main()
{
kurulum();
while(1)
{
switch (i)
{
case 1:  portb=0b00000001; break; //eğer i = 1'ise yani 4 kez butona basılıp 1 kesme oluşmuş ise;
case 2:  portb=0b00000011; break; //eğer i = 2'ise yani 8 kez butona basılıp 2 kesme oluşmuş ise;
case 3:  portb=0; i=0; break;   //eğer i = 3'ise yani 12 kez butona basılıp 3 kesme oluşmuş ise;
}
}
}

Devre şeması ise:

Şekilde görülmektedir. Buradaki buton ve direnç yapısına dikkat ederseniz, butona basıldığında RA4’e high seviyenin geldiğini görürsünüz. Yani yükselen kenar tetiklemesi yapmış oluruz. Buton ve direnç yer değiştirseydi u sefer düşen kenar tetiklemesi yapmış olacaktık. Yapıyı gerçekte denerken butona paralel 100nF kondansatör atmanızı tavsiye ederim. Çünkü butona basma anında oluşacak arkları uC sayma işleminde kullanabilir ve yanlış saymalara zemin hazırlanır.

Bu not ile ilgili dosyalara buradan ulaşabilirsiniz.

İyi çalışmalar.

yorum
  1. Alp dedi ki:

    hocam bu kodla 16f877a ile encoder dan değer alıp , 2×16 display de görebilirmiyiz.

  2. ahmet dedi ki:

    merhabalar,

    projemde şebeke gerilimindeki zero crossing dedectorden 0 noktalarını belirleyip. 100 hz lik frekans ile scr tetiklemek istiyorum. scr ye gecikmeyide potansiyometre kulanarak adc ile verdim.fakat gecikme kısmı çalışmadı. önerebileceğiniz farklı bie yöntem varmı?

  3. bekes adam dedi ki:

    Timer0 Sayıcı Modu şu aşağıda vereceğim kodları kullanarak deneme yaptım.Kodlardanda göreceğiniz gibi taşma bayrağını(INTCON.T0IF) kullansamda kesme yapmadan işi kotarmak istedim.(Çünkü işi yapacak grup kesmeyi henüz öğrenmedi)Ancak simülasyonda çalışmasına rağmen Board üzerindeki denememde hatalı çalışıyor yani 8 kez basıldığında bir LED’i yakmak istediğimde kimi zaman 5 kimi zaman 7 gibi bir sayma adedinde LED Yandı.(RA4 Düşen kenar tetiklemeli) sizce problem nedir?

    KODLAR:
    void kurulum()
    {
    trisb=0;//PORTB çıkış
    PORTB=0;//PORTB’nin tüm pinleri 0 seviyesinde.
    OPTION_REG.T0CS=1;// Clock palsi kaynağı olarak RA4 seçildi
    OPTION_REG.T0SE=1;// Butona basıldığında RA4 LOW seviyeye çekilecek.(DÜŞEN kenar tetiklemesi)
    OPTION_REG.PSA=0;//Prescaler değeri Timer0 için kullanılacak.
    OPTION_REG.PS2=0;//Prescaler değeri 1:8 olarak seçildi.
    OPTION_REG.PS1=1;
    OPTION_REG.PS0=0;
    TMR0=255 ;//Timer0 registerına 8 butona basışta bir kez kesme oluşturacak değer yükleniyor.
    }
    //*****************************************************************************
    void main()
    {
    kurulum();
    while(1)
    {
    if (INTCON.T0IF)//Timer0 TAŞTI MI?
    {
    PORTB=0XFF;
    Delay_ms(1000);
    PORTB=0;
    TMR0=255;//Timer0 registerına 8 butona basışta bir kez kesme oluşturacak değer yükleniyor.
    INTCON.T0IF=0;// Kesme bayrağı sıfırlanıyor.
    }

    }
    }

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s